OpenGL - 纹理使用 glDrawElements 映射不正确

OpenGL - texture are mapped incorrectly using glDrawElements

我正在创建一个 OBJ 解析器,它读取文件并使用 glDrawElements 绘制它。这里的问题是模型绘制正确,但是当我试图给它一个纹理时,它被错误地映射了。我已阅读 here that "OpenGL can only use one index buffer, whereas OBJ use one index buffer by attribute". I have also researched about the textures being incorrectly mapped when using glDrawElements and found out that I need to rearrange the textures because only vertices are shared but not the textures. Having said all of this, how should I suppose to rearrange the textures? Should I duplicate some textures? Please refer to this link 获得的样本输出。

我对OBJ不太熟悉,但是你说的是OBJ可以通过每个顶点的索引来引用不同的属性。你有一个大的 xyz 数组,另一个大的 uv 数组。然后每个顶点都有一个指向 xyz 数组的索引和另一个指向 uv 数组的索引。但是 opengl 每个顶点只有一个索引!所以如果 xyz 和 uv 索引不同,opengl 将无法工作。解决这个问题的一种简单方法是遍历所有顶点,如果它们的 uv 索引与 xyz 索引不同,只需将两者的数据复制到它们缓冲区的末尾并将索引设置为那个。

OBJ 格式指定了唯一的纹理坐标、顶点和面。

当然,Opengl 与 OBJ 无关,所以它想要的只是在正确位置的正确信息。

想象一下您的 OBJ 中有两个像这样的面(注意两个面中的顶点 1 纹理坐标)

f:    v1 |t1|     v2 t2      v3 t3 
f:    v1 |t2|     v4 t4      v5 t5 

你的 INDEX 缓冲区是这样的:

1 2 3     1 4 5

您的 opengl VERTEX 缓冲区首先如下所示:

v1 v2 v3 v4 v5

如果添加纹理坐标,添加到哪里?像这样?

v1 t1     v2 t2     v3 t3     v4 t4      v5 t5

这很可能是你现在拥有的,它是错误的,因为 opengl 制作的面孔是这样的:

f:    v1 |t1|      v2 t2      v3 t3 
f:    v1 |t1|      v4 t4      v5 t5 

因为 v1 和 t1 通过您的索引缓冲区链接在一起,请注意 OBJ 和 OpenGL 中的顶点之间的差异。

有几种方法可以解决这个问题。我建议摆脱索引缓冲区,因为它只会使一切复杂化。如果没有索引缓冲区,您只需提供所有面,就好像它们是唯一的一样,并使用不同的绘制调用 (glDrawArrays)。您的顶点缓冲区将如下所示:

v1 |t1|      v2 t2       v3 t3       v1 |t2|       v4 t4        v5 t5

您复制了 v1,但实际上大多数时候它并没有那么多额外数据,因为您不必再​​指定索引缓冲区。

这种东西想起来真烦人,我尽量写得平易近人,希望没有出错。