Kom*_*ave 9 optimization opengl-es vbo opengl-es-2.0
在我不断尝试从ES 1.x转换为OpenGL ES 2.0时,我正在转换一些代码以使用Vertex Buffer Objects('VBOs')而不是现有的无缓冲glDrawArrays调用.
我已经建立了VBO并使它们正常工作,但是已经遇到了设计难题,并且会对那些对OpenGL ES 2.0更有经验的人的建议表示感谢.
我想绘制一堆经常移动的多边形精灵.这是因为如果你熟悉Box2D,它们就是动态的Box2D机构.这些多边形体都是使用GL_TRIANGLE_FAN生成的,这有点关键,因为GL_POLYGON在ES 2.0上不可用.
多边形具有其他属性,例如颜色,可以在应用程序生命周期的某个阶段更改,但它是保证几乎每帧都会改变的顶点位置.
多边形在游戏中分组,因此我打算管理和绘制每个组而不是每个主体的交错顶点/颜色数组,以尽量减少GPU通信.
这里有很多成功的途径,我一直在阅读OpenGL ES 2.0编程指南,以寻求尽可能多的关于VBO的信息和优化技巧,以及他们所说的内容:
交错数据是有利的,因为"每个顶点的属性数据可以按顺序方式读取".
本书建议"如果需要修改顶点属性数据的子集,则可以...在单独的缓冲区中存储本质上是动态的顶点属性".
建议"尽可能使用GL_HALF_FLOAT_OES",尤其是颜色,因为未经投影的顶点位置可能超出此空间要求.
只有在更新整个缓冲区时才应使用glMapBufferOES,即使在这种情况下,操作"与glBufferData相比仍然可能很昂贵".
这是我的问题:
如果使用GL_TRIANGLE_FAN作为绘图模式,这是否会强制我存储每个体的VBO而不是每个组?或者,为了"结束"风扇和当前体的常见顶点位置,是否会为组VBO中的下一个体绘制新的风扇?
尽管顶点位置以高频率更新,我应该交错我的所有数据,还是应该将所有数据/只是位置分成自己的VBO?
按照上面的书籍建议,大概每次更新渲染时我都应该glBufferData我的顶点位置,而不是使用glMapBufferOES或glBufferSubData更新缓冲位置?
是否有任何未提及的功能/设计选择我应该用于提高多动态多边形背景下的性能?
我是否应该尝试使用GL_HALF_FLOAT_OES进行颜色存储,即在2个浮点数的空间中,我会存储4个半浮点数?如果答案为"是",我是否只使用GLfloat大小为每种颜色一半的GL类型,然后按位OR,然后插入适当的属性数组?
有一次,我已经创建了X许多维也纳组织,都是我需要为每个渲染glBindBuffer,glBufferData和glDrawElements /阵列的唯一呼叫,或者我也必须调用glEnableVertexAttribArray和glVertexAttribPointer每次使用glBufferData时间?
我非常感谢您对此提出进一步的建议,谢谢.
Chr*_*ica 14
我没有任何ES经验,但我认为很多事情仍然适用
部分地,它不会强迫你每个身体使用一个VBO,但你必须glDrawArrays
每个身体做一个.这些可能仍然从同一缓冲区中获取数据,但仍然不可取.相反,我会远离复杂的基元,如三角形扇形或条带,并使用索引三角形列表,这样一切都可以在一次调用中绘制.我怀疑ES支持primitve_restart扩展.有了这个,你可以指定一个特殊的顶点索引来重启primitve.
如果你有许多其他的静态属性,那么将顶点位置分隔到它们自己的缓冲区(当然有GL_DYNAMIC_DRAW
甚至GL_STREAM_DRAW
使用)是个好主意.但是,如果你只有额外的4ub颜色或类似的东西,那么额外的复制成本可能不会那么糟糕,你可能更好地从交错中获利,需要进行测试.
如果你每一帧都更新它们,那么一个完整的glBufferData
可能比一个更好glBufferSubData
.或者您也可以调用glBufferData(..., NULL)
,然后glMapBuffer(..., GL_WRITE_ONLY)
如果您不想为数据保存CPU阵列.这告诉驱动程序您不再关心以前的数据了.这样,驱动程序可以为您分配一个全新的缓冲区,而之前的数据仍然用于渲染.因此,您可以在旧数据库仍处于使用状态时上传新数据(旧的缓冲区在不再使用时由驱动程序释放).
占位
因为颜色GL_UNSIGNED_BYTE
可能更好,因为这些通常不需要那么高的精度.当你有3个浮点坐标和4个字节颜色通道时,这也可能适用于对齐优化,这使得一个16字节的顶点非常对齐.在这种情况下,建议将顶点和颜色保留在同一缓冲区中.
编辑:在第3点澄清一点:如果你有数据在CPU阵列中,那么你可以调用glBufferData
你的数据.如果您希望驱动程序为您分配该存储,您可以使用glMapBuffer
,它为您提供指向映射到CPU地址空间的缓冲区内存的指针(当然GL_WRITE_ONLY
,您不必关心以前的数据).但在这种情况下glBufferData
,使用空指针将为缓冲区分配全新的存储空间(不复制任何数据),告诉驱动程序,我们不关心以前的内容(即使它们当前仍可用于渲染).驱动程序可以优化这种情况并在引擎盖下分配新存储,但仍然不会释放先前的存储,然后在最终不再使用先前的数据进行渲染时释放该存储.但请记住,您不会创建另一个缓冲区,它只是在驱动程序的引擎盖下.因此,当您想要更新整个缓冲区时,您可以这样做
updateData(dataArray);
glBufferData(GL_ARRAY_BUFFER, size, dataArray, usage);
Run Code Online (Sandbox Code Playgroud)
如果你有自己的CPU阵列中的数据,或者
glBufferData(GL_ARRAY_BUFFER, size, NULL, usage);
dataArray = glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY);
updateData(dataArray);
glUnmapBuffer(GL_ARRAY_BUFFER);
Run Code Online (Sandbox Code Playgroud)
如果您不需要您的CPU副本并希望驱动程序能够处理.但是如果在整个应用程序期间逐步更新数据,那么第一个解决方案可能会更好,因为只要映射它就不能使用缓冲区进行渲染,并且您应该只在短时间内映射缓冲区.
归档时间: |
|
查看次数: |
6301 次 |
最近记录: |