OpenGLES3.0筆記 (三) —— GLSL語(yǔ)法

[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)限定符的概念,因此如果有需要,必須為全局變量明確指定需要的限定符。

插值限定符

一致塊

layout限定符

流程控制

函數(shù)聲明和使用

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容