【问题标题】:Adding texture to a plane made of vertices将纹理添加到由顶点组成的平面
【发布时间】:2013-02-06 22:44:39
【问题描述】:

我已经用这段代码在 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,但由于没有 UV 坐标,所以我已经停止了“在 OpenGL 中使用纹理”部分。

我知道我们必须导入纹理文件,在我的例子中是位图文件。
loader返回一个Glint,也就是textureID,是全局的吗?例如,如果我需要加载该纹理,我只需要使用给定的 ID 调用绑定纹理函数?

无论如何,我怎样才能将纹理应用到平面上?


编辑#1: 蚊子发布的示例中的纹理现在可以使用。
我发现我正在将纹理加载到类的构造函数中,我不应该这样做,因为该对象是公共的,并且它是在 OpenGL 初始化之前构造的。
所以纹理现在在四边形示例中加载良好:)

现在的问题是我尝试在我的飞机上使用它,但它看起来变形了。 解决这个问题的方法可能是让纹理加载多次,但保持原来的大小(虽然我不知道怎么做)

另外,我在当前平面旁边创建了另一个平面,颜色为奶油色,但经过纹理处理后,它看起来像这样:

所以现在有两个问题:

  • 纹理必须保持其原始分辨率,但显示的次数与覆盖整个平面一样多
  • 它旁边的飞机失去了颜色(为什么会发生这种情况?如何修复它?--我也可以为这架飞机使用纹理)

编辑#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);

【问题讨论】:

  • 我会给你我的标准“你知道你在使用旧的和不推荐使用的功能吗?这里是a better tutorial
  • @BartekBanachewicz:我使用的哪个功能已弃用?我正在使用这些来完成我的任务,这就是我们所学的。我会看你发布的教程,因为我看了一点,它看起来不错。但是我看到它使用的是一个框架,那是哪个?
  • 本教程不针对任何框架;可能只有一些窗口/上下文创建便利功能。至于实际不推荐使用的功能......实际上,您的代码的每一个功能。但是,如果这是一项任务,我知道根据我自己的经验可能很难更新。
  • @Chris 我刚刚根据您的新问题编辑了我的答案。请检查一下。
  • @BartekBanachewicz 您发布的链接指向一个已过期的域名...

标签: c++ opengl textures


【解决方案1】:

如果您有返回 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);

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


编辑

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

EDIT2

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

在中间的那些图片中,我用 red 颜色标记了纹理坐标,并用 black - 顶点坐标标记。

因此,基本上,如果您像现在一样设置纹理坐标(最大值为 1.0),那么您的纹理就会在平面周围拉伸。现在想象这个平面非常大——如果纹理分辨率低,它只会导致丑陋的拉伸效果。

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

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

【讨论】:

  • 感谢您的回答,我已经编译并运行了程序,但是在平面上看不到纹理。我生成的代码是凯文在他的答案中发布的代码。装载机可能有问题吗?这是我从教程中得到的代码:pastebin.com/pxe3GfzU
  • @Chris Loader 似乎很好,请使用我的四边形示例并检查纹理是否正在显示。如果没有,明天我们会尝试找出原因。
  • 我用过你的代码,它只是显示了一个白色的方形平面:/ glEnable(GL_TEXTURE_2D) 不应该被调用到opengl的设置函数中吗? (我一开始尝试过,然后在“glBindTexture”函数调用之前尝试过,仍然没有)。
  • 我已经完成了,它可以很好地加载到您的四边形示例中:) 但是我现在遇到了一些其他问题..我已经用 edit #1 更新了我的问题.
  • 再次感谢您的回复!第二个解决方案工作得很好(我想只在带有纹理的平面之后禁用纹理,但通常禁用纹理)。你提出的第一个没有用。如果您检查我在 pastebin 上发布的加载器,我已经在 glGenTextures() 之前添加了两行,但它看起来仍然相同。在此之下还有另外两行正在设置一些其他参数。我已将它们注释掉,但根本没有出现纹理。我该怎么办?
【解决方案2】:

您需要为每个顶点指定一个 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);

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

【讨论】:

  • 感谢您的回复,我已经做到了,但是现在还有一些其他的问题。我已经用 edit #1 更新了我的问题。
猜你喜欢
  • 2012-10-27
  • 1970-01-01
  • 2015-08-21
  • 2016-06-02
  • 1970-01-01
  • 1970-01-01
  • 2020-03-11
  • 1970-01-01
  • 2017-01-20
相关资源
最近更新 更多