OpenGL -纹理使用glDrawElements被错误地映射

OpenGL - texture are mapped incorrectly using glDrawElements

本文关键字:错误 映射 glDrawElements 纹理 OpenGL      更新时间:2023-10-16

我正在创建一个OBJ解析器,它读取文件并使用glDrawElements绘制它。这里的事情是模型是正确绘制的,但当我试图给它一个纹理,它是不正确的映射。我在这里读到"OpenGL只能使用一个索引缓冲区,而OBJ通过属性使用一个索引缓冲区"。我还研究了纹理在使用glDrawElements时被错误映射,并发现我需要重新排列纹理,因为只有顶点是共享的,而不是纹理。说了这么多,我该如何重新排列纹理呢?我应该复制一些纹理吗?

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顶点缓冲区首先看起来像这样:

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通过indexbuffer链接在一起,请注意OBJ和OpenGL中的顶点之间的差异。

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

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

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

这种事情想起来真的很烦人,我尽力让它平易近人,我希望我没有犯任何错误。

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