2017-07-14 30 views
1

我在我的opengl 2.0遊戲中有性能問題。在我改變遊戲之前,幀率是好的。它有64種形狀(磚塊)的某種爆發遊戲。我現在想要的是,當球擊中磚塊時,它不會立即移除 - 它會改變狀態,包括改變紋理或更正確 - 地圖集的uv座標。我有一個textureatlas,我所做的只是爲循環中的每個紋理調用GLES20.bindBuffer(),而不是調用循環外部。此前我有同樣的UV-座標爲各種形狀,但現在我把它取決於磚狀態改變,這就是爲什麼我需要使用綁定環路OpenGL ES 2.0:性能下降使用bindbuffer頻繁

private void drawShape() { 


    GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vboDataListLevelSprites.get(iName).getBuff_id_vertices()); 
    GLES20.glEnableVertexAttribArray(mPositionHandle); 
    GLES20.glVertexAttribPointer(mPositionHandle, 3, GLES20.GL_FLOAT, false, 0, 0); 


    //used this snipped before when using the same image (uv-coords) for all bricks 
    /*GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vboDataListLevelSprites.get(iName).getBuff_id_uvs()); 
    GLES20.glEnableVertexAttribArray(mTextureCoordinateHandle); 
    GLES20.glVertexAttribPointer(mTextureCoordinateHandle, 2, GLES20.GL_FLOAT, false, 0, 0); 
    */ 

    for (Iterator<BrickProperties> it = arrayListBricks.iterator(); it.hasNext();) { 



     BrickProperties bp = it.next(); 
     //now bindbuffer inside loop just too switch uv-coords of the atlas when its time to use another image 
     int buffIndexVal = bp.get_status_diff(); 
     GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, BrickProperties.get_buff_id_uvs()[buffIndexVal]); 
     GLES20.glEnableVertexAttribArray(mTextureCoordinateHandle); 
     GLES20.glVertexAttribPointer(mTextureCoordinateHandle, 2, GLES20.GL_FLOAT, false, 0, 0); 


     Matrix.setIdentityM(mModelMatrix, 0); 
     Matrix.translateM(mModelMatrix, 0, bp.getTranslateData()[0], bp.getTranslateData()[1], bp.getTranslateData()[2]); 

     if (bp.get_status() == 0) { 
      it.remove(); 
     } 

     render(); 
    } 
} 


private void render() { 

    GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0); 
    Matrix.multiplyMM(mMVPMatrix, 0, mViewMatrix, 0, mModelMatrix, 0); 
    GLES20.glUniformMatrix4fv(mMVMatrixHandle, 1, false, mMVPMatrix, 0); 
    Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mMVPMatrix, 0); 
    GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mMVPMatrix, 0); 
    GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 6); 
} 

我明白其中的道理,以業績下滑裏面所有的bindbuffer調用GPU,但我怎麼可能解決這個問題?

回答

1

這是一件事情,你綁定一個緩衝區的每個對象,但有另一件事是你使用2個緩衝區來繪製一個單一的對象。在render方法開始時,您還有多餘的呼叫來解除綁定緩衝區,只需刪除該緩衝區即可。

在大多數情況下(可能都是這種情況),您需要交錯頂點數據以提高性能。所以使用

{ 
    position, 
    textureCoordinates 
} 

在一個單一的緩衝區。

我看你的情況你有兩個狀態相同的對象,其中第二個將改變頂點座標但不是位置座標。如果緩衝區相對較大(我認爲沒有),共享兩者之間的位置數據可能是有意義的。反正對於這樣的共享,我建議你還是用你的緩衝結構

{ 
    position, 
    textureCoordinates, 
    secondaryTextureCoordinates 
} 

然後使用一個單獨的緩存甚至把次要紋理座標相同的緩衝液的另一部分。

因此,如果頂點緩衝區相對較小,那麼我建議您使用「圖集」程序。對於你的情況,這意味着創建兩倍的緩衝區大小,並把所有的座標(有位置重複),並把這個頂點數據,以便有一個接一個的部分。

我假設你可以很容易地爲你當前的繪圖做到這一點,並有效地減少綁定緩衝區的數量爲每個繪製調用0(你只需要綁定它在一些初始化)。現在您將擁有第二部分,您將在其中爲每個繪製元素設置屬性指針,以便您可以控制使用哪些紋理座標。這將再次出現在您的情況下可能會避免的冗餘呼叫:

由於數據結構在您的緩衝區中是一致的,因此實際上沒有理由將指針設置爲更多一次。當綁定緩衝區時,只需將它們設置到一開始,然後使用繪圖調用中的偏移量來控制實際使用的緩衝區的哪一部分GLES20.glDrawArrays(GLES20.GL_TRIANGLES, offset, 6)

如果處理得當,您的畫法應該看起來像:

for (Iterator<BrickProperties> it = arrayListBricks.iterator(); it.hasNext();) { 
    BrickProperties bp = it.next(); 

    Matrix.setIdentityM(mModelMatrix, 0); 
    Matrix.translateM(mModelMatrix, 0, bp.getTranslateData()[0], bp.getTranslateData()[1], bp.getTranslateData()[2]); 

    if (bp.get_status() == 0) { 
     it.remove(); 
    } 

    Matrix.multiplyMM(mMVPMatrix, 0, mViewMatrix, 0, mModelMatrix, 0); 
    GLES20.glUniformMatrix4fv(mMVMatrixHandle, 1, false, mMVPMatrix, 0); 
    Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mMVPMatrix, 0); 
    GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mMVPMatrix, 0); 
    GLES20.glDrawArrays(GLES20.GL_TRIANGLES, bp.vertexOffset, 6); 
} 

這將刪除所有綁定,並只保留矩陣運算和繪圖調用。如果管道中有其他圖紙,則在循環之前需要緩衝區綁定,否則可能會將其作爲初始化的一部分。在這兩種情況下,呼叫都應該顯着減少。

要在此添加註釋,通常會有另一個跟蹤openGL狀態的對象以避免多餘的調用。您不用打電話GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, bufferID..,而是打電話給contextObject.bindVertexBuffer(bufferID),這樣可以檢查bufferID是否與以前的呼叫相同。如果是,那麼就不會有實際的約束力。如果你創建和使用這樣的系統,那麼你在調用緩衝區綁定和對象設置的其餘部分的地方几乎沒有什麼區別,因爲多餘的調用將不起作用。單單這個程序不會使你的情況達到最佳狀態,所以你仍然需要兩個。

+0

謝謝 - 我會仔細研究一下。我想我找到了問題 – java

1

您可以綁定緩衝區並一次繪製具有相同UV-s的所有對象。而不是迭代每個磚塊,遍歷所有使用相同UV-s的對象。

此外,請嘗試批處理對象,以便一次繪製所有對象。使用索引緩衝區對象可能對此有所幫助。

+0

好主意:) :) :) – java