2014-04-10 48 views
1

我正在編寫一個小2D遊戲的圖形。 爲此,請使用OpenGL ES 2.0。 我有一個對象,其中包含構建矩形的頂點。對於我需要縮放的每個障礙,請翻譯並繪製這個對象。 我這樣做並不需要爲每個繪製和每個障礙物上傳頂點。 (這個「水平」就像飛揚的鳥或飛行器兜風一樣移動) 但是現在我必須在每一幀中上傳我的矩陣。 大多數情況下,我的lg g2上繪製一個Frame需要5-17 ms。但是每幀有100毫秒的峯值。移動多個對象的Android OpenGL ES 2.0性能問題

在這一點上,我只畫矩形,所以我真的不知道爲什麼我面臨這些表演problems.Following將是我的ObstacleGL類和我的渲染器的代碼。

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 and 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 I give the new position 
     GLES20.glUniformMatrix4fv(matrixHandle, 1,false, matrix, 0); 
     GLES20.glDrawArrays(GLES20.GL_TRIANGLE_FAN, 0, vertexCount); 
    } 
} 

下面是我的GameRenderer。我們在其他線程上運行的gamesimulation會使用重寫的方法。

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(); 

     for (int i = 0; i < 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) { 
     for (int i = 0; i < obstacleList.size(); i++) { 
      Obstacle o=obstacleList.get(i); 
      o.xPosition+=-x; 
     } 

    } 


    @Override 
    public void deleteObstacle(int id) { 
     for (int i = 0; i < obstacleList.size(); i++) { 
      if(obstacleList.get(i).id==id){ 
       obstacleList.remove(i); 
       return; 
      } 
     } 
    } 

    @Override 
    public void gameOver() { 
     // TODO Auto-generated method stub 
    } 
} 

回答

1

所以我發現,現在行之有效的解決方案:所有我外包矩陣障礙物類 第一,所以他們並不需要計算每一個平局。 這有3個效果:

  1. 當障礙物不移動時,矩陣不需要修改。
  2. 矩陣不需要在opengl線程中計算。
  3. 我不需要每次計算比例尺,因爲我有一個每個障礙物的比例矩陣