Android OpenGL ES 2.0 Performance Problems moving multiple Objects -
i programming graphics little 2d game. doing use opengl es 2.0. have 1 object contains vertexes build rectangle. every obstacle need scale,translate , draw object. did not have upload vertices every draw , every obstacle. (the "level" allways moving in flappy bird or jetpack joyride) have upload matrices every object in every frame. of time drawing of 1 frame takes 5-17 ms on lg g2. there peaks 100 ms per frame.
at point i'm drawing rectangles, realy don't know why i'm facing these performances problems.following code obstaclegl class , renderer.
package com.example.jump; import java.nio.bytebuffer; import java.nio.byteorder; import java.nio.floatbuffer; import java.nio.shortbuffer; import android.opengl.gles20; import android.opengl.matrix; public class obstaclegl { static final int coords_per_vertex = 3; static final int vertexstride = coords_per_vertex * 4; private static final string vertexshadercode = "uniform mat4 umvpmatrix; \n" + "attribute vec4 vposition; \n" + "attribute vec4 color; \n" + "varying vec4 fragcolor; \n"+ "void main() { \n" + " gl_position = umvpmatrix * vposition; \n" + " fragcolor = color; \n"+ "}"; private static final string fragmentshadercode = "precision mediump float; \n" + "varying vec4 fragcolor; \n" + "void main() { \n" + " gl_fragcolor = fragcolor;\n" + "}"; private float [] coords={ //x,y,z z=0 -1,1,0, //upper left -1,-1,0, //bottom left 1,-1,0, //upper right 1,1,0 //bottom right }; private final short[] draworder = { 0, 1, 2, 0, 2, 3 }; private int fragmentshader; private int vertexshader; private int mprogram; private float[] color={0.33f,1f,0.33f,0.5f}; private int colorhandle; private int positionhandle; private floatbuffer vertexbuffer; private shortbuffer drawlistbuffer; private int matrixhandle; private int vertexcount; private float[] translationmatrix=new float[16]; private float[] scalematrix=new float[16]; public void initialize(){ fragmentshader=gamerenderer.loadshader(gles20.gl_fragment_shader,fragmentshadercode); vertexshader=gamerenderer.loadshader(gles20.gl_vertex_shader, vertexshadercode); bytebuffer bb; bytebuffer dlb; bb= bytebuffer.allocatedirect(coords.length*4); bb.order(byteorder.nativeorder()); vertexbuffer=bb.asfloatbuffer(); vertexbuffer.put(coords); vertexbuffer.position(0); dlb=bytebuffer.allocatedirect(12); //draworder.length*2 dlb.order(byteorder.nativeorder()); drawlistbuffer=dlb.asshortbuffer(); drawlistbuffer.put(draworder); drawlistbuffer.position(0); mprogram=gles20.glcreateprogram(); gles20.glattachshader(mprogram, vertexshader); gles20.glattachshader(mprogram, fragmentshader); gles20.gllinkprogram(mprogram); colorhandle=gles20.glgetattriblocation(mprogram, "color"); positionhandle=gles20.glgetattriblocation(mprogram, "vposition"); matrixhandle=gles20.glgetuniformlocation(mprogram, "umvpmatrix"); gles20.glvertexattrib4fv(colorhandle, color, 0); gles20.glenablevertexattribarray(positionhandle); gles20.glvertexattribpointer(positionhandle, coords_per_vertex, gles20.gl_float, false,vertexstride , vertexbuffer); gles20.gldisablevertexattribarray(positionhandle); } public obstaclegl() { vertexcount=coords.length/coords_per_vertex; matrix.setidentitym(translationmatrix, 0); matrix.setidentitym(scalematrix, 0); initialize(); } public void prepare(){ //prepare obstacle drawing gles20.gluseprogram(mprogram); gles20.glenablevertexattribarray(positionhandle); } public void finish(){ gles20.gldisablevertexattribarray(positionhandle); } public void draw(float posx, float posy, float height, float width) { //new position , scale float[] matrix= new float[16]; matrix.setidentitym(translationmatrix, 0); matrix.setidentitym(scalematrix, 0); matrix.scalem(scalematrix, 0, width, height, 1); matrix.translatem(translationmatrix, 0, 2*posx-1,2*posy-1+height, 0); matrix.multiplymm(matrix, 0,translationmatrix , 0,scalematrix , 0); //here give new position gles20.gluniformmatrix4fv(matrixhandle, 1,false, matrix, 0); gles20.gldrawarrays(gles20.gl_triangle_fan, 0, vertexcount); } }
and here follows gamerenderer. overridden methods used our gamesimulation runs on thread.
package com.example.jump; import java.util.linkedlist; import javax.microedition.khronos.egl.eglconfig; import javax.microedition.khronos.opengles.gl10; import android.opengl.gles20; import android.opengl.glsurfaceview; import android.util.log; public class gamerenderer implements glsurfaceview.renderer,gamevisualisation { private obstaclegl obstacle; private linkedlist<obstacle> obstaclelist= new linkedlist<obstacle>(); obstacle o; //renderer methoden @override public void ondrawframe(gl10 gl) { gles20.glclear(gles20.gl_color_buffer_bit); obstacle.prepare(); (int = 0; < obstaclelist.size(); i++) { if(i==obstaclelist.size()) break; o=obstaclelist.get(i); obstacle.draw(o.xposition, o.yposition, o.height, o.width); } obstacle.finish(); } public static int loadshader(int type, string shadercode) { int shader=gles20.glcreateshader(type); gles20.glshadersource(shader, shadercode); gles20.glcompileshader(shader); return shader; } @override public void onsurfacechanged(gl10 gl, int width, int height) { gles20.glviewport(0, 0, width, height); } @override public void onsurfacecreated(gl10 gl, eglconfig config) { gles20.glclearcolor(0.5f, 0.5f, 0.5f, 1.0f); initialize(); } private void initialize() { obstacle=new obstaclegl(); } //gamevisualisationinterfacemethoden @override public void changepunktestand(int punkte) { // todo auto-generated method stub } @override public void movecharacter(double height) { // todo auto-generated method stub } @override public void changecharacteranimation(int animation) { // todo auto-generated method stub } @override public void addobstacle(int id, float xpos, float ypos, float width, float height) { obstaclelist.add(new obstacle(id, height, width, xpos, ypos)); if(o==null) o=new obstacle(id, height, width, xpos, ypos); } @override public void moveobstacle(int id, double xpos, double ypos) { // todo } @override public void moveobstaclesx(float x) { (int = 0; < obstaclelist.size(); i++) { obstacle o=obstaclelist.get(i); o.xposition+=-x; } } @override public void deleteobstacle(int id) { (int = 0; < obstaclelist.size(); i++) { if(obstaclelist.get(i).id==id){ obstaclelist.remove(i); return; } } } @override public void gameover() { // todo auto-generated method stub } }
so found solution works now: first of outsourced matrices obstacle class, don't need calculated every draw. has 3 effects:
- the matrices don't need modified when obstacle doesn't move.
- the matrices don't need calculated in opengl thread.
- i don't need calculate scale everytime, cause have scale matrix every obstacle
Comments
Post a Comment