如何在opengl中跨多个四边形平滑纹理

问题描述 投票:1回答:2

我正在尝试使用我找到并调整大小的木制位图来纹理木制桌子的模型,但是我遇到的问题是,当应用纹理时,构成桌子表面的每个四边形都清晰可见。如何让它看起来像一个光滑的纹理?

void Table::DrawTableTop()
{
    glPushMatrix();
    //draw tabletop

    glEnable(GL_TEXTURE_2D);
    glBindTexture(GL_TEXTURE_2D, texid);

    glBegin(GL_QUADS);
    glMaterialfv(GL_FRONT, GL_SPECULAR, static_cast<GLfloat*>(specular));
    glMaterialf(GL_FRONT, GL_SHININESS, static_cast<GLfloat>(shininess));

    float unitx = 1.0f / (float)(xsize * 2 + 1);
    float unity = 1.0f / (float)(zsize * 2 + 1);

    for (int i = -xsize; i <= xsize; i++)
    {
        for (int j = -zsize; j <= zsize; j++)
        {
            glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, static_cast<GLfloat*>(wDiffuse));
            //top
            glNormal3f(0.0f, 1.0f, 0.0f);
            if (tex) glTexCoord2f(unitx * static_cast<float>(i + 20 + 1), unity * static_cast<float>(j + 10));
            glVertex3f(scale[0] * static_cast<float>(i) + scale[0], 0, scale[2] * static_cast<float>(j) + scale[2]);
            if (tex) glTexCoord2f(unitx * static_cast<float>(i + 20 + 1), unity * static_cast<float>(j + 10 + 1));
            glVertex3f(scale[0] * static_cast<float>(i) + scale[0], 0, scale[2] * static_cast<float>(j));
            if (tex) glTexCoord2f(unitx * static_cast<float>(i + 20), unity * static_cast<float>(j + 10 + 1));
            glVertex3f(scale[0] * static_cast<float>(i), 0, scale[2] * static_cast<float>(j));
            if (tex) glTexCoord2f(unitx * static_cast<float>(i + 20 ), unity * static_cast<float>(j + 10));
            glVertex3f(scale[0] * static_cast<float>(i), 0, scale[2] * static_cast<float>(j) + scale[2]);
        }
    }

    glEnd();

    glBindTexture(GL_TEXTURE_2D, 0);
    glDisable(GL_TEXTURE_2D);

    glPopMatrix();

x大小和大小的值分别为20和10

我希望纹理看起来像是加载到一个大的四边形,但显然使用多个四边形来改善照明等。

这就是纹理图像的样子:

c++ opengl textures opengl-compat
2个回答
1
投票

瓷砖上的纹理沿y轴翻转。更改纹理坐标:

if (tex) 
    glTexCoord2f(
        unitx * static_cast<float>(i + 20 + 1),
        unity * static_cast<float>(j + 10 + 1));
glVertex3f(scale[0] * static_cast<float>(i) + scale[0], 0, scale[2] * static_cast<float>(j) + scale[2]);

if (tex) 
    glTexCoord2f(
        unitx * static_cast<float>(i + 20 + 1),
        unity * static_cast<float>(j + 10));
glVertex3f(scale[0] * static_cast<float>(i) + scale[0], 0, scale[2] * static_cast<float>(j));

if (tex)
    glTexCoord2f(
        unitx * static_cast<float>(i + 20),
        unity * static_cast<float>(j + 10));
glVertex3f(scale[0] * static_cast<float>(i), 0, scale[2] * static_cast<float>(j));

if (tex)
    glTexCoord2f(
        unitx * static_cast<float>(i + 20 ),
        unity * static_cast<float>(j + 10 + 1));
glVertex3f(scale[0] * static_cast<float>(i), 0, scale[2] * static_cast<float>(j) + scale[2]);

1
投票

你弄乱了第二个纹理坐标。当顶点位置具有j + 20时将其设置为+ scale[0],并且当顶点位置不具有j + 20 + 1时将其设置为+ scale[0]。因此,所有条带都是“倒置的”。

要修复它,请使用:

if (tex) glTexCoord2f(unitx * static_cast<float>(i + 20 + 1), unity * static_cast<float>(j + 10 + 1));
glVertex3f(scale[0] * static_cast<float>(i) + scale[0], 0, scale[2] * static_cast<float>(j) + scale[2]);
if (tex) glTexCoord2f(unitx * static_cast<float>(i + 20 + 1), unity * static_cast<float>(j + 10));
glVertex3f(scale[0] * static_cast<float>(i) + scale[0], 0, scale[2] * static_cast<float>(j));
if (tex) glTexCoord2f(unitx * static_cast<float>(i + 20), unity * static_cast<float>(j + 10));
glVertex3f(scale[0] * static_cast<float>(i), 0, scale[2] * static_cast<float>(j));
if (tex) glTexCoord2f(unitx * static_cast<float>(i + 20 ), unity * static_cast<float>(j + 10 + 1));
glVertex3f(scale[0] * static_cast<float>(i), 0, scale[2] * static_cast<float>(j) + scale[2]);

但是,更好的方法是提取顶点位置计算如下:

struct Vertex {
    float texcoord[2];
    float position[3];
};

Vertex vertex_at(float scale[3], float unitx, float unity, int i, int j)
{
    Vertex ret;
    ret.texcoord[0] = unitx*(i + 20);
    ret.texcoord[1] = unity*(j + 10);
    ret.position[0] = scale[0]*i;
    ret.position[1] = 0;
    ret.position[2] = scale[2]*j;
    return ret;
}

并使用它:

for (int i = -xsize; i <= xsize; i++)
{
    for (int j = -zsize; j <= zsize; j++)
    {
        glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, static_cast<GLfloat*>(wDiffuse));
        //top
        glNormal3f(0.0f, 1.0f, 0.0f);
        Vertex v[4] = {
            vertex_at(scale, unitx, unity, i + 1, j + 1),
            vertex_at(scale, unitx, unity, i + 1, j),
            vertex_at(scale, unitx, unity, i, j),
            vertex_at(scale, unitx, unity, i, j + 1),
        };
        for(int k = 0; k < 4; ++k) {
            if (tex) glTexCoord2fv(v[k].texcoord);
            glVertex3fv(v[k].position);
        }
    }
}

通过这种方式,可以更轻松地了解正在发生的事情,并且您距离使用VAO更近了一步:将所有这些qazxsw poi结构捆绑到一个缓冲区中并设置attrib指针。

© www.soinside.com 2019 - 2024. All rights reserved.