在OpenGL ES 2.0中高效绘制基本图形

3
我正在为Android编写一款游戏,进展顺利。我试图尽可能高效地存储所有内容,因此我将尽可能多的内容存储在顶点缓冲对象中,以避免不必要的CPU开销。然而,绘制大量不相关的基元,甚至是有效地绘制变长的精灵字符串(例如将文本绘制到屏幕上)仍然困扰着我。
这些基元的目的是菜单和按钮,以及文本。
对于绘制菜单,我可以为每个元素(菜单背景、按钮等)创建一个顶点数组,但由于它们都只是四边形,这感觉非常低效。我也可以创建一种drawQuad()函数,让我透明地加载一个保存的带有xy/height&width/color/texture/whatever数据的单个顶点数组。然而,每次重新加载数组的每个元素以及其他数据来将其复制到Float Buffer中(对于C++程序员来说,在Java中执行此操作需要特殊步骤才能将数据传递给GL),以便我可以将其重新发送到GPU,这也感觉效率不高,虽然我不知道还能怎么做。(我能看到的一种提高效率的方式是将四边形坐标设置为单位正方形,然后使用Uniforms进行缩放,但这似乎不可扩展)。
对于文本来说,情况更糟,因为我不知道文本长度会有多长,也不想为更大的文本创建更大的缓冲区(导致GC随机触发)。另一种方法是使用独立的draw命令绘制每个字母,但即使在屏幕上只有100个字母,这也似乎非常低效(因为我读到应尽可能少地使用draw命令)。
也有可能我正在过分深入openGL的必要优化,但我不想在早期就把自己逼入一个可怕的设计死角。
1个回答

2
你应该尝试研究交错数据的想法,用于你的glDrawArrays调用。 虽然这个链接是针对iPhone的,但页面底部有一个漂亮的图形详细说明了这个概念。http://iphonedevelopment.blogspot.com/2009/06/opengl-es-from-ground-up-part-8.html 我假设你正在为绘制字符指定一些顶点坐标和一些纹理坐标,以从某种字体位图中选择正确的字符。 因此,你可以将你的FloatBuffer视为如下所示:
[顶点1][纹理坐标1][顶点2][纹理坐标2][顶点3][纹理坐标3]
[顶点2][纹理坐标2][顶点3][纹理坐标3][顶点4][纹理坐标4]
上述内容表示,如果您使用GL_TRIANGLES,则以上内容将代表您句子中的单个字符,您可以扩展这个想法,使顶点5-8代表第二个字符,以此类推。现在,您可以通过单个glDrawArrays调用在屏幕上绘制所有文本。现在,您可能担心在FloatBuffer中有冗余数据,但是节省的空间将非常巨大。例如,在渲染具有1200个顶点的茶壶并在我的缓冲区中具有此冗余数据时,我能够比为每个单独的三角形调用glDrawArrays获得非常明显的速度提高,大约快10倍左右。

我在sourceforge上有一个小演示,其中我使用数据交错来呈现前面提到的茶壶。它是ShaderProgramTutorial.rar文件。 https://sourceforge.net/projects/androidopengles/files/ShaderProgram/请查看teapot.java中的onDrawFrame函数。

顺便说一下,您可能会发现该sourceforge页面上的其他一些内容对您未来的Android OpenGL ES 2.0有所帮助!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接