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

时间:2015-07-27 09:37:52

标签: c++ opengl textures wavefront

我正在创建一个OBJ解析器,它读取文件并使用glDrawElements绘制它。这里的事情是模型被正确绘制,但当我尝试给它一个纹理时,它被错误地映射。我已阅读here" OpenGL只能使用一个索引缓冲区,而OBJ使用一个索引缓冲区属性"。我还研究了使用glDrawElements时纹理被错误映射的情况,并发现我需要重新排列纹理,因为只有顶点是共享的而不是纹理。说完所有这些之后,我应该如何重新排列纹理?我应该复制一些纹理吗?有关我得到的示例输出,请参阅此link

2 个答案:

答案 0 :(得分:2)

OBJ格式指定UNIQUE纹理坐标,顶点和面。

当然,Opengl与OBJ无关,所以它只需要在正确的地方提供正确的信息。

想象一下你的OBJ中有两个这样的面孔(注意两个面上的顶点1个texcoords)

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 

因为你的indexbuffer将v1和t1链接在一起,所以注意OBJ和OpenGL中顶点之间的差异。

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

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

你复制了v1,但实际上它并不是大部分时间的额外数据,因为你不必再指定一个索引缓冲区了。

考虑到这种东西真的很烦人,我尽力让它变得平易近人,我希望我没有犯任何错误。

答案 1 :(得分:0)

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