如何在 opengl 中跨多个四边形平滑纹理
How to smooth texture across multiple quads in opengl
我正在尝试使用我找到并调整大小的木头位图为木头模型 table 制作纹理,但是我遇到的问题是每个四边形构成了 table 在应用纹理时清晰可见。我如何让它看起来像一个光滑的纹理?
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
我希望纹理看起来像是加载到一个大四边形上,但显然使用多个四边形来改善照明等。
纹理图像是这样的:
你弄乱了第二个纹理坐标。当顶点位置有+ scale[0]
时设置为j + 20
,当顶点位置没有+ scale[0]
时设置为j + 20 + 1
。结果你所有的条带都是 'inverted'.
要修复它,请使用:
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
结构捆绑到一个缓冲区中并设置属性指针。
瓷砖上的纹理沿 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]);
我正在尝试使用我找到并调整大小的木头位图为木头模型 table 制作纹理,但是我遇到的问题是每个四边形构成了 table 在应用纹理时清晰可见。我如何让它看起来像一个光滑的纹理?
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
我希望纹理看起来像是加载到一个大四边形上,但显然使用多个四边形来改善照明等。
纹理图像是这样的:
你弄乱了第二个纹理坐标。当顶点位置有+ scale[0]
时设置为j + 20
,当顶点位置没有+ scale[0]
时设置为j + 20 + 1
。结果你所有的条带都是 'inverted'.
要修复它,请使用:
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
结构捆绑到一个缓冲区中并设置属性指针。
瓷砖上的纹理沿 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]);