Java OpenGL ES 2.0-需要性能/优化?
Java OpenGL ES 2.0-需要性能/优化?,java,android,opengl-es-2.0,Java,Android,Opengl Es 2.0,我正在绘制大约30-80个纹理平面(正方形)-背景、玩家、敌人、子弹等。 所有平面都会移动和缩放,有些+旋转,有些具有动画纹理。 我认为,这对CPU或GPU来说并不难,但在较慢/较旧的设备上,它的性能相对较低,例如在Galaxy ACE上。 拜托,你能看一下我的代码吗,我做错了什么还是弄脏了什么?或者什么可以优化? 谢谢。 这是我的onSurfaceCreated、onSurfaceChanged和onDrawFrame: public void onSurfaceCreated(GL10 gl
我正在绘制大约30-80个纹理平面(正方形)-背景、玩家、敌人、子弹等。
所有平面都会移动和缩放,有些+旋转,有些具有动画纹理。
我认为,这对CPU或GPU来说并不难,但在较慢/较旧的设备上,它的性能相对较低,例如在Galaxy ACE上。
拜托,你能看一下我的代码吗,我做错了什么还是弄脏了什么?或者什么可以优化?
谢谢。
这是我的onSurfaceCreated、onSurfaceChanged和onDrawFrame:
public void onSurfaceCreated(GL10 glUnused, EGLConfig config) {
..
// load and prepare all textures
..
GLES20.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
GLES20.glEnable(GLES20.GL_CULL_FACE);
GLES20.glDisable(GLES20.GL_DEPTH_TEST);
GLES20.glEnable(GLES20.GL_TEXTURE_2D);
GLES20.glDisable(GL10.GL_DITHER);
GLES20.glDisable(GL10.GL_LIGHTING);
final float eyeX = 0.0f; final float eyeY = 0.0f; final float eyeZ = 1.5f;
final float lookX = 0.0f; final float lookY = 0.0f; final float lookZ = -3.0f;
final float upX = 0.0f; final float upY = 1.0f; final float upZ = 0.0f;
Matrix.setLookAtM(mViewMatrix, 0, eyeX, eyeY, eyeZ, lookX, lookY, lookZ, upX, upY, upZ);
mProgramHandle = GLES20.glCreateProgram();
final String vertexShader =
"uniform mat4 u_MVPMatrix; \n"
+ "attribute vec4 a_Position; \n"
+ "attribute vec2 a_TexCoordinate; \n"
+ "attribute float a_AlphaValue; \n"
+ "varying vec2 v_TexCoordinate; \n"
+ "varying float v_AlphaValue; \n"
+ "void main() \n"
+ "{ \n"
+ " v_TexCoordinate = a_TexCoordinate; \n"
+ " v_AlphaValue = a_AlphaValue; \n"
+ " gl_Position = u_MVPMatrix * a_Position; \n"
+ "} \n";
final String fragmentShader =
"precision lowp float; \n"
+ "uniform sampler2D u_Texture; \n"
+ "varying vec2 v_TexCoordinate; \n"
+ "varying float v_AlphaValue; \n"
+ "void main() \n"
+ "{ \n"
+ " gl_FragColor = texture2D(u_Texture, v_TexCoordinate); \n"
+ " gl_FragColor.a *= v_AlphaValue; \n"
+ "} \n";
final int vertexShaderHandle = ShaderHelper.compileShader(GLES20.GL_VERTEX_SHADER, vertexShader);
final int fragmentShaderHandle = ShaderHelper.compileShader(GLES20.GL_FRAGMENT_SHADER, fragmentShader);
mProgramHandle = ShaderHelper.createAndLinkProgram(vertexShaderHandle, fragmentShaderHandle, new String[] {"a_Position", "a_TexCoordinate", "a_AlphaValue"});
GLES20.glUseProgram(mProgramHandle);
mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgramHandle, "u_MVPMatrix");
mMVMatrixHandle = GLES20.glGetUniformLocation(mProgramHandle, "u_MVMatrix");
mPositionHandle = GLES20.glGetAttribLocation(mProgramHandle, "a_Position");
}
public void onSurfaceChanged(GL10 glUnused, int width, int height) {
GLES20.glViewport(0, 0, width, height);
float ratio = (float) width / height;
Matrix.frustumM(mProjectionMatrix, 0, -ratio, ratio, -1, 1, 1, 1000);
}
public void onDrawFrame(GL10 glUnused) {
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
GLES20.glEnable(GLES20.GL_BLEND);
GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE_MINUS_SRC_ALPHA);
updateGame();
// all planes are saved in Vector<Mesh> children
int size = children.size();
for (int i = 0; i < size; i++)
{
children.get(i).Draw(renderer);
}
}
你以前看过使用游戏引擎吗?他们中有相当多的人能够用更少的代码处理这类任务,并且压力=P 最初学习一个游戏引擎会花费你更多的时间,但会为你节省数百小时的时间。它们是为游戏而设计的,即使在较旧的设备上,通常也能在不牺牲性能的情况下很好地处理大量对象 这不是你问题的直接解决方案,但也许它可以帮助你以后^^ 下面是Android游戏引擎的大量列表 如果你喜欢开源游戏引擎,你可能会喜欢这些,我只有使用其中一些的经验,但我发现AndEngine是最简单的入门工具,而且它绝对强大到足以处理30-80个对象。
您以前看过使用游戏引擎吗?他们中有相当多的人能够用更少的代码处理这类任务,并且压力=P 最初学习一个游戏引擎会花费你更多的时间,但会为你节省数百小时的时间。它们是为游戏而设计的,即使在较旧的设备上,通常也能在不牺牲性能的情况下很好地处理大量对象 这不是你问题的直接解决方案,但也许它可以帮助你以后^^ 下面是Android游戏引擎的大量列表 如果你喜欢开源游戏引擎,你可能会喜欢这些,我只有使用其中一些的经验,但我发现AndEngine是最简单的入门工具,而且它绝对强大到足以处理30-80个对象。
我认为您不想在绘图循环中多次调用glGet*,因为这可能是一个缓慢的操作
您能否在对象内部本地缓存属性位置?或者我想知道为什么在每个对象都使用相同的着色器时,您甚至要为每个对象设置属性位置。我认为您不想在绘制循环中多次调用glGet*,因为这可能是一个缓慢的操作
您能否在对象内部本地缓存属性位置?或者我想知道为什么在每个对象都使用相同的着色器时,您甚至要为每个对象设置属性位置。如果您运行的是较新版本的Android SDK(例如v16),您可以使用探查器找出问题区域的位置: 但乍一看,我可以看到以下几点:
glGetAttriblLocation
,您不必每次都这样做。一旦设置了“程序”,就可以获得这些引用,只要该程序不更改(即不更改着色器),它们就不会更改。调用GlenableVertexAttributeArray
glBindTexture
都可能导致VRAM中的状态更改,这是一个缓慢的操作。纹理图集只是包含所有(或多个)纹理或您的纹理(例如精灵)的单个图像。指定纹理坐标时,只需指定一个介于0和1之间的值,表示单个精灵在地图集中的位置。如果你想使用这种方法,你将不得不“装箱”你的地图集,这样你就不会浪费空间。有一些工具可以做到这一点(如TexturePacker)。这意味着对glBindTexture
glUniformMatrix4fv
传递MVP矩阵两次,这是不必要的。在发送后更改发送到着色器的矩阵将不会产生任何效果(即,初始设置操作将被覆盖),因为只有在调用glDrawArrays
glDrawArrays时才会使用矩阵setRotateM
非常慢。在这个地方我也需要找到其他的选择系统.arrayCopy
是不必要的。您只需将矩阵乘法链接起来,而不需要临时值。矩阵。模型*视图=MV,然后MV*投影=MVP祝您好运。如果您运行的是较新版本的Android SDK(如v16),您可以使用探查器找出问题所在: 但乍一看,我可以看到以下几点:
glGetAttriblLocation
,您不必每次都这样做。一旦设置了“程序”,就可以获得这些引用,只要该程序不更改(即不更改着色器),它们就不会更改。调用GlenableVertexAttributeArray
glBindTexture
都可能导致VRAM中的状态更改,这是一个
public void Draw(Renderer renderer)
{
if (!Visible) return; // no visible object, no need draw
mTextureCoordinateHandle = GLES20.glGetAttribLocation(renderer.mProgramHandle, "a_TexCoordinate");
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mBrickDataHandle);
mAlphaHandle = GLES20.glGetAttribLocation(renderer.mProgramHandle, "a_AlphaValue");
GLES20.glVertexAttrib1f(mAlphaHandle, alpha);
// texture animation
renderer.mPlaneTextureCoords[(byte)indexAnim].position(0);
GLES20.glVertexAttribPointer(mTextureCoordinateHandle, mTextureCoordinateDataSize, GLES20.GL_FLOAT, false, 0, renderer.mPlaneTextureCoords[(byte)indexAnim]);
indexAnim++;
renderer.mPlanePositions.position(0);
GLES20.glVertexAttribPointer(Renderer.mPositionHandle, renderer.mPositionDataSize, GLES20.GL_FLOAT, false, 0, renderer.mPlanePositions);
GLES20.glEnableVertexAttribArray(Renderer.mPositionHandle);
if (angleZ == 0) // no rotating plane -> no need setRotateM
{
Matrix.setIdentityM(renderer.mModelMatrix, 0);
Matrix.translateM(renderer.mModelMatrix, 0, x, y, z);
Matrix.scaleM(renderer.mModelMatrix, 0, scaleX, scaleY, 1);
}
else // rotating plane
{
float[] mt = new float[16];
Matrix.setIdentityM(mt, 0);
Matrix.translateM(mt, 0, x, y, z);
Matrix.scaleM(mt, 0, scaleX, scaleY, 1);
Matrix.setRotateM(mRotZMatrix, 0, angleZ, 0, 0, 1);
Matrix.multiplyMM(renderer.mModelMatrix, 0, mt, 0, mRotZMatrix, 0);
}
Matrix.multiplyMM(renderer.mMVPMatrix, 0, renderer.mViewMatrix, 0, renderer.mModelMatrix, 0);
GLES20.glUniformMatrix4fv(renderer.mMVMatrixHandle, 1, false, renderer.mMVPMatrix, 0);
//Matrix.multiplyMM(renderer.mMVPMatrix, 0, renderer.mProjectionMatrix, 0, renderer.mMVPMatrix, 0);
Matrix.multiplyMM(renderer.mTemporaryMatrix, 0, renderer.mProjectionMatrix, 0, renderer.mMVPMatrix, 0); // little bit faster (?)
System.arraycopy(renderer.mTemporaryMatrix, 0, renderer.mMVPMatrix, 0, 16);
GLES20.glUniformMatrix4fv(renderer.mMVPMatrixHandle, 1, false, renderer.mMVPMatrix, 0); // pass in the combined matrix
GLES20.glEnableVertexAttribArray(mTextureCoordinateHandle);
GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 6);
}