Android 我可以通过将attrib数据组合到单个vbo中来提高opengl es2的性能吗?

Android 我可以通过将attrib数据组合到单个vbo中来提高opengl es2的性能吗?,android,performance,opengl-es-2.0,Android,Performance,Opengl Es 2.0,我正在android应用程序中绘制少量相当大的网格(实际上是srtm数据中的地形),我希望它运行得更快(或者在较慢的设备上运行)。目前,我对顶点数据使用1个浮点缓冲区,对法线使用1个字节缓冲区 将两个缓冲区合并为一个会提高性能吗?我在这里和博客上发现了一些帖子,声称一个缓冲区会更好,但几乎没有确凿的证据 测试用例使用6个单独的网格,每个网格具有65k个顶点和128k个三角形。(我使用抽屉元素,因为每个顶点最多用于8个三角形) 颜色(到目前为止)是根据顶点着色器中的点高度计算的,因此我不需要将颜色

我正在android应用程序中绘制少量相当大的网格(实际上是srtm数据中的地形),我希望它运行得更快(或者在较慢的设备上运行)。目前,我对顶点数据使用1个浮点缓冲区,对法线使用1个字节缓冲区

将两个缓冲区合并为一个会提高性能吗?我在这里和博客上发现了一些帖子,声称一个缓冲区会更好,但几乎没有确凿的证据

测试用例使用6个单独的网格,每个网格具有65k个顶点和128k个三角形。(我使用抽屉元素,因为每个顶点最多用于8个三角形)

颜色(到目前为止)是根据顶点着色器中的点高度计算的,因此我不需要将颜色信息作为属性数据传入

这是在标准android虚拟机中运行的所有Java代码

片段着色器是统一的

void main() {
  gl_FragColor = v_Colour;
}
顶点着色器是:

uniform mat4 u_MVPMatrix;
uniform mat4 u_MVMatrix;
uniform float u_many[8];

const int inflightx = 0; //vector to light in u_many
const int inflighty = 1;
const int inflightz = 2;

const int ambfactor = 3;

const vec3 basecolour1 = vec3(28.0 / 255.0, 188.0 / 255.0, 108.0 / 255.0);
const vec3 basecolour2 = vec3(150.0 / 255.0, 75.0 / 255.0, 0.0);
const vec3 basecolour3 = vec3(0.85, 0.85, 0.85);

attribute vec4 a_vpos;
attribute vec3 a_vertexnormal;

varying vec4 v_Colour;

void main() {
  vec3 eyenormal = vec3(u_MVMatrix *vec4(a_vertexnormal, 0.0));
  eyenormal = eyenormal / length(eyenormal);

  vec3 basecolour;

  if (a_vpos.z < 100.0) {
    basecolour = basecolour1 + ((basecolour2-basecolour1) * a_vpos.z / 100.0);
  } else {
    basecolour = basecolour2 + ((basecolour3-basecolour2) * (a_vpos.z - 100.0) / 500.0);
  }

  v_Colour = vec4(((dot(eyenormal, vec3(u_many[inflightx],u_many[inflighty],u_many[inflightz])) + u_many[ambfactor]) * basecolour),1.0);

  gl_Position = u_MVPMatrix * a_vpos;

}

我已经测试了这两种方法,在我尝试过的两款设备上,Galaxy S2和Nexus 7的性能没有显著差异。以下是详细信息:

双缓冲区:顶点数据作为浮点的三倍,普通数据作为字节的三倍,紧密压缩

单缓冲区:跨步16字节,三倍浮点,三倍字节,1字节填充

结果信息:我在GLSurfaceView.Renderer中的onDrawFrame的入口和出口处对此进行了计时,通过测量每次入口和出口处的SystemClock.uptimeMillis()和SystemClock.currentThreadTimeMillis()的抓取时间来查看每次调用在我的代码中花费的时间以及实际的cpu时间。以毫秒、每秒帧数->每秒帧数表示的时间

Galaxy S2使用2个缓冲区:

max:74.0 min:65.0 avg:66.0 fps:9.883199 from 33 frames cpu: 15.86144%

max:77.0 min:65.0 avg:67.0 fps:9.88616 from 33 frames cpu: 15.955056%

max:84.0 min:54.0 avg:64.0 fps:10.197961 from 34 frames cpu: 13.786848%
max:14.0 min:2.0 avg:4.0 fps:19.642859 from 66 frames cpu: 72.22222%

max:9.0 min:1.0 avg:3.0 fps:19.725044 from 66 frames cpu: 82.35294%

max:7.0 min:2.0 avg:3.0 fps:19.689737 from 66 frames cpu: 82.30453%
使用1个缓冲区的Galaxy S2:

max:85.0 min:64.0 avg:68.0 fps:9.806835 from 33 frames cpu: 15.654102%

max:76.0 min:55.0 avg:64.0 fps:10.36116 from 35 frames cpu: 17.079645%

max:85.0 min:64.0 avg:68.0 fps:9.806835 from 33 frames cpu: 15.654102%
Nexus 7使用2个缓冲区:

max:74.0 min:65.0 avg:66.0 fps:9.883199 from 33 frames cpu: 15.86144%

max:77.0 min:65.0 avg:67.0 fps:9.88616 from 33 frames cpu: 15.955056%

max:84.0 min:54.0 avg:64.0 fps:10.197961 from 34 frames cpu: 13.786848%
max:14.0 min:2.0 avg:4.0 fps:19.642859 from 66 frames cpu: 72.22222%

max:9.0 min:1.0 avg:3.0 fps:19.725044 from 66 frames cpu: 82.35294%

max:7.0 min:2.0 avg:3.0 fps:19.689737 from 66 frames cpu: 82.30453%
使用组合缓冲区的Nexus 7:

max:7.0 min:2.0 avg:3.0 fps:19.881306 from 67 frames cpu: 80.0%

max:22.0 min:1.0 avg:4.0 fps:19.828352 from 67 frames cpu: 62.26994%

max:9.0 min:2.0 avg:3.0 fps:19.904932 from 67 frames cpu: 80.15564%

将每个顶点属性存储在单独的缓冲区中称为数组结构。将每个顶点属性连续存储在同一缓冲区中称为结构数组

理论上说,将顶点存储在结构数组中是最有效的方法,因为顶点着色器可以读取给定顶点的每个属性以进行顺序处理。仅当程序需要修改每个帧的某些属性(但不是所有属性,例如顶点位置,但不是法线)时,才建议使用数组结构,这样就可以只更新需要修改的数据,而无需重写整个顶点缓冲区

但这是理论,在你的情况下,你可能没有足够的数据来处理,以实际看到差异

此外,如果您仍然希望使用两个缓冲区,我建议您为普通缓冲区保持4字节对齐(如果您有足够的内存),如果顶点大小不是4的倍数,则性能可能会受到影响