2010-03-23 44 views
6

我想知道是否有人可以建議在Android Java & OpenGL ES應用程序中加載紋理的好模式。在Android OpenGL ES應用程序中加載紋理

我首先關心的是確定要分配多少個紋理名稱,以及如何在渲染頂點之前有效地執行此操作。

我的第二個問題是加載紋理時,我必須根據我的遊戲數據來推斷要加載的紋理。這意味着我會玩弄字符串,我明白這是我在GL線程中不應該做的事情。

總體而言,我瞭解加載紋理時發生了什麼,我只想從中獲得最好的生命週期。還有什麼我應該考慮的事情嗎?

回答

14

1)您應該根據需要分配儘可能多的紋理名稱。一個用於你正在使用的每個紋理。

加載紋理是一個非常繁重的操作,它會停止渲染管線。所以,你不應該在遊戲循環中加載紋理。在渲染紋理的應用程序狀態之前,您應該有一個加載狀態。加載狀態負責加載渲染中所需的所有紋理。所以當你需要渲染你的幾何圖形時,你將會加載所有的紋理,你不必再擔心它。

請注意,在您不再需要紋理之後,您必須使用glDeleteTextures將其刪除。 2)如果你的意思是推斷你需要不同的紋理或不同的層次或類似的東西,那麼你應該在加載狀態下處理關卡數據並決定需要加載哪些紋理。另一方面,如果您需要繪製文本(如當前分數),那麼OpenGL中的事情會變得更加複雜。您將有以下選擇:將所需文本預渲染到紋理(簡單),實現自己的位圖字體引擎(較難)或使用位圖和畫布對快速生成紋理(較慢)。

如果您在遊戲中顯示的消息數量有限,那麼我很可能會將它們預渲染爲紋理,因爲實現非常簡單。

對於當前分數,只需具有一個紋理,該紋理的數字從0到9的字形,並使用該紋理來渲染任意值。實現將非常簡單。

如果您需要更長的本地化文本,那麼您需要開始思考即時生成紋理。基本上你會創建一個使用Canvas呈現文本的位圖。然後,您會將其作爲紋理上傳並將其渲染爲任何其他紋理。在你不再需要它之後,你會刪除它。這個選項很慢,應該在應用程序循環中避免。

3)關於紋理和獲得最好的GPU,你至少應該在腦海中保留下面的東西(這些東西會更先進一些,只有在你獲得應用程序後,你才應該打擾他們如果您需要優化幀率):

  • 最小化紋理更改,因爲它是一個緩慢的操作。理想情況下,您應該使用同一個紋理批量渲染所有對象。然後改變紋理並渲染需要的對象 等等。
  • 使用紋理圖集來最小化紋理的數量(和紋理更改)
  • 如果您有很多紋理,則可能需要使用比8888更多的位深度才能使所有紋理適合內存。使用較低的位深度也可以提高性能。
+2

當你說「加載狀態」時,是否可以在初始化我的渲染器的同時正常運行? 我目前的想法是讓它初始化我的場景圖並查詢場景圖中的所有對象,以獲得最終要求的紋理(通過讓它們從遊戲模型中推斷出名稱)。 然後,每個請求紋理的對象都將被提供相應的OpenGL整數「名稱」的紋理它要求。 這聽起來好聽嗎? – 2010-03-24 19:57:27

+2

我喜歡使用狀態機爲高級應用程序邏輯建模。因此術語加載狀態。 在完成初始化的其餘部分的同時完成此操作是完全正確的。這只是你想如何設計你的應用程序邏輯的問題。 所以它看起來很合理。 – Lauri 2010-03-25 06:35:16

2

這應該是對勞裏的回答評論,但我不能與1名代表發表意見,而且也應該指出的一件事:

您應該重新加載紋理每次您EGL上下文丟失(即,當你的應用程序被放置到後臺並返回時)。所以,(重新)加載它們的正確位置在於渲染器的方法

public void onSurfaceChanged(GL10 gl, int width, int height) 

。顯然,如果你有不同的紋理集要根據你正在玩的遊戲級別進行加載,那麼當你改變級別時,你應該刪除你不打算使用的紋理並加載新的紋理。另外,您必須跟蹤在EGL上下文丟失時必須重新加載的內容。