2012-05-29 54 views
9

我想用OpenGL ES 2.0在Android上批量繪製一堆線,我需要知道最好的方法來做到這一點。Android上的OpenGL ES 2.0中的快速動態頂點

現在我創建了一個名爲LineEngine的類,它建立了一個FloatBuffer,用於繪製所有的頂點,然後一次繪製所有的線。問題在於,顯然FloatBuffer.put()非常慢,並且像瘋了似的吞噬CPU時間。

這裏是我的類

public class LineEngine { 
    private static final float[] IDENTIY = new float[16]; 
    private FloatBuffer mLinePoints; 
    private FloatBuffer mLineColors; 
    private int mCount; 

    public LineEngine(int maxLines) { 
     Matrix.setIdentityM(IDENTIY, 0); 

     ByteBuffer byteBuf = ByteBuffer.allocateDirect(maxLines * 2 * 4 * 4); 
     byteBuf.order(ByteOrder.nativeOrder()); 
     mLinePoints = byteBuf.asFloatBuffer(); 

     byteBuf = ByteBuffer.allocateDirect(maxLines * 2 * 4 * 4); 
     byteBuf.order(ByteOrder.nativeOrder()); 
     mLineColors = byteBuf.asFloatBuffer(); 

     reset(); 
    } 

    public void addLine(float[] position, float[] color){ 
     mLinePoints.put(position, 0, 8); //These lines 
     mLineColors.put(color, 0, 4); // are taking 
     mLineColors.put(color, 0, 4); // the longest! 
     mCount++; 
    } 

    public void reset(){ 
     mLinePoints.position(0); 
     mLineColors.position(0); 
     mCount = 0; 
    } 

    public void draw(){ 
     mLinePoints.position(0); 
     mLineColors.position(0); 
     GraphicsEngine.setMMatrix(IDENTIY); 
     GraphicsEngine.setColors(mLineColors); 
     GraphicsEngine.setVertices4d(mLinePoints); 
     GraphicsEngine.disableTexture(); 
     GLES20.glDrawArrays(GLES20.GL_LINES, 0, mCount * 2); 
     GraphicsEngine.disableColors(); 
     reset(); 
    } 
} 

有批量所有這些線一起更好的辦法?

+0

哪個android版本是設備運行? [有關FloatBuffer的問題](http://www.badlogicgames.com/wordpress/?p=899)。 GLES20要求API等級8,所以它至少是Froyo。你可以在運行Honeycomb的設備上測試嗎? –

+0

我在Galaxy Nexus的ICS上運行它。我會仔細檢查它確實需要很長時間。 – EmbMicro

+0

我剛剛測試了批量生產線,未在我的Galaxy Nexus和EVO 4G上進行批量生產。 EVO將FPS從28.8提高到30,Galaxy Nexus保持在58.4。然而,在方法分析器中,它顯示繪圖函數(包括FloatBuffer.put和實際的OpenGL繪圖調用)佔用了更多時間。它從CPU時間的31.5%降至53.1%。這只是探查器搞亂了事情嗎? – EmbMicro

回答

1

你要做的就是所謂的SpriteBatching。如果你想讓你的程序在openGL es中穩健運行,你必須檢查以下內容(一個讓程序變慢的列表):

- 改變許多opengl ES狀態。

-Enable // Dissable(紋理等)一次又一次。一旦你啓用了一些你不需要再做的事情,它就會自動應用它的框架。

- 使用許多資產,而不是spriteSheets。是的,這會對性能產生巨大的影響。例如,如果您有10個圖像,則必須爲每個圖像加載不同的紋理,即SLOW。更好的方法是創建一個spriteSheet(你可以檢查谷歌免費的spriteSheet創建者)。

- 您的圖像質量很高。是!檢查你的分辨率和文件擴展名。首選.png文件。

- 支持api 8浮點緩衝區錯誤(您必須使用int緩衝區來修復該錯誤)。

- 使用java容器。如果你使用字符串連接(這不是一個容器,但它每次都會返回一個新字符串),或者是一個List或任何其他容器,這是最大的陷阱,因爲垃圾回收會導致程序運行緩慢。對於輸入處理,我建議你搜索一個名爲池類的teqnique。它的用途是回收對象而不是創建新對象。垃圾收集器是大敵,試圖讓他高興,並避免任何可能稱他的編程技術。

- 在運行中不加載事物,而是創建加載器類並在應用程序的開始加載所有必需的資源。

如果你確實實現了這個列表,那麼你的機會將會很強大。

最後一次加入。什麼是精靈分配器? spriteBatcher是一個使用單個紋理渲染多個對象的類。它會自動創建頂點,索引,顏色,U - V座標,並將它們作爲一個批處理。這種模式將節省GPU功耗以及CPU功耗。從你的發佈代碼,我不能確定是什麼導致CPU減速,但從我的經驗是由於我以前提到的列表中的一個(或更多)的東西。檢查列表,按照它搜索谷歌spriteBatching,我相信你的程序將運行得很快。希望我幫助!

編輯:我想我找到了什麼原因導致你的程序減速,你不要翻轉緩衝區!你只需重置位置。您只需添加添加更多對象,並導致緩衝區過載。在重置方法中,只需翻轉緩衝區。 mLineColors.flip mLinePaints.flip將完成這項工作。如果每個幀都發送新的版本,請確保每幀都稱爲它們。

+0

我早就停止了這段代碼的工作,但你的回答有很多很好的信息,如果翻轉緩衝區有了很大的改進,我也不會感到驚訝。由於舊點將被覆蓋,不會有溢出嗎?或者緩衝區不能以這種方式工作? – EmbMicro

+0

嘿,抱歉,我花了很長時間纔回答我離開了。所以,第一件事情首先是聖誕快樂!現在你的問題,一個緩衝區是一個臨時存儲大量信息的數組,它需要被處理,而不是逐個處理相同的信息直到結束。當你翻轉一個緩衝區時,它會自動調整大小,所以你不必擔心重載它(除非你提供了一個非常大的尺寸)。重載意味着如果緩衝區有10個int的容量,只要你不給11就可以了。如果你給11,那麼你將有一個緩衝區溢出。 – KostasRim

+0

覆蓋內存位置不會超載。只記得你改變了內存的價值,你不要求你的程序保留相同的內存加上新的點。你只是渲染當前幀點(舊點不再存在!)。希望我幫助,祝新年快樂:)! – KostasRim

0

FloatBuffer.put(float [])具有相對較大的float數組應該快得多。單次put(float)調用有很多開銷。

0

只要去一個非常簡單的本地函數,它將從你的類中調用。您可以直接將float[]添加到OpenGL中,無需使用愚蠢的緩衝區界面來殺死CPU時間。