OpenGL ES pipeline簡介

作者:abamon/XTBlock

我的個人博客站:www.zy2zy.com

轉載請註明出處:http://www.zy2zy.com/articles/64.html


前言

在移動應用開發過程中用到了OpenGL ES的相關知識,雖然app已經完成了相應的功能,但是始終覺得自己的認知與真實的OpenGL ES隔了一層薄霧,因此趁着週末有時間,徹底學習一下OpenGL ES。

 

OpenGLES 簡介

OpenGL ES 是一套用於手持嵌入式設備的API,如手機、PDA等上面都可以使用到。OpenGLES是一個跨平臺的,功能完善的2D和3D圖形應用程序接口API,而且它還是免授權費的。它其實是源自於桌面系統使用的OPENGL,但是因爲目標設備不一樣,OpenGL ES不可避免的對OpenGL做了一遍精簡,比如說去除了OpenGL中的立即模式(immediate mode)、顯示列表(display list)等許多非必要的複雜特性。

OpenGL ES其實是一個狀態機,它保存一種狀態直至它改變,然後進入下一個狀態。每個狀態都有本身默認的缺省值,可以通過相關的函數進行查詢和設置。因爲OpenGL ES在流程上採用的是同一套處理順序,因此我們平常稱這一個標準的處理流程爲OpenGL ES的渲染管線(pipeline)。

OpenGL ES 2.0的標準流程圖如下:


OpenGL ES 3.0的標準流程圖如下:


從OpenGL ES Programming Guide來看,OpenGL ES 2.0 與 OpenGL ES3.0大體上是一致的,對API來說,其可使用的接口模塊也是一樣的(Graphics Pipeline圖中有陰影的模塊爲可編程API)。因此本文主要以我OpenGL ES 2.0的流程來學習OpenGL ES。

 

OpenGLES 2.0 pipeline 介紹

1、Vertex Buffer/ArrayObjects

頂點數據來源,即渲染管線的頂點輸入,通常使用Buffer object效率更好。

 

2、Vertex Shader

頂點着色器,該模塊爲可編程模塊,可以通過API來對頂點進行操作。頂點着色器是以頂點爲目標來進行處理的,如通過矩陣變換位置,根據光源生成每個頂點的顏色數據,以及計算生成或移動紋理的座標。

該模塊的輸入通常爲:

1) Attributes:來自頂點數組中每個頂點的數據

2) Uniforms:頂點着色器的常量數據,不能被着色器修改,一般用於對同一組頂點組成的3D物體中所有頂點都相同的變量,如光源的位置。

3) Samplers:一種特殊的Uniforms,頂點着色器使用的紋理,這個輸入是可選的。

4) Shader program:這個是頂點着色器上要執行的處理的代碼。

頂點着色器的輸出稱爲Varying變量(varying variables),在圖元光柵化階段,varying變量的值爲每個生成的原片進行計算(這個計算過程稱爲插值),然後作爲輸入數據輸入到片元着色器(fragment shader)。

頂點着色器的結構圖如下:


vertex shader編程示例,詳細編程規則參看《OpenGL ES2.0 Programming Guide》:

// uniforms used by the vertex shader
 uniform mat4 u_mvpMatrix; // matrix to convertP from model
 //space to normalized device space.
 
// attributes input to the vertex shader
 attribute vec4 a_position; // position value
 attribute vec4 a_color; // input vertex color
 
 //varying variables – input to the fragment shader
 varying vec4 v_color; // output vertex color
 
 void
 main()
 {
 v_color = a_color;
 gl_Position = u_mvpMatrix * a_position;
 }


3、Primitive Assembly

圖元(Primitive)是一個可以使用合適OpenGL ES指令進行渲染的幾何結構。圖元裝配(Primitive Assembly),顧名思義就是組裝圖元的意思,也就是說它會把頂點組裝成圖元,同時它也會對它組裝的圖元進行一個簡單的處理以使得在後續流程中只處理可以在屏幕中顯示的圖元。圖元裝配首先會將頂點着色器處理過的頂點組裝成一個一個獨特的可以被渲染的幾何圖元,如三角形、線、點塊紋理。在組裝好圖元之後,它會判斷該圖元是否處於屏幕的可顯示的範圍內,如果圖元完全不在屏幕的可顯示範圍內,那麼它就會丟棄該圖元,如果圖元有一部分在可顯示的範圍內,則裁切圖元,丟棄不在屏幕顯示範圍內的部分。除此之外,圖元裝配也會去判斷圖元的朝向是面向正面還是背面,如果圖元是面向背面的,那麼該圖元也會被丟棄。

 

4、Rasterization

在圖元裝配之後就是光柵化(Rasterization)圖元了,它是將上一步裝配好的圖元(點塊、線、三角形)轉換成可以畫到屏幕上的二維片(two-dimensional fragments),以便家下來的片元着色器(fragmentsshader)對它進行處理。其流程圖如下:



5、Fragment Shader

片元着色器(Fragment Shader)也是一個可編程模塊,我們可以通過OpenGL ES的對應api來對片元進行處理。片元着色器可以丟棄片元(fragment)也可以爲片元生成一個顏色值儲存在內置變量gl_FragColor中。光柵化階段生成的顏色、深度、模板和屏幕座標將成爲下一個階段——逐個片源處理(Per-Fragment operations)的輸入。

1) Varying vriables:頂點着色器計算出來的Varyingvriables經過光柵化模塊對每個片進行插值計算之後的值

2) Uniforms:片着色器模塊使用的常量數據

3) Samplers:一種特殊的uniforms類型,供片着色器使用的紋理

4) Shader program:實現片着色器裏相關處理/操作的代碼

其結構如圖:


Shader program編程示例,詳細編程規則參看《OpenGL ES 2.0 Programming Guide》:

 precision mediump float;
 varying vec4 v_color; // input vertex colorfrom vertex shader
 
void
 main(void)
 {
 gl_FragColor = v_color;
}


6、Per-FragmentOperations

在逐個片元處理階段,一個經由光柵化階段生成的片元,假如它對應的屏幕座標爲(x,y),那麼在這個階段,在該片元處理過程中,只能改動framebuff中座標爲(x,y)的像素。

其處理過程由如下流程組成:


1) Pixel ownership test:像素所有權測試,該測試是爲了確定片元座標(x,y)對應在framebuffer中的像素是否是屬於當前OpenGL ES的context,而所有權的決定方在窗口系統(Windows System),比如說:如果一個OpenGL ES幀緩衝窗口被其它窗口遮住了,那麼窗口系統會決定這個像素不屬於當前OpenGL ES的context,也就是說這個像素不應該在當前窗口中顯示

2) Scissor test:裁剪測試,該測試用於判斷片元的座標(x,y)是否處於當前OpenGL ES確定的裁剪矩形內,如果片元座標不在這個矩形裏面,那麼該片元會被丟棄

3) Stencil and depthtests:模板和深度測試,根據傳入片元的模板和深度來決定是否丟棄片元

4) Blending:混合,將新產生的片元的顏色值與framebuffer中對應座標(x,y)的像素的顏色值進行回合

5)Dithering:抖動,用於最大限度地優化用有限精度儲存framebuffer中的顏色的過程。

在經過以上過程之後,要麼丟棄片元,要麼將片元的顏色、深度、模板值寫入framebuffer的(x,y)像素。最後是丟棄片元還是寫入像素是由write mask決定的,write mask能夠完美地使顏色、深度和模板值寫入合適的像素。比如說,write mask可以設置成沒有紅色的像素被寫入framebuffer

 

最後

除此之外,OpenGL ES 2.0還提供了從framebuffer中讀取像素的接口。不過需要注意,只有像素能夠讀取,而深度與模板值是無法獲取的。

 

參考文檔:

[1]. 《OpenGL ES 2.0 ProgrammingGuide》

[2]. 《OpenGL ES 3.0 ProgrammingGuide》

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章