3个索引缓冲区

13

所以,在D3D和OpenGL中都有从索引缓冲区绘制的功能。

然而,OBJ文件格式做了一些奇怪的事情。它指定了一堆顶点,如:

v -21.499660 6.424470 4.069845
v -25.117170 6.418100 4.068025
v -21.663851 8.282170 4.069585
v -21.651890 6.420180 4.068675
v -25.128481 8.281520 4.069585

然后指定了一堆法向量,如:

vn 0.196004 0.558984 0.805680
vn -0.009523 0.210194 -0.977613
vn -0.147787 0.380832 -0.912757
vn 0.822108 0.567581 0.044617
vn 0.597037 0.057507 -0.800150
vn 0.809312 -0.045432 0.585619

然后指定了一堆纹理坐标,如:

vt 0.1225 0.5636
vt 0.6221 0.1111
vt 0.4865 0.8888
vt 0.2862 0.2586
vt 0.5865 0.2568
vt 0.1862 0.2166

然后在模型上指定了“面”:

f 1/2/5 2/3/7 8/2/6
f 5/9/7 6/3/8 5/2/1

在这里,我们v/t/n,第一个数字是顶点数组中的索引,第二个数字是纹理坐标数组中的索引,第三个数字是法线数组中的索引。

因此,在使用顶点缓冲区进行渲染时,

在OpenGL中,我可以使用glVertexPointerglNormalPointerglTexCoordPointer分别设置指向每个顶点、法线和纹理坐标数组的指针...但是当涉及到使用glDrawElements绘制时,我只能指定一个索引集,即它在访问顶点时应该使用的索引。

好吧,那接下来呢?我仍然有3组要访问的索引。

在d3d中,情况也差不多——我可以设置3个流:一个用于顶点,一个用于纹理坐标,一个用于法线,但是当涉及到使用IDirect3DDevice9::DrawIndexedPrimitive时,我仍然只能指定一个索引缓冲区,它将索引到顶点数组。

那么,使用每个顶点、纹理坐标和法线缓冲区的不同索引数组从顶点缓冲区绘制是可能的吗(无论是d3d还是opengl!),还是必须创建一个单一的交错数组,然后访问它?


可能是使用多个索引渲染网格的重复问题。 - Nicol Bolas
2个回答

8

OBJ不是为映射到OpenGL或DirectX而设计的。

你所说的一切都是正确的,而且不可能使用逐属性索引。

你必须将OBJ表示转换为仅使用每个顶点一个索引的内容(可能需要在此过程中复制一些顶点数据)。


所以,作为后续,我可以假设一个obj文件在中途不会切换顶点格式吗? - bobobobo
@bobobobo:嗯,我已经很久没有处理OBJ文件了,但是我记得有一些奇怪的情况,其中纹理只应用于模型的某些部分。因此,我认为只有部分顶点具有相应的纹理坐标。不过,这大约是10年前的事了,所以不要完全相信我。 - Bahbar
哈哈。你现在在处理什么? - bobobobo
@bobobobo:我的背景部分在另一边的围栏上,从事GL的实现。在那之前,我写过客户端代码。 - Bahbar
1
@ bobobobo 你不能假设它不会在中途切换顶点格式。事实上,去年夏天(2012年)使用Lightwave时,我导出了一个OBJ / MTL文件,它使用不同的f pos / tex / norm组合来指定不同面的顶点属性(尽管每个单独的面都具有一致的格式),所以也不要期望“新”OBJ文件的行为良好。 - GraphicsMuncher

2
你真正想做的事情(从D3D的角度来看,我不知道OpenGL,抱歉)是将OBJ加载到自定义顶点格式的数组中--这样你就有了一个包含索引、顶点、法线和纹理坐标的结构体,你可以使用一个DrawIndexedPrimtive渲染它。
我是否误解了你的问题定义?我认为你需要提供更多的细节--渲染单个OBJ文件不应该需要多个索引缓冲区(除非你是故意批处理)。如果是这种情况,即你故意批处理,那么你应该查看DrawIndexedPrimitive的参数,它允许你指定要使用的VB中的偏移量。

我需要多个索引缓冲区的原因是在面部规范中,顶点、法线和纹理坐标实际上是“以不同的速率”进行索引的。在 f 1/3/5 2/8/1 4/2/2 中,第一个顶点使用了顶点数组中的索引1,纹理数组中的索引3和法线数组中的索引5。 - bobobobo
是的 - 你需要将OBJ数据加载到自定义结构中,以便在D3D中正确渲染。这个过程的一部分需要复制顶点以正确引用面格式。根据您使用的版本,DirectX SDK中包含了一个示例。它可以在\Samples\C++\Direct3D10\MeshFromOBJ10中找到。 - Josh Atkins
@JoshuaAtkins 那是一个很好的地方看到实现,我因为懒惰用了几个for循环。 - Rashid Ellis

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接