天天看點

《OpenGL ES應用開發實踐指南:Android卷》—— 2.4 使資料可以被OpenGL存取

本節書摘來自華章出版社《opengl es應用開發實踐指南:android卷》一 書中的第2章,第2.4節,作者:(美)kevin brothaler ,更多章節内容可以通路雲栖社群“華章計算機”公衆号檢視。

我們已經完成頂點的定義了,但是,在opengl可以存取它們之前,我們仍然需要完成另外一步。主要的問題是這些代碼運作的環境與opengl運作的環境使用了不同的語言,我們需要了解如下兩個主要的概念。

1.當我們在模拟器或者裝置上編譯和運作java代碼的時候,它并不是直接運作在硬體上的;相反,它運作在一個特殊的環境上,即dalvik虛拟機(dalvik virtual machine);運作在虛拟機上的代碼不能直接通路本地環境(native environment),除非通過特定的api。

davik虛拟機還使用了垃圾回收(garbage collection)機制。這意味着,當虛拟機檢測到一個變量、對象或者其他記憶體片段不再被使用時,就會把這些記憶體釋放掉以備重用;它也能騰挪記憶體以提高空間使用效率。

本地環境并不是這樣工作的,它不期望記憶體塊會被移來移去或者被自動釋放。

android之是以這樣設計,是因為開發者在開發程式的時候不必關心特定的cpu或者機器架構,也不必關心底層的記憶體管理。這通常都能工作得很好,除非要與本地系統互動,比如opengl。opengl作為本地系統庫直接運作在硬體上;沒有虛拟機,也沒有垃圾回收或記憶體壓縮。

dalvik方案是android的主要特點之一,但是,如果代碼運作在虛拟機内部,那它怎麼與opengl通信呢?有兩種技術,第一種技術是使用java本地接口(jni),這個技術已經由android軟體開發包提供了;當調用android.opengl.gles20包裡的方法時,軟體開發包實際上就是在背景使用jni調用本地系統庫的。

第二種技術就是改變記憶體配置設定的方式,java有一個特殊的類集合,它們可以配置設定本地記憶體塊,并且把java的資料複制到本地記憶體。本地記憶體可以被本地環境存取,而不受垃圾回收器的管控。

我們需要按如圖2-5所示傳輸資料;在類的頂部,在構造函數之前加入如下代碼:

《OpenGL ES應用開發實踐指南:Android卷》—— 2.4 使資料可以被OpenGL存取

這裡加入了一個整型常量bytes_perfloat和一個floatbuffer類型變量;一個java的浮點數(float)有32位(bit)精度,而一個位元組(byte)隻有8位精度;這點可能看起來很明顯,每個浮點數都占用4個位元組;在後面的開發講解中,很多地方都會提到這點。那個floatbuffer用來在本地記憶體中存儲資料。

讓我們加入更多的代碼,這次加在構造函數體的結尾處:

《OpenGL ES應用開發實踐指南:Android卷》—— 2.4 使資料可以被OpenGL存取

讓我們看一下代碼的每一個部分。首先,我們使用bytebuffer.allocatedirect()配置設定了一塊本地記憶體,這塊記憶體不會被垃圾回收器管理。這個方法需要知道要配置設定多少位元組的記憶體塊;因為頂點都存儲在一個浮點數組裡,并且每個浮點數有4個位元組,是以這塊記憶體的大小應該是tableverticeswithtriangles.length * bytes_per_float。

下一行告訴位元組緩沖區(byte buffer)按照本地位元組序(native byte order)組織它的内容;本地位元組序是指,當一個值占用多個位元組時,比如32位整型數,位元組按照從最重要位到最不重要位或者相反順序排列;可以認為這與從左到右或者從右到左寫一個數類似。知道這個排序并不重要,重要的是作為一個平台要使用同樣的排序;調用order(byteorder.nativeorder())可以保證這一點。

最後,我們不願直接操作單獨的位元組,而是希望使用浮點數,是以,調用asfloatbuffer()得到一個可以反映底層位元組的floatbuffer類執行個體;然後就可以調用vertexdata.put(tableverticeswithtriangles)把資料從dalvik的記憶體複制到本地記憶體了。當程序結束的時候,這塊記憶體會被釋放掉,是以,我們一般情況下不用關心它;但是,如果你在編寫代碼的時候,建立了很多bytebuffer,或者随着程式運作産生了很多bytebuffer,你也許想學習一些堆碎片化以及記憶體管理的技術。

為了把資料從dalvik傳進opengl,用了這麼多步驟,但是在繼續講解之前,了解它是如何工作的是很重要的;就像文化和風俗一樣,國與國有很多不同,我們也要知道跨越本地代碼邊界時的差異。

繼續閱讀