0

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

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

测试用例使用 6 个独立的网格,每个网格有 65k 个顶点和 128k 个三角形。(我正在使用drawelements,因为每个顶点最多可用于8个三角形)。

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

这是在标准 android VM 中运行的所有 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;

}
4

2 回答 2

1

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

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

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

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

于 2013-06-17T13:48:55.507 回答
0

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

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

单个缓冲区:跨度 16 字节,浮点数的三倍,字节的三倍,1 字节填充。

结果信息:我已经在 GLSurfaceView.Renderer 中的 onDrawFrame 的入口和出口处计时,方法是测量在每个入口和出口处抓取 SystemClock.uptimeMillis() 和 SystemClock.currentThreadTimeMillis() 以查看每个呼叫花费多长时间我的代码以及实际的 cpu 时间。以毫秒为单位的时间,fps-> 每秒帧数。

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%

Galaxy S2 使用 1 个缓冲区:

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: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%
于 2013-06-13T10:28:44.573 回答