Kom*_*ave 6 performance opengl-es vbo opengl-es-2.0
我在OpenGL ES 2.0中使用顶点缓冲对象(VBO).
我有一组顶点数据,它们永久存储在普通的RAM中.原因是从头开始计算顶点位置是昂贵的,但可以将delta添加到最后位置以便廉价地更新它.
要绘制的实际顶点数随时间快速变化.在一个帧中,我可能有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.
Run Code Online (Sandbox Code Playgroud)
然而,这打破了一个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, ...);
Run Code Online (Sandbox Code Playgroud)
但是,这种设置每帧需要更多的工作,并且正如您所看到的那样涉及更改VBO大小(因为它使用实际大小,而不是UPPER
),我被告知这是一个很大的性能消耗.
有人可以向我解释我的新设置中的任何明显问题,最重要的是我之前需要调用哪些命令glDrawElements
?我假设我可以提前准备所有可能的索引,然后传递实际的顶点数,glDrawElements
这显然是错误的.
要回答您在问题标题中提出的问题,没有"最有效"的缓冲区对象设置用于流式传输顶点数据.特别是ES 2.0,它涵盖了各种不同的硬件,每个硬件都有自己的特点.
要回答有关代码停止工作原因的问题,可能是因为您不尊重这些功能实际执行的操作.
例如,glUseProgram
使给定的程序对象成为任何后续程序对象glDraw*
调用将使用直到调用glUseProgram
一次.可以把大多数OpenGL函数想象成全球状态,因为它是如何工作的.glUseProgram
设置一个全局变量,glDraw*
读取以找出要使用的着色器.
因此,如果要确保特定绘制调用使用特定着色器,则必须glUseProgram
事先确定该着色器.或者至少在最近你知道你没有在其他地方改变它.通常,对象的呈现如下所示:
第一步使用glEnableVertexAttribArray
,glBindBuffer
和glVertexAttribPointer
.这些函数就像glUseProgram
设置全局状态一样.您应该在使用glDisableVertexAttribArray
对象渲染之后使用,并且应该取消绑定您可能已使用的任何缓冲区.