我正在开发一款简单的乒乓式游戏来掌握opengl和android,并且在性能方面似乎已经碰到了一堵砖墙。
我的游戏逻辑在一个单独的线程上,draw命令通过阻塞队列发送到gl线程。问题是我被困在40fps左右,我尝试过的任何东西似乎都没有提高帧速率。
为了简单起见,我设置了opengl:
GLES20.glDisable(GLES20.GL_CULL_FACE);
GLES20.glDisable(GLES20.GL_DEPTH_TEST);
GLES20.glDisable(GLES20.GL_BLEND);
设置opengl程序和绘图由以下类处理:
class GLRectangle {
private final String vertexShaderCode =
"precision lowp float;" +
// This matrix member variable provides a hook to manipulate
// the coordinates of the objects that use this vertex shader
"uniform lowp mat4 uMVPMatrix;" +
"attribute lowp vec4 vPosition;" +
"void main() {" +
// the matrix must be included as a modifier of gl_Position
" gl_Position = vPosition * uMVPMatrix;" +
"}";
private final String fragmentShaderCode =
"precision lowp float;" +
"uniform lowp vec4 vColor;" +
"void main() {" +
" gl_FragColor = vColor;" +
"}";
protected static int mProgram = 0;
private static ShortBuffer drawListBuffer;
private static short drawOrder[] = { 0, 1, 2, 0, 2, 3};//, 4, 5, 6, 4, 6, 7 }; // order to draw vertices
// number of coordinates per vertex in this array
private static final int COORDS_PER_VERTEX = 3;
private static final int vertexStride = COORDS_PER_VERTEX * 4; // bytes per vertex
GLRectangle(){
int vertexShader = GameRenderer.loadShader(GLES20.GL_VERTEX_SHADER, vertexShaderCode);
int fragmentShader = GameRenderer.loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentShaderCode);
mProgram = GLES20.glCreateProgram(); // create empty OpenGL ES Program
GLES20.glAttachShader(mProgram, vertexShader); // add the vertex shader to program
GLES20.glAttachShader(mProgram, fragmentShader); // add the fragment shader to program
GLES20.glLinkProgram(mProgram); // creates OpenGL ES program executables
// initialize byte buffer for the index list
ByteBuffer dlb = ByteBuffer.allocateDirect(
// (# of coordinate values * 2 bytes per short)
drawOrder.length * 2);
dlb.order(ByteOrder.nativeOrder());
drawListBuffer = dlb.asShortBuffer();
drawListBuffer.put(drawOrder);
drawListBuffer.position(0);
}
protected static void Draw(Drawable dObj, float mvpMatrix[])
{
FloatBuffer vertexBuffer = dObj.vertexBuffer;
GLES20.glUseProgram(mProgram);
//GameRenderer.checkGlError("glUseProgram");
// get handle to fragment shader's vColor member
int mColorHandle = GLES20.glGetUniformLocation(mProgram, "vColor");
//GameRenderer.checkGlError("glGetUniformLocation");
// get handle to shape's transformation matrix
int mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
//GameRenderer.checkGlError("glGetUniformLocation");
// get handle to vertex shader's vPosition member
int mPositionHandle = GLES20.glGetAttribLocation(mProgram, "vPosition");
//GameRenderer.checkGlError("glGetAttribLocation");
// Apply the projection and view transformation
GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mvpMatrix, 0);
//GameRenderer.checkGlError("glUniformMatrix4fv");
// Set color for drawing the quad
GLES20.glUniform4fv(mColorHandle, 1, dObj.color, 0);
//GameRenderer.checkGlError("glUniform4fv");
// Enable a handle to the square vertices
GLES20.glEnableVertexAttribArray(mPositionHandle);
//GameRenderer.checkGlError("glEnableVertexAttribArray");
// Prepare the square coordinate data
GLES20.glVertexAttribPointer(mPositionHandle, COORDS_PER_VERTEX,
GLES20.GL_FLOAT, false,
vertexStride, vertexBuffer);
//GameRenderer.checkGlError("glVertexAttribPointer");
// Draw the square
GLES20.glDrawElements(GLES20.GL_TRIANGLES, drawOrder.length,
GLES20.GL_UNSIGNED_SHORT, drawListBuffer);
//GameRenderer.checkGlError("glDrawElements");
// Disable vertex array
GLES20.glDisableVertexAttribArray(mPositionHandle);
//GameRenderer.checkGlError("glDisableVertexAttribArray");
}
}
我已经做了大量的分析和谷歌搜索,但是找不到任何可以让这项工作更快的内容...我已经包含了DDMS输出的截图:
对我来说,看起来glClear导致GLThread睡了23分钟......虽然我怀疑情况确实如此。
我完全不知道如何才能提高效率,没有什么花哨的东西。在我寻求更好的渲染性能的过程中,我已经切换到我所描述的多线程方法,关闭了alpha混合和深度测试,改为批量绘制方法(不适用于这个简单的例子),并在着色器中将所有内容切换为lowp
任何获得60fps的帮助都将非常感谢!
布鲁斯
编辑好好谈谈过度思考问题。事实证明,过去一周我已经开启了省电模式......它似乎将渲染锁定为40fps。
答案 0 :(得分:4)
使用Galaxy S3打开省电模式时会出现此问题。
似乎省电模式将帧速率锁定为40fps。轻松关闭它可以达到所需的60fps。
答案 1 :(得分:0)
不确定您是否可以控制设备表面的EGL设置,但是如果可以,则可以设置更新以“非同步”模式运行。
egl.eglSwapInterval( dpy, 0 )
这并非在所有设备上都可用,但允许对渲染进行一些控制。