[TOC]
OpenGL ES著色語(yǔ)言雖然是基于C/C++基本語(yǔ)法的語(yǔ)言,但是其與C/C++相比較還是有很大不同的。例如,該語(yǔ)言不支持雙精度浮點(diǎn)型(double)、字節(jié)型(byte)、短整型(short)、長(zhǎng)整型(long),并且取消了C中的聯(lián)合體(union)及枚舉類型(enum)等特性。
1. 數(shù)據(jù)類型概述
與C語(yǔ)言類似,著色語(yǔ)言中有許多內(nèi)建的原生數(shù)據(jù)類型以及構(gòu)建數(shù)據(jù)類型,如浮點(diǎn)型(float)、布爾型(bool)、有符號(hào)整型(int)、無(wú)符號(hào)整型(uint)、矩陣型(matrix)以及向量型(vec2、vec3等)等??傮w來(lái)說(shuō),這些數(shù)據(jù)類型可以分為標(biāo)量、向量、矩陣、采樣器、結(jié)構(gòu)體以及數(shù)組等幾類
-
標(biāo)量
OpenGL ES3著色語(yǔ)言支持的標(biāo)量類型有bool、int、uint與float
聲明無(wú)符號(hào)整型(uint)字面常量時(shí),需要在數(shù)字之后添加后綴u或U,否則該字面常量的類型為有符號(hào)整型
-
向量
OpenGL ES著色語(yǔ)言中,向量可以看作是用同樣類型的標(biāo)量組成的,其基本類型也分為bool、int、uint及float 四種。每個(gè)向量可以由2個(gè)、3個(gè)或者4個(gè)相同的標(biāo)量組成.
| 向 量 類 型 | 說(shuō) 明 |
|---|---|
| vec2 | 包含了2個(gè)浮點(diǎn)數(shù)的向量 |
| bvec2 | 包含了2個(gè)布爾數(shù)的向量 |
| vec3 | 包含了3個(gè)浮點(diǎn)數(shù)的向量 |
| bvec3 | 包含了3個(gè)布爾數(shù)的向量 |
| vec4 | 包含了4個(gè)浮點(diǎn)數(shù)的向量 |
| bvec4 | 包含了4個(gè)布爾數(shù)的向量 |
| ivec2 | 包含了2個(gè)整數(shù)的向量 |
| uvec2 | 包含了2個(gè)無(wú)符號(hào)整數(shù)的向量 |
| ivec3 | 包含了3個(gè)整數(shù)的向量 |
| uvec3 | 包含了3個(gè)無(wú)符號(hào)整數(shù)的向量 |
| ivec4 | 包含了4個(gè)整數(shù)的向量 |
| uvec4 | 包含了4個(gè)無(wú)符號(hào)整數(shù)的向量 |
若向量是4維的,當(dāng)看作顏色使用時(shí),則可以使用的分量名為:r、g、b、a;
若向量是4維的,當(dāng)看作位置使用時(shí),則可以使用的分量名為:x、y、z、w;
若向量是4維的,當(dāng)看作紋理坐標(biāo)使用時(shí),則可以使用的分量名為:s、t、p、q;
訪問(wèn)向量中的各個(gè)分量不但可以采用“.”加上不同的分量名,還可以將向量看作一個(gè)數(shù)組,用下標(biāo)來(lái)進(jìn)行訪問(wèn)
aColor.r=0.6; //給向量aColor的紅色通道分量賦值
aColor.g=0.8; //給向量aColor的綠色通道分量賦值
aPosition.x=67.2; //給向量aPosition的X分量賦值
aPosition.z=48.3; //給向量aPosition的Z分量賦值
aTexCoor.s=0.65; //給向量aTexCoor的s分量賦值
aTexCoor.t=0.34; //給向量aTexCoor的t分量賦值
aColor[0]=0.6; //給向量aColor的紅色通道分量賦值
aPosition[2]=48.3; //給向量aPosition的z軸分量賦值
aTexCoor[1]=0.34; //給向量aTexCoor的t分量賦值
-
矩陣
矩陣按尺寸分為2×2矩陣、2×3矩陣和2×4矩陣、3×2矩陣、3×3矩陣和3×4矩陣以及4×2矩陣、4×3矩陣和4×4矩陣,其中矩陣類型的第一個(gè)數(shù)字表示矩陣的列數(shù),第二個(gè)數(shù)字表示矩陣的行數(shù),具體情況如表4-2所列。
| 矩 陣 類 型 | 說(shuō) 明 |
|---|---|
| mat2 | 2×2的浮點(diǎn)數(shù)矩陣 |
| mat2×2 | 2×2的浮點(diǎn)數(shù)矩陣 |
| mat3 | 3×3的浮點(diǎn)數(shù)矩陣 |
| mat2×3 | 2×3的浮點(diǎn)數(shù)矩陣 |
| mat4 | 4×4的浮點(diǎn)數(shù)矩陣 |
| mat2×4 | 2×4的浮點(diǎn)數(shù)矩陣 |
| mat3×2 | 3×2的浮點(diǎn)數(shù)矩陣 |
| mat4×2 | 4×2的浮點(diǎn)數(shù)矩陣 |
| mat3×3 | 3×3的浮點(diǎn)數(shù)矩陣 |
| mat4×3 | 4×3的浮點(diǎn)數(shù)矩陣 |
| mat3×4 | 3×4的浮點(diǎn)數(shù)矩陣 |
| mat4×4 | 4×4的浮點(diǎn)數(shù)矩陣 |
OpenGL ES著色語(yǔ)言中,矩陣是按列順序組織的,也就是一個(gè)矩陣可以看作由幾個(gè)列向量組成。例如,mat3就可以看作由3個(gè)vec3組成。另外,mat2與mat2×2、mat3與mat3×3以及mat4與mat4×4是3組兩兩完全相同的類型,只是其類型的名稱不同而已。
-
采樣器
采樣器是著色語(yǔ)言中不同于C語(yǔ)言的一種特殊的基本數(shù)據(jù)類型,其專門用來(lái)進(jìn)行紋理采樣的相關(guān)操作。一般情況下,一個(gè)采樣器變量代表一幅或一套紋理貼圖。
| 采樣器類型 | 說(shuō) 明 |
|---|---|
| sampler2D | 用于訪問(wèn)浮點(diǎn)型的二維紋理 |
| isampler3D | 用于訪問(wèn)整型的三維紋理 |
| sampler3D | 用于訪問(wèn)浮點(diǎn)型的三維紋理 |
| isamplerCube | 用于訪問(wèn)整型的立方貼圖紋理 |
| samplerCube | 用于訪問(wèn)浮點(diǎn)型的立方貼圖紋理 |
| isampler2DArray | 用于訪問(wèn)整型的2D紋理數(shù)組 |
| samplerCubeShadow | 用于訪問(wèn)浮點(diǎn)型的立方陰影紋理 |
| usampler2D | 用于訪問(wèn)無(wú)符號(hào)整型的二維紋理 |
| sampler2DShadow | 用于訪問(wèn)浮點(diǎn)型的二維陰影紋理 |
| usampler3D | 用于訪問(wèn)無(wú)符號(hào)整型的三維紋理 |
| sampler2DArray | 用于訪問(wèn)浮點(diǎn)型的2D紋理數(shù)組 |
| usamplerCube | 用于訪問(wèn)無(wú)符號(hào)整型的立方貼圖紋理 |
| sampler2DArrayShadow | 用于訪問(wèn)浮點(diǎn)型的2D陰影紋理數(shù)組 |
| usampler2DArray | 用于訪問(wèn)無(wú)符號(hào)整型的2D紋理數(shù)組 |
| isampler2D | 用于訪問(wèn)整型的二維紋理 |
需要注意的是,與前面介紹的幾類變量不同,采樣器變量不能在著色器中進(jìn)行初始化。一般情況下采樣器變量都用uniform限定符來(lái)修飾,從宿主語(yǔ)言(如C++、Java)接收傳遞進(jìn)著色器的值。此外,采樣器變量也可以用作函數(shù)的參數(shù),但是作為函數(shù)參數(shù)時(shí)不可以使用out或inout修飾符來(lái)修飾。
-
結(jié)構(gòu)體
OpenGL ES著色語(yǔ)言還提供了類似于C語(yǔ)言中的用戶自定義結(jié)構(gòu)體,同樣也是使用struct關(guān)鍵字進(jìn)行聲明,基本用法與C語(yǔ)言基本類似,不在此贅述了。
-
數(shù)組
在著色語(yǔ)言中,開(kāi)發(fā)人員可以聲明任何類型的數(shù)組。聲明數(shù)組的方式主要有兩種,具體如下所列。
(1). 在聲明數(shù)組的同時(shí),指定數(shù)組的大小:
vec3 position[20]; //聲明了一個(gè)包含20個(gè)vec3的數(shù)組,索引從0開(kāi)始
(2). 在聲明數(shù)組并初始化的同時(shí),可以不指定數(shù)組的大小,不支持動(dòng)態(tài)長(zhǎng)度數(shù)組
float x[]=float[2](1.0,2.0); //數(shù)組的長(zhǎng)度為2
float y[]=float[](1.0,2.0,3.0); //數(shù)組的長(zhǎng)度為3
OpenGL ES 3.0的著色語(yǔ)言只支持一維數(shù)組的使用,不支持二維以及更多維數(shù)組的使用。
2. 運(yùn)算符
| 運(yùn) 算 符 | 說(shuō) 明 |
|---|---|
| () | 括號(hào)分組 |
| [ ] | 數(shù)組下標(biāo) |
| () | 函數(shù)調(diào)用和構(gòu)造函數(shù)結(jié)構(gòu) |
| . | 用于成員選擇與混合 |
| ++ -- | 自加1與自減1后綴 |
| ++ -- | 自加1與自減1 前綴 |
| + - ~ ! | 一元運(yùn)算符 |
| * / % | 乘法、除法和取余 |
| + - | 加法與減法 |
| << >> | 逐位左移和右移 |
| < > <= >= | 關(guān)系運(yùn)算符 |
| == != | 等于以及不等于 |
| & | 逐位與 |
| ^ | 逐位異或 |
| | | 逐位或 |
| && | 邏輯與 |
| ^^ | 邏輯異或 |
| || | 邏輯或 |
| ?: | 選擇 |
| = += -= *= /= | 賦值運(yùn)算符 |
| %= <<= >>= &= ^= |= | 賦值運(yùn)算符 |
| , | 按順序排列 |
-
OpenGLES運(yùn)算符的特殊操作
某些OpenGLES的運(yùn)算符有不同于c語(yǔ)言的操作,下面簡(jiǎn)單介紹下。
- 通過(guò)運(yùn)算符“.”進(jìn)行混合選擇操作
在運(yùn)算符“.”之后列出一個(gè)向量中需要的各個(gè)分量的名稱,就可以選擇并重新排列這些分量。下面的代碼片段說(shuō)明了這個(gè)問(wèn)題。
vec4 color= vec4(0.7,0.1,0.5,1.0); //聲明一個(gè)vec4類型的向量color
vec3 temp=color.agb; //相當(dāng)于獲取到一個(gè)向量(1.0,0.1,0.5)賦值給temp
vec4 tempL=color.aabb; //相當(dāng)于獲取到一個(gè)向量(1.0,1.0,0.5,0.5)賦值給tempL
vec3 tempLL; //聲明了一個(gè)3維向量tempLL
tempLL.grb=color.aab; //對(duì)向量tempLL的3個(gè)分量賦值
一次出現(xiàn)的各部分的分量名稱必須是來(lái)自同一名稱組。3個(gè)名稱組分別為:xyzw、rgba、stpq
3. 構(gòu)造函數(shù)
-
矩陣的構(gòu)造函數(shù)
矩陣的構(gòu)造函數(shù)共有3種基本形式。
- 如果矩陣的構(gòu)造函數(shù)內(nèi)只有一個(gè)標(biāo)量值,那么矩陣的對(duì)角線上的分量都等于該值,其余值為0。
- 矩陣可以由許多向量構(gòu)造而成。比如說(shuō),一個(gè)mat2矩陣可以由兩個(gè)vec2構(gòu)成。
- 矩陣還可以由大量的標(biāo)量值構(gòu)成,矩陣的分量由左向右依次被賦值。
vec2 d=vec2(1.0,2.0); //d的分量值分別為1.0、2.0
mat2 e=mat2(d,d); //e的第一列和第二列均為1.0、2.0
mat3 f=mat3(e); //將矩陣e放到矩陣f的左上角,右下角剩余對(duì)角線元素的值為1,其余為0
mat4x2 g=mat4x2(d,d,d,d); //聲明一個(gè)mat4*2矩陣
mat2x3 h=mat2x3(g); //將矩陣g左上角的2*2個(gè)元素值賦值給h中的對(duì)應(yīng)元素,h矩陣的最后一行為0,0
mat3 myMat3 = mat3(1.0, 0.0, 0.0, //矩陣myMat3第一列的值
0.0, 1.0, 0.0, //矩陣myMat3第二列的值
0.0, 1.0, 1.0); //矩陣myMat3第三列的值
OpenGL ES中矩陣元素的存儲(chǔ)順序以列為主,即矩陣由列向量組成。因此,當(dāng)使用矩陣的構(gòu)造函數(shù)時(shí),矩陣的元素將會(huì)按照矩陣的列的順序依次被參數(shù)賦值。這一點(diǎn)從上述代碼片段的第5行有所體現(xiàn)
其他數(shù)據(jù)類型的構(gòu)造函數(shù)和C語(yǔ)言一樣,不再贅述。
類型轉(zhuǎn)換
OpenGL ES著色語(yǔ)言沒(méi)有提供類型的自動(dòng)提升功能,并且對(duì)類型匹配的要求十分嚴(yán)格。賦值表達(dá)式中的兩個(gè)操作數(shù)類型必須完全相同,另外調(diào)用函數(shù)時(shí)的形參以及實(shí)參的類型也必須完全相同。
同時(shí)OpenGL ES著色語(yǔ)言也沒(méi)有提供數(shù)據(jù)類型的強(qiáng)制轉(zhuǎn)換功能,只能使用構(gòu)造函數(shù)來(lái)完成類型轉(zhuǎn)換。
float f=1.0; //聲明一個(gè)浮點(diǎn)數(shù)f并賦值
bool b=bool(f); //將浮點(diǎn)數(shù)轉(zhuǎn)換成布爾類型,該構(gòu)造函數(shù)將非0的數(shù)字轉(zhuǎn)為true,0轉(zhuǎn)為false
float f1=float(b); //將布爾值轉(zhuǎn)變?yōu)楦↑c(diǎn)數(shù),true轉(zhuǎn)換為1.0,false轉(zhuǎn)換為0.0
int c=int(f1); //將浮點(diǎn)數(shù)轉(zhuǎn)換成有符號(hào)或者無(wú)符號(hào)整型,直接去掉小數(shù)部分
存儲(chǔ)限定符
這些限定符中大部分只能用來(lái)修飾全局變量,主要的如下所列。
| 限 定 符 | 說(shuō) 明 |
|---|---|
| const | 用于聲明常量 |
| in/centroid in | 一般用于聲明著色器的輸入變量,如頂點(diǎn)著色器中用來(lái)接收頂點(diǎn)位置、顏色等數(shù)據(jù)的變量,centroid in變量與插值類型有關(guān) |
| out/centroid out | 一般用來(lái)聲明著色器的輸出變量,如從頂點(diǎn)著色器向片元著色器傳遞的頂點(diǎn)位置等數(shù)據(jù)的變量,centroid out變量與插值類型有關(guān) |
| uniform | 一般用于對(duì)同一組頂點(diǎn)組成的單個(gè)3D物體中所有頂點(diǎn)都相同的量,如當(dāng)前的光源位置 |
限定符在使用時(shí)應(yīng)該放在變量類型之前,且使用in、uniform以及out限定符修飾的變量必須為全局變量。同時(shí)要注意的是,著色語(yǔ)言中沒(méi)有默認(rèn)限定符的概念,因此如果有需要,必須為全局變量明確指定需要的限定符。