2013-07-12 111 views
1

平臺:Android的 版本:2.2及以上 加速:OpenGL ES 2.0的 語言:Java的 IDE:ADT - Eclipse的優化的OpenGL ES 2.0繪圖爲Android

我試圖利用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); 
    } 

回答

1

如果你要繪製很多相同的對象,你可以做的一件簡單的事情是避免進行多餘的調用。

例如,在Android Breakout中,我最近確定可以通過拆分一些設置代碼來將CPU(而非GPU)的時間減半。如果傳遞給諸如glEnableVertexAttribArray,glVertexAttribPointer和之類的函數的值對於一系列對象是相同的,則需要將這些值設置一次,然後繪製所有可以對象的對象。

在我的情況下,對象實際上只有兩種風格(紋理和非紋理),所以一堆調用從每幀發出一百次到每幀兩次。

有關具體示例,請參閱this bit of codesDrawPrepared是我用來確保我只在班級準備好時纔打電話的健全檢查。 (它不檢查所有可能的錯誤,但是如果你看看onDrawFrame(),你會發現它並不是一個複雜的遊戲。)