2012-10-26 77 views
0

我已經有一個程序繪製了90個2D形狀,帶有紋理,用戶可以通過觸摸屏幕進行拾取和拖動。有很明顯的不連貫性,DDMS告訴我,佔用CPU時間最多(〜85%)的一種方法是draw()方法。由於實際上只有一個形狀正在移動,而其他89個形狀不移動,使用FrameBuffer對象將89個形狀渲染爲紋理並在填充整個屏幕的形狀上繪製該紋理可能會更快/更快?如果沒有,有沒有其他可能的加速方法?OpenGL ES2:使用FrameBuffer對象更快地渲染多個形狀

private void draw() { 
    // Pass in the position information 
    mCubePositions.position(0); 
    GLES20.glVertexAttribPointer(mPositionHandle, mPositionDataSize, GLES20.GL_FLOAT, false, 0, mCubePositions); 
    GLES20.glEnableVertexAttribArray(mPositionHandle); 

    // Pass in the color information 
    mCubeColors.position(0); 
    GLES20.glVertexAttribPointer(mColorHandle, mColorDataSize, GLES20.GL_FLOAT, false, 0, mCubeColors); 
    GLES20.glEnableVertexAttribArray(mColorHandle); 

    // Pass in the texture coordinate information 
    mCubeTextureCoordinates.position(0); 
    GLES20.glVertexAttribPointer(mTextureCoordinateHandle, mTextureCoordinateDataSize, GLES20.GL_FLOAT, false, 0, mCubeTextureCoordinates); 
    GLES20.glEnableVertexAttribArray(mTextureCoordinateHandle); 

    // This multiplies the view matrix by the model matrix, and stores the 
    // result in the MVP matrix 
    // (which currently contains model * view). 
    Matrix.multiplyMM(mMVPMatrix, 0, mViewMatrix, 0, mModelMatrix, 0); 

    // Pass in the modelview matrix. 
    GLES20.glUniformMatrix4fv(mMVMatrixHandle, 1, false, mMVPMatrix, 0); 

    // This multiplies the modelview matrix by the projection matrix, and 
    // stores the result in the MVP matrix 
    // (which now contains model * view * projection). 
    Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mMVPMatrix, 0); 

    // Pass in the combined matrix. 
    GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mMVPMatrix, 0); 

    // Draw the cube. 
    GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 6); 
} 

在此先感謝。

回答

3

當意味着四邊形時,我對引用「多維數據集」的問題感到困惑,所以這個答案處理了三維情況,無論如何這可能更有教育意義。

將視圖矩陣和投影矩陣組合成一個ViewProj矩陣。然後在垂直着色器中,執行VertexPos * Model * ViewProj。

另外你真的需要批處理。您應該有一個包含所有多維數據集的大數組,以及另一個包含每個多維數據集轉換的數組。然後你做一個所有立方體的平局。考慮將其轉換爲使用頂點緩衝區對象。繪圖調用是CPU密集型的,因爲它們在後臺的API中調用了大量的邏輯和存儲器複製等。遊戲引擎竭盡全力將其最小化。

如何使一個繪製調用汲取很多東西

將所有不同的紋理爲一個紋理(一個「圖集」),並通過調整每個立方體的UV的補償來查找相應的部分的紋理。將所有的模型矩陣放入一個連續的數組中,並在頂點着色器中索引到這個數組中。

attribute vec3 a_position; 
attribute vec2 a_texCoord; 
attribute int a_modelIndex; 
attribute int a_UVlIndex; 

uniform mat4 u_model[90]; 
uniform vec2 u_UVOffset[16]; // Support 16 different textures in our atlas. 

varying vec2 v_texCoord; 
... 

void main() 
{ 
    gl_Position = u_viewProj * u_model[a_modelIndex] * vec4(a_position, 1); 
    v_texCoord = a_texCoord + u_UVOffset[a_UVlIndex]; 
    ... 
}  

你可以收拾你所有的頂點數據到一個大陣,所以你最終做GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 6 * 90);但即使是更好的,因爲你是剛剛繪製的多維數據集的時候,你可以重新使用完全相同的頂點數據每次。模型矩陣負責其餘部分(比例尺,旋轉,平移)。要做到這一點,請使用glDrawElements而不是glDrawArrays,並且---假定三個簡單列表---指定36個索引,引用頂點數組中的36個頂點構成一個立方體,然後只需重複這36個索引90次以使您的索引數組。頂點應該是一個以(0,0,0)爲中心的單位立方體。這個相同的「立方體模板」然後被頂點着色器中的模型矩陣修改以創建每個可見的「立方體實例」。您需要更改每個框架的唯一方法是模型矩陣和紋理UV。

glVertexAttribPointer()允許您將任何喜歡的東西都投射到您的頂點着色器中,並且將模型矩陣作爲屬性而不是制服使用glVertexAttribPointer可能會更有效。

移動設備往往對像素綁定非常敏感。如果你的立方體在屏幕上很大,你可能會得到很多透支。高CPU%(畢竟它只是一個百分比)可能是一個紅鯡魚,你可能是在GPU上的像素綁定。一個簡單的測試就是讓所有的立方體非常小,看看幀率是否提高。

作爲參考,S5570有一個Adreno 200 GPU

+0

我在S5570上運行。大多數立方體非常小,改變尺寸對幀率沒有明顯影響。立方體的數量,大小和紋理根據其他立方體的位置而變化很大,每次用戶完成拖動形狀時都會發生變化。重新調整一個ArrayList並將其轉換爲一個數組並且每次都是低效率的多維數據集?我怎樣才能讓一個繪畫調用從一個數組渲染單獨的形狀? –

+0

感謝您的詳細回覆。但有一個問題:這種方法是否允許不。立方體的繪製和沒有。的紋理支持在飛行中增加或減少? –

+0

是的,儘管我建議您決定最大數量的多維數據集,並預先分配這個最大數據結構,以避免動態分配。在上面的例子中,例如,我已經允許最多16個紋理。 –