平台:安卓 版本:2.2及以上 加速:OpenGL ES 2.0 语言:Java IDE:ADT-Eclipse
我正在尝试利用 OpenGL ES 2.0 为我正在创建的游戏快速加速 2D Sprites 的绘制,但是我没有从适用于 Android 的 OpenGL ES 2.0 获得所需的速度。下面是我的与在 OpenGL 中绘图相关的代码。使用分析器时,每帧的大部分时间都被 Draw 方法占用。
此外,由于游戏的性质,CreateModelMatrix() 在绘制前的每一帧都被调用,因为对象不断移动和旋转。
如何优化 Draw 方法使其更高效?
void Create(float[] ModelData, float[] CoordData)
{
//Count Verts
Verts = ModelData.length / 3;
//Create Buffer outside Java VM
FloatBuffer ModelBuffer;
ModelBuffer = ByteBuffer.allocateDirect(ModelData.length* BYTES_PER_FLOAT)
.order(ByteOrder.nativeOrder()).asFloatBuffer();
ModelBuffer.put(ModelData).position(0);
FloatBuffer CoordBuffer;
CoordBuffer = ByteBuffer.allocateDirect(CoordData.length* BYTES_PER_FLOAT)
.order(ByteOrder.nativeOrder()).asFloatBuffer();
CoordBuffer.put(CoordData).position(0);
//Create OpenGL Buffer
final int buffers[] = new int[2];
GLES20.glGenBuffers(2,buffers,0);
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, buffers[0]);
GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, ModelBuffer.capacity() * 4, ModelBuffer, GLES20.GL_STATIC_DRAW);
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, buffers[1]);
GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, CoordBuffer.capacity() * 4, CoordBuffer, GLES20.GL_STATIC_DRAW);
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER,0);
VertHandle = buffers[0];
FrameHandle.add( buffers[1] );
//Set empty for Garbage Collection
ModelBuffer.limit(0);
ModelBuffer = null;
CoordBuffer.limit(0);
CoordBuffer = null;
ModelMatrix = new float[16];
Matrix.setIdentityM(ModelMatrix, 0);
//ModelMatrix[3] = 0.5f;
}
void CreateModelMatrix() {
Matrix.setIdentityM(ModelMatrix, 0);
Matrix.translateM(ModelMatrix,0,x,y,0.0f);
Matrix.rotateM(ModelMatrix, 0, rot, 0.0f, 0.0f, 1.0f);
Matrix.translateM(ModelMatrix,0,-this.OriginX,-this.OriginY,0.0f);
}
void Draw()
{
//final int stride = (POSITION_DATA_SIZE + NORMAL_DATA_SIZE + TEXTURE_COORDINATE_DATA_SIZE) * BYTES_PER_FLOAT;
// Pass in the position information
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, VertHandle);
GLES20.glEnableVertexAttribArray(mPositionHandle);
GLES20.glVertexAttribPointer(mPositionHandle, POSITION_DATA_SIZE, GLES20.GL_FLOAT, false, POSITION_DATA_SIZE * BYTES_PER_FLOAT, 0);
// Pass in the texture information
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, FrameHandle.get((int)Frame));
GLES20.glEnableVertexAttribArray(mTextureCoordinateHandle);
GLES20.glVertexAttribPointer(mTextureCoordinateHandle, TEXTURE_COORDINATE_DATA_SIZE, GLES20.GL_FLOAT, false,
TEXTURE_COORDINATE_DATA_SIZE * BYTES_PER_FLOAT, 0);
// Clear the currently bound buffer (so future OpenGL calls do not use this buffer).
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
//Pass the Model Matrix
GLES20.glUniformMatrix4fv(mMMatrixHandle, 1, false, ModelMatrix, 0);
//Set Texturing
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureDataHandle);
GLES20.glUniform1i(mTextureUniformHandle, 0);
// Draw the cubes.
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, Verts);
}
最佳答案
如果您要绘制很多相同的对象,您可以做的一件简单的事情就是避免进行冗余调用。
例如,在 Android Breakout 中,我最近确定我可以通过拆分一些设置代码来将 CPU(而不是 GPU)时间减半。如果传递给 glEnableVertexAttribArray
、glVertexAttribPointer
和 glActiveTexture
等函数的值对于一系列对象是相同的,您希望设置这些值一次然后尽可能地画出所有物体。
在我的例子中,对象实际上只有两种类型(纹理和非纹理),所以一堆调用从每帧发出一百次变成每帧两次。
参见 this bit of code举个具体的例子。 sDrawPrepared
是一种健全性检查,我用它来确保我只在类准备好时才调用 draw。 (它不会检查所有可能的错误,但如果您查看 onDrawFrame()
,您会发现它并不是一个复杂的游戏。)
关于java - 为 Android 优化 OpenGL ES 2.0 绘图,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17621646/