OpenGL:在圆柱体周围包裹纹理
OpenGL: Wrapping texture around cylinder
我正在尝试向圆柱体添加纹理以很好地绘制石头。我从一个圆柱体开始,然后映射我发现 here 的石头纹理,但得到了一些奇怪的结果。这是我正在使用的函数:
void draw_well(double x, double y, double z,
double dx, double dy, double dz,
double th)
{
// Set specular color to white
float white[] = {1,1,1,1};
float black[] = {0,0,0,1};
glMaterialfv(GL_FRONT_AND_BACK,GL_SHININESS,shinyvec);
glMaterialfv(GL_FRONT_AND_BACK,GL_SPECULAR,white);
glMaterialfv(GL_FRONT_AND_BACK,GL_EMISSION,black);
glPushMatrix();
// Offset
glTranslated(x,y,z);
glRotated(th,0,1,0);
glScaled(dx,dy,dz);
// Enable textures
glEnable(GL_TEXTURE_2D);
glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE);
glBindTexture(GL_TEXTURE_2D,texture[0]); // Stone texture
glBegin(GL_QUAD_STRIP);
for (int i = 0; i <= 359; i++)
{
glNormal3d(Cos(i), 1, Sin(i));
glTexCoord2f(0,0); glVertex3f(Cos(i), -1, Sin(i));
glTexCoord2f(0,1); glVertex3f(Cos(i), 1, Sin(i));
glTexCoord2f(1,1); glVertex3f(Cos(i + 1), 1, Sin(i + 1));
glTexCoord2f(1,0); glVertex3f(Cos(i + 1), -1, Sin(i + 1));
}
glEnd();
glPopMatrix();
glDisable(GL_TEXTURE_2D);
}
// Later down in the display function
draw_well(0, 0, 0, 1, 1, 1, 0);
我收到的输出是
我对 OpenGL 和更具体的纹理仍然很陌生,所以我的理解非常有限。我在这里的思考过程是,我会将纹理映射到用于制作圆柱体的每个 QUAD
,但显然我做错了什么。任何关于导致此奇怪输出的原因以及如何修复它的解释将不胜感激。
您的绘制例程可能存在三个主要问题。 quad-strip 索引、纹理坐标重复太频繁以及三角函数可能不正确的使用;
三角函数 函数通常接受以弧度而非度数表示的角度值。仔细检查您使用的 Sin 和 Cos 函数的参数。
Quadstrip 索引不正确。索引应该是这样的...
注意四边形是如何以顺时针方式定义的,但是对角线顶点是按顺序定义的。您将四边形定义为 v0、v1、v3、v2 而不是 v0、v1、v2、v3,因此交换四个顶点的最后两个顶点。这也会导致另一个错误,即无法正确共享顶点。您正在沿每个垂直边复制它们,因为您在一个循环中绘制了相同的一组顶点 (i+1),就像您在下一个循环中所做的那样(即,因为 i 现在已递增 1)。
纹理坐标在每个四边形的 0、1 范围内,这意味着您正在定义一个被分割 360 次的圆柱体,并且该纹理围绕圆柱体重复 360 次.我假设纹理应该 1:1 映射到圆柱体而不是重复?
这是一些使用您提供的代码的示例代码。我已将段数减少到 64,如果您希望仍然有 360,请相应地修改 numberOfSegments
。
float pi = 3.141592654f;
unsigned int numberOfSegments = 64;
float angleIncrement = (2.0f * pi) / static_cast<float>(numberOfSegments);
float textureCoordinateIncrement = 1.0f / static_cast<float>(numberOfSegments);
glBegin(GL_QUAD_STRIP);
for (unsigned int i = 0; i <= numberOfSegments; ++i)
{
float c = cos(angleIncrement * i);
float s = sin(angleIncrement * i);
glTexCoord2f( textureCoordinateIncrement * i, 0); glVertex3f( c, -1.0f, s);
glTexCoord2f( textureCoordinateIncrement * i, 1.0f); glVertex3f( c, 1.0f, s);
}
glEnd();
N.BYou 正在使用旧版本的 OpenGL(使用 glBegin/glVertex 等)。
我正在尝试向圆柱体添加纹理以很好地绘制石头。我从一个圆柱体开始,然后映射我发现 here 的石头纹理,但得到了一些奇怪的结果。这是我正在使用的函数:
void draw_well(double x, double y, double z,
double dx, double dy, double dz,
double th)
{
// Set specular color to white
float white[] = {1,1,1,1};
float black[] = {0,0,0,1};
glMaterialfv(GL_FRONT_AND_BACK,GL_SHININESS,shinyvec);
glMaterialfv(GL_FRONT_AND_BACK,GL_SPECULAR,white);
glMaterialfv(GL_FRONT_AND_BACK,GL_EMISSION,black);
glPushMatrix();
// Offset
glTranslated(x,y,z);
glRotated(th,0,1,0);
glScaled(dx,dy,dz);
// Enable textures
glEnable(GL_TEXTURE_2D);
glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE);
glBindTexture(GL_TEXTURE_2D,texture[0]); // Stone texture
glBegin(GL_QUAD_STRIP);
for (int i = 0; i <= 359; i++)
{
glNormal3d(Cos(i), 1, Sin(i));
glTexCoord2f(0,0); glVertex3f(Cos(i), -1, Sin(i));
glTexCoord2f(0,1); glVertex3f(Cos(i), 1, Sin(i));
glTexCoord2f(1,1); glVertex3f(Cos(i + 1), 1, Sin(i + 1));
glTexCoord2f(1,0); glVertex3f(Cos(i + 1), -1, Sin(i + 1));
}
glEnd();
glPopMatrix();
glDisable(GL_TEXTURE_2D);
}
// Later down in the display function
draw_well(0, 0, 0, 1, 1, 1, 0);
我收到的输出是
我对 OpenGL 和更具体的纹理仍然很陌生,所以我的理解非常有限。我在这里的思考过程是,我会将纹理映射到用于制作圆柱体的每个 QUAD
,但显然我做错了什么。任何关于导致此奇怪输出的原因以及如何修复它的解释将不胜感激。
您的绘制例程可能存在三个主要问题。 quad-strip 索引、纹理坐标重复太频繁以及三角函数可能不正确的使用;
三角函数 函数通常接受以弧度而非度数表示的角度值。仔细检查您使用的 Sin 和 Cos 函数的参数。
Quadstrip 索引不正确。索引应该是这样的...
注意四边形是如何以顺时针方式定义的,但是对角线顶点是按顺序定义的。您将四边形定义为 v0、v1、v3、v2 而不是 v0、v1、v2、v3,因此交换四个顶点的最后两个顶点。这也会导致另一个错误,即无法正确共享顶点。您正在沿每个垂直边复制它们,因为您在一个循环中绘制了相同的一组顶点 (i+1),就像您在下一个循环中所做的那样(即,因为 i 现在已递增 1)。
纹理坐标在每个四边形的 0、1 范围内,这意味着您正在定义一个被分割 360 次的圆柱体,并且该纹理围绕圆柱体重复 360 次.我假设纹理应该 1:1 映射到圆柱体而不是重复?
这是一些使用您提供的代码的示例代码。我已将段数减少到 64,如果您希望仍然有 360,请相应地修改 numberOfSegments
。
float pi = 3.141592654f;
unsigned int numberOfSegments = 64;
float angleIncrement = (2.0f * pi) / static_cast<float>(numberOfSegments);
float textureCoordinateIncrement = 1.0f / static_cast<float>(numberOfSegments);
glBegin(GL_QUAD_STRIP);
for (unsigned int i = 0; i <= numberOfSegments; ++i)
{
float c = cos(angleIncrement * i);
float s = sin(angleIncrement * i);
glTexCoord2f( textureCoordinateIncrement * i, 0); glVertex3f( c, -1.0f, s);
glTexCoord2f( textureCoordinateIncrement * i, 1.0f); glVertex3f( c, 1.0f, s);
}
glEnd();
N.BYou 正在使用旧版本的 OpenGL(使用 glBegin/glVertex 等)。