performance - OpenGL ES 2.0 : The most efficient setup for a VBO with GL_STREAM_DRAW?

标签 performance opengl-es opengl-es-2.0 vbo

我在 OpenGL ES 2.0 中使用顶点缓冲区对象 (VBO)。

我有一组永久存储在普通 RAM 中的顶点数据。原因是从头开始计算顶点位置的成本很高,但是可以在最后一个位置添加一个增量来廉价地更新它。

要绘制的实际顶点数会随着时间迅速变化。在一帧中我可能有 1000 个,在接下来的 2500 个中。根据之前收到的建议,我现在指定整数 UPPER作为将要绘制的顶点数的上限。我 malloc我的顶点和索引数据数组在启动时仅基于此值一次。

我通过 GL_STREAM_DRAW每个 glBindBuffer 的使用提示调用以指示每一帧的数据变化。

为了尽可能高效,我创建了以下设置:

// SETUP: Called only once.
glBindBuffer(GL_ARRAY_BUFFER,...);
glBufferData(GL_ARRAY_BUFFER,...); // Pass vertex data for UPPER vertices.
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,...);
glBufferData(GL_ELEMENT_ARRAY_BUFFER,...); // Pass index values 0 - (UPPER-1).
glEnableVertexAttribArray(...); // Setup vertex attributes.
glVertexAttribPointer(...);
glUseProgram(...); // Use program with custom shaders.
glUniformMatrix4fv(...); // Identify shader uniforms.

// UPDATE: Called when vertex data changes (on each frame).
glBindBuffer(GL_ARRAY_BUFFER,...);
glBufferSubData(GL_ARRAY_BUFFER,...); // Update VBO data.

// RENDER: Called on each frame.
glDrawElements(GL_TRIANGLES, numberOfVerticesThisFrame, ...); // Number of vertices and indices to be used is inherently specified in here.

然而,这与 EXC_BAD_ACCESS 中断。在 glDrawElements ,我知道这是由于我订购了 gl命令。

我之前有一个类似的设置,它有效:
// UPDATE: Called when vertex data changes (on each frame).
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,...);
glBufferData(GL_ELEMENT_ARRAY_BUFFER,...); // Pass index values 0 - (actual number of vertices to draw - 1)

// RENDER: Called on each frame.
glBindBuffer(GL_ARRAY_BUFFER,...);
glBufferData(GL_ARRAY_BUFFER,...); // Pass vertex data for actual number of vertices (not UPPER).
glEnableVertexAttribArray(...); // Setup vertex attributes.
glVertexAttribPointer(...);
glUseProgram(...); // Use program with custom shaders.
glUniformMatrix4fv(...); // Identify shader uniforms.
glDrawElements(GL_TRIANGLES, numberOfVerticesThisFrame, ...);

但是,此设置每帧需要更多的工作,并且如您所见,涉及更改 VBO 大小(因为它使用实际大小,而不是 UPPER ),我被告知这是一个很大的性能消耗。

有人可以向我解释一下我的新设置有什么明显的问题,最重要的是我使用了哪些命令 必须调用 glDrawElements 之前的每一帧?我的假设是我可以提前准备所有可能的索引,然后将实际顶点数传递给 glDrawElements显然是错误的。

最佳答案

要回答您在问题标题中提出的问题,对于流式顶点数据没有“最有效”的缓冲区对象设置。尤其是在 ES 2.0 上,它涵盖了广泛的不同硬件,每个都有自己的特点。

要回答有关您的代码为何停止工作的问题,很可能是因为您不尊重这些函数的实际作用。

例如,glUseProgram使给定的程序对象成为任何后续 glDraw* 的程序对象。在您调用 glUseProgram 之前,电话将一直使用再次。将大多数 OpenGL 函数视为在全局状态下进行操作,因为它就是这样工作的。 glUseProgram正在设置一个全局变量 glDraw*阅读以找出要使用的着色器。

因此,如果您想确保特定的绘制调用使用特定的着色器,那么您必须 glUseProgram事先立即使用该着色器。或者至少最近足够你知道你没有在其他地方改变它。通常,对象的渲染如下所示:

  • 建立渲染对象的顶点属性。
  • 设置当前程序,并更改任何每个对象的统一(矩阵等)。
  • 为程序绑定(bind)纹理(如果有)。
  • 绑定(bind)程序的其他状态,如果有的话。
  • 使成为。
  • 停用属性

  • 第一步使用glEnableVertexAttribArray , glBindBuffer , 和 glVertexAttribPointer .这些函数,就像 glUseProgram设置全局状态。您应该使用 glDisableVertexAttribArray在使用对象渲染后,您应该取消绑定(bind)您可能使用过的任何缓冲区。

    关于performance - OpenGL ES 2.0 : The most efficient setup for a VBO with GL_STREAM_DRAW?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7303000/

    相关文章:

    python - 使用索引以递归方式快速获取目录中的所有文件

    android - 使用 openGL ES 管理不同分辨率的手机

    iphone - 如何为 iPhone 应用程序创建一个带有兴趣点的旋转地球仪?

    android - fwidth() tegra 3 glsl

    sql-server - SQL Server 闩锁及其对性能问题的指示

    iphone - Cocos2d : usage of references vs getChild performance

    ios - 使用 GLKit 在 OpenGL 中的 glBlendFunc 透明度

    opengl-es - OpenGL ES 2.0 和 OpenGL ES 3.0 有什么区别

    javascript - 我可以将分析脚本放入 JavaScript 文件中吗

    iphone - 体系结构 i386 的 undefined symbol ,ld : symbol(s) not found for architecture i386