1

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

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();

xsize 和 zsize 的值分别为 20 和 10

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

这是纹理图像的样子:

4

2 回答 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 更近了一步:只需将所有这些Vertex结构捆绑到一个缓冲区中并设置属性指针。

于 2019-05-01T21:21:40.857 回答
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]);
于 2019-05-01T21:21:49.203 回答