天天看點

着色器語言(GLSL)基礎學習一

着色器語言主要特性:

  1. 着色器語言是一門進階的圖形編輯語言和過程語言。
  2. 頂點着色器和片元着色器使用相同的語言。
  3. 基于C/C++文法及流程控制,但該語言不支援double,byte,short,long資料類型,取消了union,enum,unsigned以及位運算。

語言組成:标量,向量,矩陣,采樣器,結構體,數組

基本類型

類型 說明
void 空類型,既不傳回任何值
bool 布爾類型,true/false
int 帶符号的整數 signed integer
float 帶符号的浮點數 floating scalar
vec2,vec3,vec4 n維浮點數向量 n-component floating point vector
bvec2,bvec3,bvec4 n維布爾向量 boolea vector
ivec2,ivec3,ivec4 n維整數向量 signed integer vector
mat2,mat3,mat4 2維(2* 2),3維(3* 3),4維(4*4)浮點數矩陣 float matrix
sampler2D 2D紋理 a 2D texture
sampler3D 3D紋理 a 3D texture
samplerCube 盒紋理 cube mapped texture

GLSL的int類型 的取值範圍是16位精度。

GLSL的向量可以看做是同樣類型的标量組成,如2維向量表示為v2(x,y),3維向量表示為v3(x,y,z)

向量在着色器語言中,用于存儲以及操作顔色,位置,紋理坐标等。

單獨通路某個分量的基本文法為<向量名>·<分量名>,如顔色向量color(r,g,b,a),color.r=0.6

GLSL中,矩陣是按列順序組織的,一個矩陣可以看做由幾個列向量組成。如mat3可以看做3個vec3組成。

對于矩陣的通路,可以将矩陣看成列向量的數組。如,matrix為mat4,通路第二列,使用matrix[1],其值為一個vec4,取得第三列的第二個分量,使用matrix[2][1],其值為float;

采樣器,如sampler2D等,其專門用來進行紋理采樣的相關操作。一般情況下,一個采樣器變量代表一副或一套紋理貼圖,采樣器變量不能在着色器中初始化,一般情況下采樣器變量都用uniform限定符來修飾,從宿主語言中(如java)接受傳遞進着色器的值。

基本結構和數組

類型 說明
結構 struct type-name{} 類似C語言的結構體
數組 float foo[3] glsl隻支援1維數組,數組可以是結構體成員

基本類型間的運算:

GLSL中,沒有隐式類型的轉換,原則上要求左右兩側表達式(left-value = right-value)的類型必須一緻,如果類型不同,必須使用顯示轉換(使用構造函數轉換);

1.float與int

同類型之間直接運算,不同類型需要顯示轉換。

int a=int(2.0);
float a=float(2)*6.0+2.3;
           

2.float與vec(向量)/mat(矩陣)

vec,mat其實是由float複合而成的,當他們與float預算時,其實就是每一個分量分别于float進行運算,即逐分量運算。GLSL裡大部分涉及vec,mat的運算都是逐分量運算,逐分量運算是線性的,如vec與float運算的結果還是vec。

vec3 v=vec3(1.0,2.0,3.0);
mat3 m=mat3(1.0);
float f=10.0;
vec3 a=f*v;		//vec3(10.0,20.0,30.0)
vec3 b=v*f;  	//vec3(10.0,20.0,30.0)
mat3 c=f*m;;	//mat3(10.0)
mat3 d=m*f;	    //mat3(10.0)
           
int與vec,mat之間是不可運算的,因為vec和mat中的每一個分量都是float類型的,無法與int逐分量運算。

3.vec與vec(向量與向量)

兩向量間的運算必須保證操作數的階數都相同,即次元相同,否則不能計算。計算方式為兩操作數在同位置上的分量分别進行運算,且階數不變,其本質還是逐分量進行。

vec3 a=vec3(1.0,2.0,3.0);
vec3 b=vec3(0.1,0.2,0.3);
vec3 c=a+b;		//vec3(1.1,2.2,3.3)
vec3 d=a*b;		//vec3(0.1,0.4,0.9)
           

4.vec與mat(向量與矩陣)

要保證操作數的階數相同,且vec與mat隻存在乘法運算,且結果為vec(向量)。計算方式和線性代數中的矩陣乘法相同。

vec2 v=vec2(10.0,20.0);
mat2 m=mat2(1.0,2.0,3.0,4.0);
vec2 a=m*v;		//vec2((1.0*10.0+3.0*20.0),(2.0*10.0+4.0*20.0))  --vec2(70,100)
vec2 b=v*m		//vec2((10.0*1.0+20.0*2.0),(10.0*3.0+20.0*4.0))  --vec2(50,110)
           

向量與矩陣的乘法規則:

着色器語言(GLSL)基礎學習一
着色器語言(GLSL)基礎學習一

矩陣A,B,C; C=A*B 乘法運算注意事項:

1.A的列數等于B的行數;

2.A的行數為C的行數,B的列數為C的列數;

3.C的第m行第n列元素等于A的第m行的各個元素與B的第n列的對應元素相乘之和

4.mat與mat(矩陣和矩陣)

必須操作數的階數相同,乘法運算為線性代數運算方式。其餘的運算仍然為逐分量運算

mat2 a=mat2(1.0,2.0,3.0,4.0);
    mat2 b=mat2(10.0,20.0,30.0,40.0);
    mat2 c=a+b;		//mat2(11.0,22.0,33.0,44.0);
    mat2 d=a*b;	//mat2((1.0*10.0+3.0*20.0),(2.0*10.0+4.0*20.0),(1.0*30.0+3.0*40.0),(2.0*30.0+4.0*40.0))    --mat2(70.0,100.0,150.0,220.0)
           

矩陣乘法規則:

着色器語言(GLSL)基礎學習一

變量限定符

修飾符 說明
none (預設的,可省略)本地變量,可讀可寫,函數的輸入參數即是這種類型
const 聲明變量或函數的參數為隻讀類型
attribute 隻能存在于vertex shader(頂點着色器)中,一般用于儲存頂點或法線資料,他可以在資料緩沖區讀取資料
uniform 在運作時shader無法改變uniform變量,一般用來放置程式傳遞給shader的變換矩陣,從材質,光照參數等等
varying 主要負責在vertex(定點着色器)和fragment(片元着色器)之間傳遞變量

1.const:

被const限定符修飾的變量初始後不可變,出了局部變量,函數參數也可以使用const修飾符。結構變量可以用const修飾,但結構中的字段不行。

const變量必須在聲明時就初始化

const vec3 v=vec3(0.0,0.0,0.0);
           

局部變量隻能使用const限定符;函數參數隻能使用const限定符。

2.attribute:

attribute變量是全局隻讀的,它隻能在vertext shader中使用,隻能與浮點數,向量或矩陣變量組合,一般attribute變量用來防止程式傳遞來的模型頂點,法線,顔色,紋理等資料,它可以通路資料緩沖區。

attribute vec4 a_Position;
           

3.uniform:

uniform變量是全局且隻讀的,在整個shader執行完畢前其值不會改變,它可以和任意基本類型變量組合,一般我們使用uniform變量來放置外部程式傳遞來的環境資料(如光源位置,模型的變換矩陣等等),這些資料在運作中顯然不需要被改變。

uniform vec4 lightPosition;
           

4.varying:

varying變量是vertex shader與fragment shader之間的信使,一般在vertex shader中修改然後在fragment shader使用它,但不能在fragment shader中修改它。

//頂點着色器
varying vec4 v_Color;
void main(){ 
    ...
    v_Color = vec4(1.,1.,1.,1);
}

//片元着色器
...
varying vec4 v_Color;
void main() {
  gl_FragColor = v_Color;
}
...
           
要注意全局變量限制符隻能為 const、attribute、uniform和varying中的一個.不可複合.

繼續閱讀