vbo 只拥有相同大小的顶点?

Posted

技术标签:

【中文标题】vbo 只拥有相同大小的顶点?【英文标题】:vbo holds only same size vertex? 【发布时间】:2011-06-13 11:25:00 【问题描述】:

OpenGL/OpenGLES VBO 是否只保存相同大小的顶点?

我问是因为我发现 glDrawElements 的参数只有索引缓冲区的偏移值(它的最后一个参数),这意味着: 1. 如果缓冲区已经部分填满,我必须在将它们提交给 IBO 之前手动抵消我的指数。无论如何,手动偏移索引很容易,所以这里不是问题。 2.用作顶点缓冲区的VBO必须拥有相同大小的顶点,否则索引无意义。

这种行为与DirectX Vertex Buffer不同,在directx中,有一个SetStreamSource,可以用来偏移Verterx Buffer,还有DrawIndexedPrimitive,你的VB可以保存任意大小的顶点。

也许 OpenGLES 1.1 版本的 SetStreamSource 不可用?也许 OpenGLES 2.0 会支持它?

我的目标平台是 iPhone OpenGLES 1.1,所以如果 GL 版本 SetStreamSource 不可用,我将放弃使用 VBO,因为: 1.它带来了更多的麻烦(我将不得不分配许多持有不同大小顶点的VBO) 2. 无论如何都没有性能提升(OpenGLES 1.1 没有硬件支持)

感谢您的阅读,非常感谢您分享有关在 OpenGLES 1.1 中正确使用 VBO 的经验。谢谢。

【问题讨论】:

“相同大小的顶点”你是怎么理解的? 【参考方案1】:

OpenGL 缓冲区对象(VBO 是一种使用模式)可以包含任意信息。但是绘图函数(如glDrawElements)处理相同格式的顶点信息的连续数组(显然,每个顶点占用相同的大小)。如果这就是您要询问的尺寸 - 那么我看不出它可以如何改变。

如果您想使用特定偏移量的 VBO(例如,包含不同格式的顶点),那么您可以使用最后一个参数 glVertexAttribPointer。绑定VBO时,最后这个参数是用于顶点属性的数据段的字节偏移量。

【讨论】:

感谢 kvark,我一看到您的“glVertexAttribPointer”就知道如何解决我的问题,它非常有启发性(实际上在我的情况下应该是“glVertexPointer”),我用过该功能很多次,不幸的是,当我茫然地看着“glDrawElements”时,我完全忘记了它。谢谢。【参考方案2】:

当您说您有不同大小的顶点时,我不确定我是否完全理解您的意思。但是 OpenGL 可以处理 D3D 可以处理的任何顶点格式。

OpenGL 没有的是顶点“流”的概念。那是因为它不需要它们;将每个单独的属性(位置、法线、颜色等)视为一个单独的流。但它们都可以来自同一个缓冲区,并且它们都可以相互交织。

缓冲区对象的工作方式非常简单。缓冲区对象只是由 OpenGL 控制的一块大小的内存。您可以在其中放入您想要的任何字节。

要告诉 OpenGL 如何从中获取顶点数据,您必须定义许多数组,每个数组都与一个属性相关联。用于此的函数是 glVertexPointer、glNormalPointer 等;它们都是 gl*Pointer 的形式。你似乎已经掌握了这么多。

你可能不明白的是,这些函数定义的顶点格式并不是与缓冲区对象永久关联的。例如,您可以使用带有字节颜色的 3D 位置,所有这些都来自同一个缓冲区对象:

glBindBuffer(GL_ARRAY_BUFFER, bufferObject);
glEnableClientState(GL_VERTEX_ARRAY);   //Our vertices contain positions.
glVertexPointer(3, GL_FLOAT, 16, (void*)0);  //The last parameter is the byte offset from the beginning of the buffer to where the data starts.
glEnableClientState(GL_COLOR_ARRAY);    //Our vertices contain colors.
glColorPointer(4, GL_UNSIGNED_BYTE, 16, (void*)12); //Offset must add in the 3 floats from the vertex.
//Draw stuff.

然后,您可以重新定义此指针,根据需要更改格式。这一次,我们使用 2D 位置,定义为短裤,完全没有颜色:

glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(2, GL_SHORT, 4, (void*)1024);
glDisableClientState(GL_COLOR_ARRAY);  //Our vertices contain no colors.
//Draw stuff.

在这些调用之间缓冲区绑定没有改变。这个新数组从缓冲区的开头开始 1024 个字节。因此,您可以将多个对象的数据放在同一个缓冲区中。

现在,OpenGL ES 1.1 没有提供 D3D 提供的一件事。当您调用 DrawIndexedPrimitives 时,您可以在从数组中获取顶点之前提供一个添加到每个索引的偏移量。桌面 OpenGL 3.2 及更高版本提供此功能(以及通过扩展的更低版本),但 ES 1.1 不提供。

【讨论】:

我认为魔术数字只是为了说明目的?真正的代码应该使用sizeofoffsetof 感谢 Nicol Bolas 和详细的解释。您对“缓冲区对象的工作方式非常简单”是正确的:P。我已经使用 glVertexPointer 解决了我的问题,不知道为什么当我发布我的问题时我完全忘记了它,我的错。再次感谢您,祝您有愉快的一天。

以上是关于vbo 只拥有相同大小的顶点?的主要内容,如果未能解决你的问题,请参考以下文章

配置VAO和VBO时,顶点数据数组是不是应该使用相同的方法? (OpenGL)[重复]

我应该使用相同的 VBO 来传递不同的顶点属性吗?还是我应该使用 2?

OpenGL顶点数组对象不记录VBO和IBO绑定

在 Vbo 中显示具有不同点大小的网格?

使用 VBO 在 OpenGL 中渲染人群

OpenGL 顶点数组对象是存储顶点缓冲区名称和索引,还是只存储索引?