2012年5月2日 星期三

Android 開發教學筆記 - 研究 Renderscript 之 Fountain 與 FountainFbo 的差異

fountainFbo


關於 Fountain 和 FountainFbo 的介紹,可以看 Renderscript>Graphics 官網得到更詳細的介紹,在此僅簡易筆記。


首先快速帶一下 Fountain 的特效,就是在螢幕上點擊、久按、拖拉著任何一點,這時螢幕會隨著點擊事件產生一個點畫在螢幕上,接著亂數決定這個點的顏色以及該如何移動並會隨著時間往下掉,這樣的效果就接近煙火。其中在 FountainRS 有定義最多顯示 50000 個點(PART_COUNT變數),所以拖曳時的效果又跟煙火不太一樣。而 FountainFbo 則是多顯示一塊小區域,重複繪出螢幕上的特效,並使用 Framebuffer Object。


先用 vimdiff 看一下 FountainRS.java 和 FountainFboRS.java 的差異:


$ cd ~/workspace
$ vimdiff Fountain/src/com/example/android/rs/fountain/FountainRS.java FountainFbo/src/com/example/android/rs/fountainfbo/FountainFboRS.java


java_FountainRS_FountainFboRS


扣除 package name 這類東西外,看得出來主要差別在 public void init(RenderScriptGL rs, Resources res) 中所使用的流程。


先看一下共同項目:


ProgramFragmentFixedFunction,其定義 http://developer.android.com/reference/android/renderscript/ProgramFragmentFixedFunction.html


ProgramFragmentFixedFunction is a helper class that provides a way to make a simple fragment shader without writing any GLSL code. This class allows for display of constant color, interpolated color from the vertex shader, or combinations of the both blended with results of up to two texture lookups.


Mesh,其定義 http://developer.android.com/reference/android/renderscript/Mesh.html


This class is a container for geometric data displayed with Renderscript. Internally, a mesh is a collection of allocations that represent vertex data (positions, normals, texture coordinates) and index data such as triangles and lines.


Vertex data could either be interleaved within one allocation that is provided separately, as multiple allocation objects, or done as a combination of both. When a vertex channel name matches an input in the vertex program, Renderscript automatically connects the two together.


Parts of the mesh can be rendered with either explicit index sets or primitive types.


ScriptField_Point,其定義在 renderscript 裡頭(C99語法)


typedef struct __attribute__((packed, aligned(4))) Point {
        float2 delta;
        float2 position;
        uchar4 color;
} Point_t;


ScriptField_Point 是自訂結構,定義於在 *.rs,編譯後自動產生的,用途是紀錄每一個點的資訊;Mesh為一種資料結構,用來收集一批資料,最重要的是 Renderscript 有 rsgDrawMesh API,可以一次把 Mesh 收集的資料繪出,因此程式架構上,並非用 loop 繪每個 Point,有點像寫 C 時,用 memset 取代用 loop 對 array 的初始化,更多細節請參考 Renderscript>Graphics>Drawing with a mesh;ProgramFragmentFixedFunction 對我而言是比較生疏的部份,這跟 OpenGL Shading Language (GLSL) 有關,其中 Google Translate 對 Shader 翻譯為"著色",我把 GLSL 當作繪圖相關的基本需求,另外,從描述的意思是使用 ProgramFragmentFixedFunction 可以省去從頭到尾定義 GLSL 出來,何謂 GLSL 呢?可以參考 Renderscript>Sample>Balls>BallsRS.java,裡頭有用 ProgramVertex 引入 GLSL 語法,更多細節請參考 Renderscript>Graphics>Programs


不一樣的地方:


對 FountainRS.java 來說,使用 ProgramFragmentFixedFunction 建立 GLSL 環境後,傳給 RenderScriptGL rs 環境使用,但在 FountainFboRS.java 中,多定義兩個 ProgramFragment 變數,mProgramFragment 和 mTextureProgramFragment,並且在 Renederscript 裡頭接應,接用 vimdiff 看一下 fountain.rs 和 fountainfbo.rs 的差異:


$ cd ~/workspace
$ vimdiff Fountain/src/com/example/android/rs/fountain/fountain.rs FountainFbo/src/com/example/android/rs/fountainfbo/fountainfbo.rs


rs_fountain_fountainfbo


可看出 fountain.rs 裡的東西基本上都出現在 fountainfbo.rs 了,所以了解 fountrain.rs 在 void root 做事後,可以細看 fountainfbo.rs 的變化,此部份在官網 Renderscript > Graphics > Framebuffer Object 有很多細部介紹,在此就不多提囉。


總結一下,在 fountainfbo 中採用 Framebuffer Object 的繪圖技巧,可以讓開發者先在某一處 buffer 繪圖(offscreen),繪完後在貼到螢幕上(onscreen)。


沒有留言:

張貼留言