在openGL ES 2.0中高效绘制基元

时间:2012-03-22 02:57:09

标签: java android opengl-es-2.0

我正在Android上编写一款游戏,它的表现非常好。我试图保持一切尽可能高效,所以我尽可能多地存储在顶点缓冲区对象中以避免不必要的CPU开销。然而,有效地绘制大量不相关的图元,甚至是不同长度的精灵字符串(例如将文本绘制到屏幕上)的简单行为正在逃避我。

这些原语的目的是菜单和按钮,以及文本。

为了绘制菜单,我可以为每个元素(菜单背景,按钮等)创建一个顶点数组,但由于它们都只是四边形,因此效率非常低。我还可以创建一种drawQuad()函数,它允许我透明地加载一个保存的顶点数组,其中包含xy / height& width / color / texture / whatever的数据。但是,每次使用新坐标和其他数据重新加载数组的每个元素,将其复制到浮点缓冲区(对于C ++人员来说,这是您必须在Java中将数据传递给GL的特殊步骤)所以我可以重新发送到GPU也感觉缺乏效率,虽然我不知道我怎么能做到这一点。 (我可以看到效率的一个提升是将四边形坐标设置为单位平方,然后使用Uniforms来缩放它,但这似乎是不可扩展的。)

对于文本,它更糟糕,因为我不知道文本将持续多长时间,并且不希望为较大的文本创建更大的缓冲区(导致GC随后随机触发)。替代方案是使用独立的绘图命令绘制每个字母,但是对于屏幕上的一百个字母来说这似乎也非常低效(因为我读到你应该尝试尽可能少的绘制命令)。

我也有可能对openGL的必要优化过于深入,但我不想在早期将自己置于一个可怕的设计角落。

1 个答案:

答案 0 :(得分:2)

您应该尝试研究为glDrawArrays调用交错数据的想法。 当然这个链接适用于iphone,但页面底部有一个很好的图形,详细说明了这个概念。 http://iphonedevelopment.blogspot.com/2009/06/opengl-es-from-ground-up-part-8.html

我将假设绘制你的角色,你正在指定一些顶点坐标和一些纹理坐标到某种字体位图来选择正确的字符。 所以你可以设想你的FloatBuffer看起来像

[vertex 1] [texcoord 1] [vertex 2] [texcoord 2] [vertex 3] [texcoord 3]

[vertex 2] [texcoord 2] [vertex 3] [texcoord 3] [vertex 4] [texcoord 4]

如果您正在使用GL_TRIANGLES,上面将代表您句子中的单个字符,并且您可以扩展此构思以使顶点5 - 8代表第二个字符,依此类推。现在,您可以使用一个glDrawArrays调用在屏幕上绘制所有文本。现在您可能担心FloatBuffer中存在冗余数据,但节省的费用将会非常巨大。例如,在渲染带有1200个顶点的茶壶并在我的缓冲区中使用这个冗余数据时,我能够获得非常明显的速度增加,而不是为每个三角形调用glDrawArrays可能会好10倍。

我在sourceforge上有一个小型演示,我使用数据交错来渲染我之前提到过的茶壶。 它的ShaderProgramTutorial.rar。 https://sourceforge.net/projects/androidopengles/files/ShaderProgram/ 查看onDrawFrame函数中的teapot.java以查看它。

另外,您可以在sourceforge页面上找到其他一些有助于您未来Android OpenGL ES 2.0的其他内容!

相关问题