OpenGL中的顶点缓冲区

4
我正在制作一个小型的3D图形游戏/演示,用于个人学习。我了解d3d9和相当多的d3d11知识,但目前对opengl知之甚少,因此我打算将实际的图形渲染抽象出来,这样我的场景图和所有“上层”内容都不需要太了解如何绘制图形。我打算先让它与d3d9配合工作,然后添加d3d11支持,最后再添加opengl支持。这只是为了学习3D图形和抽象而进行的练习。
但我现在对opengl并不了解,也不想让我的抽象接口暴露任何在opengl中难以实现的东西。具体来说,我正在研究顶点缓冲区。在d3d中,它们本质上是一组结构体数组,但是看看opengl接口,等价物似乎是顶点数组。然而,这些似乎有所不同,你需要为顶点、法线、纹理坐标等分别设置一个单独的数组,并使用glVertexPointer、glTexCoordPointer等指针来设置。
我希望能够实现类似于directx的VertexBuffer接口,但看起来在d3d中,你有一个结构体数组,在opengl中你需要为每个元素单独设置一个数组,这使得找到一个通用的抽象变得非常困难,而且效率也不高。
有没有办法以类似于directx的方式使用opengl?或者有没有关于如何设计一个高级抽象来有效地与两个系统配合工作的建议?
1个回答

3

顶点数组具有步幅和偏移属性,这是专门为结构体数组而设计的。

因此,如果您想设置一个包含float3顶点和float2纹理坐标的VBO,您需要执行以下操作:

// on creation of the buffer
typedef struct { GLfloat vert[3]; GLfloat texcoord[2]; } PackedVertex;
glBindBuffer(GL_ARRAY_BUFFER, vboname);
glBufferData(...); // fill vboname with array of PackedVertex data

// on using the buffer
glBindBuffer(GL_ARRAY_BUFFER, vboname);
glVertexPointer(3, GL_FLOAT, sizeof(PackedVertex), BUFFER_OFFSET(0)));
glTexCoordPointer(2, GL_FLOAT, sizeof(PackedVertex), BUFFER_OFFSET(offsetof(PackedVertex, texcoord));

使用BUFFER_OFFSET宏将偏移量转换为相应的指针(vbos使用指针参数作为偏移量),并使用另一个名为offsetof的宏在PackedVertex结构中查找texcoord的偏移量。这里,由于结构体内部不太可能存在填充,所以很可能是sizeof(float)*3。


啊,好的,那很有道理。你仍然需要调用不同的函数来设置不同的属性,但我应该仍然能够与d3d共享一个结构。嗯,我真的需要学习更多关于OpenGL的知识 :) - jcoder
@JB,实际上,如果您选择GL3.0版本,它会引入顶点数组对象(vertex array objects),将整个东西封装起来。http://www.opengl.org/registry/specs/ARB/vertex_array_object.txt - Bahbar
避免使用gl..Pointer,就像避开瘟疫一样。改用glVertexAttribPointer。此外,如果可能的话,请避免交错数据(步幅)。最好将单个顶点属性按顺序保存在一个缓冲对象中。记得通过对齐数据缓冲区来让GPU更加愉快。 - Mads Elvheim
@Mads Elvheim:为什么?因为它们在GL3中被弃用了吗?我不知道GL JB使用的是什么。它们并不会更慢,而且更具表现力。但是,它们确实已经被弃用了。此外,关于交错,我可以告诉你,它确实可以使某些平台上的渲染速度更快。主要是顶点获取的缓存行为更好。另外,_那_才是最初的问题。 - Bahbar
1
抱歉,我应该表述得更清楚。在我看来,强制每个顶点数据都是特定的,会限制着你使用着色器所能表达的内容。我想分享一下我的观点。此外,在某些嵌入式平台上(通常是OpenGL ES),交错顶点数据速度很快,但在桌面PC上的OpenGL上则不然。 - Mads Elvheim

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