在 OpenGL ES 2 中实现 VBO 以渲染精灵
Posted
技术标签:
【中文标题】在 OpenGL ES 2 中实现 VBO 以渲染精灵【英文标题】:Implementing VBOs to render sprites in OpenGL ES 2 【发布时间】:2012-12-14 15:09:08 【问题描述】:我正在尝试实现 VBO 以提高 OpenGL 中的渲染速度,虽然我了解整体概念,但我不确定如何在带有精灵的 2D 中实现。我发现的所有实现似乎都是用于绘制所有顶点相对于彼此固定的 3D 模型。然而,在 2D 游戏中,每个精灵都有自己的位置,因此也有自己的 MVP 矩阵。
看起来是怎么做的:
Basic vertex shader:
"uniform mat4 uMVPMatrix; \n" +
"attribute vec4 vPosition;" +
"attribute vec2 texCoord;" +
"varying vec2 vTexCoord;" +
"void main() " +
// matrix must be included as part of gl_Position
" gl_Position = uMVPMatrix * vPosition;" +
" vTexCoord = texCoord;" +
"";
Drawing with VBOs (pseudocode)
1. Bind vertex/texture buffers
2. Load MVP matrix with glUniformMatrix4fv
3. Call glDrawArrays/glDrawElements to draw the all the vertices in one call
有没有一种简单的方法来扩展上述方法以允许不断变化的 MVP?
两种可能的想法:
将顶点加载到 VBO 中,但绘制每个精灵,加载每个精灵的 MVP 矩阵,如上。唯一的节省是您不必每次都传入顶点数据,但您仍然需要调用 glVertexAttribPointer 来索引每个精灵在 VBO 中的正确位置。我想速度节省将是微乎其微的。
不要将 MVP 矩阵作为统一矩阵,而是将其定义为属性。将每个精灵的所有 MVP 连接到一个大数组中,并使用 glVertexAttribPointer 加载它。似乎不可能使用 glVertexAttribPointer 一次加载一个矩阵(你最多可以加载一个 vec4),所以我必须用 4 次连续调用逐列加载它。然后我应该能够独立地转换每个精灵。与我当前的实现相比,速度应该会得到相当大的提升,尽管连接 MVP 仍然需要时间。
还有比上面更简单的实现吗?我想必须有一些“标准”的方式来作为批量绘制精灵。
编辑
我决定使用选项 2,但是我在开始工作时遇到了问题:Shader attribute mat4 not binding correctly (Opengl ES 2.0 android)
【问题讨论】:
【参考方案1】:常见的 2d 引擎所做的是提供基于树的渲染。一个节点有它的模型矩阵,并且有一些子节点,它们都受到父模型矩阵和它们自己的矩阵的影响。在运行时访问每个节点并将其连接父矩阵和自己的矩阵呈现为一个矩阵。除非您要渲染数千个节点(精灵),否则您不必担心将这么多矩阵传递到驱动程序内存中的性能问题。
编辑:您还可以拥有一种特定类型的节点,通常称为 atlas,您可以在其中添加仅受节点模型矩阵影响的预计算四边形(请参阅 https://github.com/cocos2d/cocos2d-iphone/blob/master-v2/cocos2d/CCAtlasNode.m 或 https://github.com/TraxNet/ShadingZen/blob/master/library/src/main/java/org/traxnet/shadingzen/core2d/QuadAtlas.java)。
【讨论】:
我可能会进一步研究这个问题,但目前我决定在上面的帖子中选择选项 2,因为这似乎是我目前所拥有的一个相当直接的进展。但是,正如在编辑的 OP 中解释的那样,我遇到了麻烦。 最好在此处发布新问题并留下指向其他问题的链接。以上是关于在 OpenGL ES 2 中实现 VBO 以渲染精灵的主要内容,如果未能解决你的问题,请参考以下文章
Android OpenGL ES 2. 0 VBO 不渲染