6

我用以下代码在 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();

现在我想在这个平面上应用纹理。

我在这里阅读了本教程,但我在“在 OpenGL 中使用纹理”部分停了下来,因为我没有 UV 坐标。

我知道我们必须导入纹理文件,在我的例子中是位图文件。
loader返回一个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);
4

2 回答 2

11

如果您有返回 textureID 的加载器,那么它可能已经负责加载图像数据、设置属性并将其存储为真实纹理以供进一步使用。因此,我将继续将纹理绑定到您的纹理目标。

glBindTexture()如果你有这个 id,你基本上必须在绘制三角带之前调用函数:

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

您不必每次使用纹理绘制对象时都调用它。它可能在您绘图之前只调用一次。


编辑

  1. 根据您的下一个问题:您想要的是实现平铺效果,这可以在创建纹理时轻松完成。在您的加载程序中,在此行之后:

    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 相同,依此类推。

  2. 您的第二个问题存在,因为您仍然有纹理绑定并且您启用了纹理(记住您使用过 glEnable(GL_TEXTURE_2D);),所以基本上您现在绘制的所有内容都将被纹理覆盖。

    但是,如果您现在想在不对其进行纹理化的情况下绘制某些东西,则基本上必须在绘制第二个平面之前禁用纹理化,并在绘制后再次启用它:

    glDisable(GL_TEXTURE_2D);
       // Draw your second plane here
    glEnable(GL_TEXTURE_2D);
    

编辑2

好吧,我想你误解了我一点。在这种情况下,平铺无法工作,因为您将纹理坐标指定为最大值 1.0,这是纹理的结尾。我准备了一张图片,可以向您展示我的意思:

在此处输入图像描述

在中间那些红色的图片中,我标记了纹理坐标和黑色- 顶点坐标。

所以基本上如果你像现在这样设置你的纹理坐标(最大值为 1.0),你会让你的纹理围绕你的平面拉伸。现在想象这个平面非常大——如果纹理分辨率低,它只会导致丑陋的拉伸效果。

为了达到平铺效果,您必须将值设置为高于 1.0,就像在我的示例中一样 - 2.0 会导致纹理重复两次。

由于没有神奇的方法可以让您的纹理在您的平面上看起来“漂亮”,因此您必须使用一些数学来实现它。现在我把这个留给你。

于 2013-02-06T23:06:10.803 回答
1

您需要为每个顶点指定一个 uv 坐标。您使用函数执行此操作,该glTexCoord2f();
函数接受两个参数,第一个是 u,另一个是 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);

我会让纹理的实际加载由你决定,因为这将是一个完全不同的问题,并且需要在这里广泛讨论。

于 2013-02-06T23:12:24.060 回答