我有一个程序可以绘制超过90个带有纹理的2D形状,用户可以通过触摸屏幕来拾取和拖动。有一个明显的紊乱,DDMS告诉我占用最多CPU时间(~85%)的一种方法是draw()方法。由于只有1个形状实际上是移动而另外89个不是,使用FrameBuffer对象将89个形状渲染到纹理是否可能/更快,并将该纹理绘制在填满整个屏幕的形状上?如果没有,还有其他可能的加速方法吗?
private void draw() {
// Pass in the position information
mCubePositions.position(0);
GLES20.glVertexAttribPointer(mPositionHandle, mPositionDataSize, GLES20.GL_FLOAT, false, 0, mCubePositions);
GLES20.glEnableVertexAttribArray(mPositionHandle);
// Pass in the color information
mCubeColors.position(0);
GLES20.glVertexAttribPointer(mColorHandle, mColorDataSize, GLES20.GL_FLOAT, false, 0, mCubeColors);
GLES20.glEnableVertexAttribArray(mColorHandle);
// Pass in the texture coordinate information
mCubeTextureCoordinates.position(0);
GLES20.glVertexAttribPointer(mTextureCoordinateHandle, mTextureCoordinateDataSize, GLES20.GL_FLOAT, false, 0, mCubeTextureCoordinates);
GLES20.glEnableVertexAttribArray(mTextureCoordinateHandle);
// This multiplies the view matrix by the model matrix, and stores the
// result in the MVP matrix
// (which currently contains model * view).
Matrix.multiplyMM(mMVPMatrix, 0, mViewMatrix, 0, mModelMatrix, 0);
// Pass in the modelview matrix.
GLES20.glUniformMatrix4fv(mMVMatrixHandle, 1, false, mMVPMatrix, 0);
// This multiplies the modelview matrix by the projection matrix, and
// stores the result in the MVP matrix
// (which now contains model * view * projection).
Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mMVPMatrix, 0);
// Pass in the combined matrix.
GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mMVPMatrix, 0);
// Draw the cube.
GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 6);
}
提前致谢。
答案 0 :(得分:3)
我对提到" cube"的问题感到困惑。当它意味着四边形,所以这个答案处理的是3d案例,无论如何这可能更有启发性。
将视图和投影矩阵组合到ViewProj矩阵中。然后在vert着色器中执行VertexPos * Model * ViewProj。
你真的需要批量。您应该有一个包含所有多维数据集的大数组,以及另一个包含每个多维数据集转换的数组。然后,您为所有多维数据集执行一次绘制调用。考虑将其转换为使用顶点缓冲区对象。绘制调用是CPU密集型的,因为它们在幕后的API中调用了大量的逻辑和内存复制等。游戏引擎竭尽全力将它们最小化。
如何使一个绘制调用绘制很多东西
将所有不同的纹理放入单个纹理(" atlas"),并通过调整每个立方体的UV来补偿以查找纹理的适当部分。将所有模型矩阵放入一个连续的数组中,并在顶点着色器中索引此数组,例如
attribute vec3 a_position;
attribute vec2 a_texCoord;
attribute int a_modelIndex;
attribute int a_UVlIndex;
uniform mat4 u_model[90];
uniform vec2 u_UVOffset[16]; // Support 16 different textures in our atlas.
varying vec2 v_texCoord;
...
void main()
{
gl_Position = u_viewProj * u_model[a_modelIndex] * vec4(a_position, 1);
v_texCoord = a_texCoord + u_UVOffset[a_UVlIndex];
...
}
您可以将所有顶点数据打包成一个大数组,这样您最终会做GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 6 * 90);
但更好的是,因为您只是一直在绘制多维数据集,所以您可以重新使用完全相同每次都是顶点数据。模型矩阵负责其余的(缩放,旋转,平移)。要做到这一点,使用glDrawElements
代替glDrawArrays,并且---为简单起见假设三个列表 - 指定36个引用顶点数组中36个顶点的索引,这些顶点构成一个立方体,然后重复这36个索引90制作索引数组的时间。顶点应该是一个单位立方体,以(0,0,0)为中心。同样的"立方体模板"然后由顶点着色器中的模型矩阵修改,以创建每个可见的"立方体实例"。您需要更改每个帧的唯一方法是模型矩阵和纹理UV。
glVertexAttribPointer()
允许你在你的顶点着色器中喷出你喜欢的任何东西,将模型矩阵作为属性而不是制服使用glVertexAttribPointer可能更有效。
移动设备往往对像素绑定非常敏感。如果你的立方体在屏幕上非常大,你可能会得到很多透支。高CPU%(毕竟它只是一个百分比)可能是一个红色鲱鱼,你可能是GPU上的像素绑定。对此进行简单测试就是使所有立方体非常小,并查看帧速率是否有所改善。
作为参考,S5570有一个Adreno 200 GPU。