我使用以下代码在OpenGL上创建了一个平面:
glBegin(GL_TRIANGLE_STRIP);
glColor4f(0.8, 0.8, 0.5, 1.0);
glVertex3f(startlen, height, startwid);
glVertex3f(startlen, height, startwid + width);
glVertex3f(startlen + length, height, startwid);
glVertex3f(startlen + length, height, startwid + width);
glEnd();
现在我想将纹理应用于此平面。
我已阅读本教程here,但我已停止使用“在OpenGL中使用纹理”部分,因为我没有UV坐标。
我知道我们必须导入纹理文件,在我的例子中是一个位图文件 加载器返回一个Glint,它是textureID,是全局的吗?在示例中,如果我需要加载该纹理,我只需要使用给定的ID调用绑定纹理函数?
无论如何,我怎样才能将纹理应用到平面上?
编辑#1: 发布的示例蚊子的纹理现在可以使用了 我发现的是我将纹理加载到类的构造函数中,我不应该因为该对象是公共的而且是在OpenGL初始化之前构造的。 所以现在纹理在四边形示例中加载得很好:)
现在的问题是我试图在我的飞机上使用它,它看起来很扭曲。 对此的解决方案可能是将纹理加载多次,但保持原始大小(虽然我不知道如何做)。
另外,我在当前的一个平面旁边创建了一个奶油色的飞机,但是在纹理化之后它似乎是这样的:
现在有2个问题:
编辑#2:
第二个问题现在已经解决,感谢蚊子! 但是平铺仍然不起作用。 这就是它现在的样子:
这就是我用过的纹理:
它的尺寸是256x256(我用图像编辑器裁剪它)
编辑#3:
这些是glTexCoord2f坐标及其匹配的顶点(对于内边距):
glTexCoord2f(0.0f, 0.0f); glVertex3f(startlen, height, startwid);
glTexCoord2f(0.0f, 1.0f); glVertex3f(startlen, height, startwid - width/2);
glTexCoord2f(1.0f, 0.0f); glVertex3f(startlen + length, height, startwid);
glTexCoord2f(1.0f, 1.0f); glVertex3f(startlen + length, height, startwid - width/2);
答案 0 :(得分:10)
如果你有装载器返回textureID,那么它可能已经负责加载图像数据,设置属性并将其存储为真实纹理以供进一步使用。所以我将继续将纹理绑定到纹理目标。
如果您有此ID,则在绘制三角形条之前,您基本上必须调用glBindTexture()
函数:
glBindTexture(GL_TEXTURE_2D, id); // where id is GLuint returned by your loader
现在对于您绘制的每个顶点,您还应该为这些顶点指定纹理坐标。为此,您使用glTexCoord2f()
功能。对于简单的四边形,它可能如下所示:
glBegin(GL_QUADS);
// Bottom left
glTexCoord2f(0.0f, 1.0f);
glVertex2i(0.0f, 10.0f);
// Top left
glTexCoord2f(0.0f, 0.0f);
glVertex2i(0.0f, 0.0f);
// Top right
glTexCoord2f(1.0f, 0.0f);
glVertex2i(10.0f, 0.0f);
// Bottom right
glTexCoord2f(1.0f, 1.0f);
glVertex2i(10.0f, 10.0f);
glEnd();
如您所见,每个顶点都附有纹理“点”。它会告诉OpenGL如何显示纹理。
现在由您决定如何通过指定顶点的正确坐标来选择纹理在平面上的分布。
您必须记住的是纹理坐标以0.0开头并以1.0结尾。将此值增加到大于1.0将导致行为取决于纹理的设置(例如平铺)。
在你的教程中,你有非常好的图片,表明纹理坐标从0.0到1.0范围,以及为特定顶点设置的纹理坐标:
PS。为了显示纹理,您必须首先调用:
来启用此功能glEnable(GL_TEXTURE_2D);
每次使用纹理绘制对象时都不必调用它。在绘图之前可能只调用一次。
修改强>
根据你的下一个问题:你想要的是实现平铺 效果,可以在创建纹理时轻松完成。 在您的装载机中,在此行之后:
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
你应该设置下一个纹理参数:
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
在这种情况下,GL_REPEAT
被用于重复纹理
它的坐标高于1.0。例如,如果您指定
纹理坐标为2.0,它与你放置的1.0相同,等等
上。
你的第二个问题是因为你还有你的纹理绑定
并且你启用了纹理(记住你使用过
glEnable(GL_TEXTURE_2D);
),基本上你现在绘制的所有内容,
将覆盖纹理。
但是,如果您现在想要绘制一些没有纹理的东西,那么 在绘制第二架飞机之前,基本上必须禁用纹理 并在绘制后再次启用它:
glDisable(GL_TEXTURE_2D);
// Draw your second plane here
glEnable(GL_TEXTURE_2D);
<强> EDIT2 强>
嗯,我觉得你误会了我一点。在这种情况下,平铺无法工作,因为您指定纹理坐标最大为1.0,这是纹理的结束。我准备了一张图片,可以告诉你我的意思:
在中间带有红色颜色的照片中,我标记了纹理坐标,并使用黑色 - 顶点坐标。
所以基本上如果你像现在这样设置你的纹理坐标(最大值为1.0),你可以让你的纹理在你的平面上伸展。现在想象一下这个平面非常大 - 如果纹理分辨率低,它只会造成丑陋的拉伸效果。
为了实现平铺效果,你必须设置高于1.0的值,就像在我的例子中一样 - 2.0导致纹理重复两次。
由于没有神奇的方法可以让你的纹理在飞机上看起来很“漂亮”,你必须使用一些数学来实现它。现在我留给你。
答案 1 :(得分:1)
您需要为每个顶点指定一个uv坐标。您可以使用函数glTexCoord2f();
执行此操作
该函数有两个参数,第一个是你,另一个是v。你的绘图代码会变成这个:
glBegin(GL_TRIANGLE_STRIP);
glColor4f(0.8, 0.8, 0.5, 1.0);
glTexCoord2f(0.0f, 0.0f); glVertex3f(startlen, height, startwid);
glTexCoord2f(0.0f, 1.0f); glVertex3f(startlen, height, startwid + width);
glTexCoord2f(1.0f, 1.0f); glVertex3f(startlen + length, height, startwid);
glTexCoord2f(1.0f, 0.0f); glVertex3f(startlen + length, height, startwid + width);
glEnd();
您可能会稍微切换一下,我不知道您希望如何将纹理映射到它。您可以在纹理上看到u为x,其中0.0 =左,1.0 =右,您可以在纹理上看到v为y,其中0.0 =顶部,1.0 =底部。
现在,还有一些你需要的东西,首先,需要启用纹理:
glEnable(GL_TEXTURE_2D); //call this once, during initialization
需要加载纹理,就像你已经说过的那样:
glGenTextures(1, &MyTexture);
glBindTexture(GL_TEXTURE_2D, MyTexture);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data); //data is a gluByte array of your image data
在绘制四边形之前必须绑定它:
glBindTexture(GL_TEXTURE_2D, MyTexture);
我会让纹理的实际加载到你这里,因为这将是一个完全不同的问题,并在此广泛讨论。