Opengl es 2.0實現(xiàn)了可編程的圖形管線,比起1.x的固定管線要復雜和靈活很多,由兩部分規(guī)范組成:Opengl es 2.0 API規(guī)范和Opengl es著色語言規(guī)范。下圖是Opengl es 2.0渲染管線,陰影部分是opengl es 2.0的可編程階段。
1. 頂點著色器(VertexShader)
頂點著色器對頂點實現(xiàn)了一種通用的可編程方法。
頂點著色器的輸入數(shù)據(jù)由下面組成:
Attributes:使用頂點數(shù)組封裝每個頂點的數(shù)據(jù),一般用于每個頂點都各不相同的變量,如頂點位置、顏色等。
Uniforms:頂點著色器使用的常量數(shù)據(jù),不能被著色器修改,一般用于對同一組頂點組成的單個3D物體中所有頂點都相同的變量,如當前光源的位置。
Samplers:這個是可選的,一種特殊的uniforms,表示頂點著色器使用的紋理。
Shader program:頂點著色器的源碼或可執(zhí)行文件,描述了將對頂點執(zhí)行的操作。
頂點著色器的輸出數(shù)據(jù)是varying變量,在圖元光柵化階段,這些varying值為每個生成的片元進行計算,并將結果作為片元著色器的輸入數(shù)據(jù)。從分配給每個頂點的原始varying值來為每個片元生成一個varying值的機制叫做插值。
頂點著色器數(shù)據(jù)的輸入和輸出可以參考下圖:
頂點著色器可用于傳統(tǒng)的基于頂點的操作,例如:基于矩陣變換位置,進行光照計算來生成每個頂點的顏色,生成或者變換紋理坐標。
另外因為頂點著色器是由應用程序指定的,所以你可以用來進行任意自定義的頂點變換。
下面是一個用opengl es著色器語言編寫的頂點著色器源碼,這個頂點著色器使用一個position和跟它相關聯(lián)的color數(shù)據(jù)作為輸入數(shù)據(jù),通過一個4×4矩陣變換位置,然后輸出變換后的位置和顏色數(shù)據(jù)。
第2行代碼定義了一個uniform變量u_mvpMatrix,mat4表示4×4浮點數(shù)矩陣,該變量存儲了組合模型視圖和投影矩陣。6和7行代碼定義了頂點著色器的輸入數(shù)據(jù):Attributes,vec4表示包含了4個浮點數(shù)的向量,a_position是頂點位置屬性,a_color是頂點顏色屬性。第10行代碼定義了varying類型的變量v_color,varying是用于從頂點著色器傳遞到片元著色器的變量,v_color是頂點著色器的輸出數(shù)據(jù),存儲了每個頂點的顏色。12-17行的main函數(shù)是頂點著色器和片元著色器的入口,第15行讀取了頂點著色器輸入屬性中a_color的值,并把它賦值給輸出數(shù)據(jù)v_color,第16行的gl_Position 是內(nèi)置的varying變量,不需要聲明,頂點著色器必須把變換后的位置賦值給它。 2.圖元裝配(Primitive Assembly) 3. 光柵化(Rasterization)
4. 片元著色器(FragmentShader)
片元著色器對片元實現(xiàn)了一種通用的可編程方法,它對光柵化階段產(chǎn)生的每個片元進行操作,需要的輸入數(shù)據(jù)如下:
Varying variables:頂點著色器輸出的varying變量經(jīng)過光柵化插值計算后產(chǎn)生的作用于每個片元的值。
Uniforms:片元著色器使用的常量數(shù)據(jù)
Samplers:一種特殊的uniforms,表示片元著色器使用的紋理。
Shader program:片元著色器的源碼或可執(zhí)行文件,描述了將對片元執(zhí)行的操作。
片元著色器也可以丟棄片元或者為片元生成一個顏色值,保存到內(nèi)置變量gl_FragColor。光柵化階段產(chǎn)生的顏色、深度、模板和屏幕坐標(Xw, Yw)成為流水線中pre-fragment階段(FragmentShader之后)的輸入。如下圖:
下面是一個簡單的片元著色器源碼,可以跟上面的頂點著色器源碼結合繪制一個高洛德著色的三角形。
第1行代碼設置默認的精度修飾符,有highp、mediump、lowp,這個后面再詳細解釋。第3行代碼定義了片元著色器的輸入數(shù)據(jù),頂點著色器必須賦值給片元著色器一組一樣的varying變量。注意:gl_FragColor是片元著色器唯一的輸出,第9行代碼把輸入數(shù)據(jù)v_color賦值給gl_FragColor。 5. 逐個片元操作階段(Per-Fragment Operations) Pixel ownership test:像素所有權測試決定framebuffer中某一個(Xw, Yw)位置的像素是否屬于當前Opengl ES的context,比如:如果一個Opengl ES幀緩沖窗口被其他窗口遮住了,窗口系統(tǒng)將決定被遮住的像素不屬于當前Opengl ES的context,因此也就不會被顯示。 注意:Opengl ES 2.0 的Per-Fragment Operations已經(jīng)不再支持Alpha test 和 LogicOp了,這兩個步驟在 OpenGL 2.0 和 OpenGL ES 1.x中是存在的。Alpha test 階段不再需要的原因是片元著色器可以丟棄片元,所以可以在片元著色器中執(zhí)行Alpha test。 LogicOp因為很少使用,所以不再支持了。 |
|