GLSL 全稱爲 OpenGL Shading Language ,是用來在OpenGL中編寫着色器程序的語言。用GLSL編寫的着色器程序是在圖形卡的GPU (Graphic Processor Unit圖形處理單元)上執行的,代替了固定的渲染管線的一部分,使渲染管線中不一樣層次具備可編程性。好比:視圖轉換、投影轉換、顏色混合等等。GLSL(GL Shading Language)的着色器代碼分紅2個部分:Vertex Shader(頂點着色器)和Fragment(片元着色器),有時還會有Geometry Shader(幾何着色器)。
程序員
標識符其實就是程序員自定義的變量名、函數名等等。變量名能夠由下劃線、數組、字母組成,咱們能夠隨便用下劃線、數組、字母定義變量名可是須要注意一下幾點:編程
在GLSL中僅支持下列基礎數據類型,須要注意的是與C語言相比GLSL中並無字符、字符串、指針這些類型。數組
Typebash |
Meaningapp |
void函數 |
for functions that do not return a valuepost |
boolui |
a conditional type, taking on values of true or falsespa |
intscala |
a signed integer |
float |
a single floating-point scalar |
vec2 |
a two component floating-point vector |
vec3 |
a three component floating-point vector |
vec4 |
a four component floating-point vector |
bvec2 |
a two component Boolean vector |
bvec3 |
a three component Boolean vector |
bvec4 |
a four component Boolean vector |
ivec2 |
a two component integer vector |
ivec3 |
a three component integer vector |
ivec4 |
a four component integer vector |
mat2 |
a 2×2 floating-point matrix |
mat3 |
a 3×3 floating-point matrix |
mat4 |
a 4×4 floating-point matrix |
mat2x2 |
same as a mat2 |
mat2x3 |
a floating-point matrix with 2 columns and 3 rows |
mat2x4 |
a floating-point matrix with 2 columns and 4 rows |
mat3x3 |
same as a mat3 |
mat3x4 |
a floating-point matrix with 3 columns and 4 rows |
mat4x2 |
a floating-point matrix with 4 columns and 2 rows |
mat4x3 |
a floating-point matrix with 4 columns and 3 rows |
mat4x4 |
same as a mat4 |
sampler1D |
a handle for accessing a 1D texture |
sampler2D |
a handle for accessing a 2D texture |
sampler3D |
a handle for accessing a 3D texture |
samplerCube |
a handle for accessing a cube mapped texture |
sampler1DShadow |
a handle for accessing a 1D depth texture with comparison |
sampler2DShadow |
a handle for accessing a 2D depth texture with comparison
|
除了以上這些基礎數據類型,GLSL中還支持由以上這些類型組合而成的結構體、數組等複合數據類型
能夠用struct 關鍵字將已定義的數據類型聚合到一塊兒造成結構體,好比:
struct light {
float intensity;
vec3 position;
} lightVar;複製代碼
結構體具體用法和C語言差很少這裏就很少贅敘了;數組同樣具體用法和C語言差很少,只不過在GLSL中不支持多維數組,也就是說數組的元素不能是數組。
GLSL中變量的定義能夠在類型前面指定存儲限定符,例如:
attribute vec4 position
uniform vec3 color = vec3(0.7, 0.7, 0.2)複製代碼
GLSL中常見的存儲限定符以下表:
限定符
|
意思 |
< none: default > |
默認的,可省略,這種狀況下僅僅提供一個對相關處理器上內存的讀寫權限 |
const |
編譯時常量,其值必須在聲明時初始化,或只讀的函數參數。 |
爲每一個頂點數據鏈接頂點着色器和OpenGL。因此attribute表示只讀的頂點數據,僅用在頂點着色器中。其數據來自當前的頂點狀態或者頂點數組。它必須是全局範圍聲明的,不能再函數內部。attribute修飾的變量能夠是浮點數類型的標量,向量,或者矩陣。不能夠是數組或則結構體 |
|
uniform |
統一變量。在着色器執行期間統一變量的值是不變的,與const常量不一樣的是,這個值在編譯時期是未知的,是由着色器外部初始化的。統一變量在頂點着色器和片斷着色器之間是共享的。它也只能在全局範圍進行聲明。 |
varying |
頂點着色器的輸出。例如顏色或者紋理座標,(插值後的數據)做爲片斷着色器的只讀輸入數據。必須是全局範圍聲明的全局變量。能夠是浮點數類型的標量,向量,矩陣。不能是數組或者結構體。 |
centroid varying |
在沒有多重採樣的狀況下,與varying是同樣的意思。在多重採樣時,centorid varying在光柵化的圖形內部進行求值而不是在片斷中心的固定位置求值。 |
限定符 |
說明 |
< none: default > |
默認使用 in 限定符 |
in |
in函數參數的默認限定符,傳入形參的實際上是實參的一份拷貝.在函數中,修改in修飾的形參不會影響到實參變量自己 |
out |
out做用是向函數外部傳遞新值,out傳遞進來的參數是write-only的,就像是一個"坑位",坑位中的值須要函數給他賦予. 在函數中,修改out修飾的形參會影響到實參自己. |
inout |
inout 能夠被理解爲是一個帶值的"坑位",及可讀也可寫,在函數中,修改inout修飾的形參會影響到實參自己. |
GLSL內部爲咱們預先定義了一批具備特殊含義的變量,方便開發者使用,這些變量就是內置變量,在頂點着色器中有着以下的內置變量:
名稱 |
類型 |
描述 |
gl_Color |
vec4 |
輸入屬性-表示頂點的主顏色 |
gl_SecondaryColor |
vec4 |
輸入屬性-表示頂點的輔助顏色 |
gl_Normal |
vec3 |
輸入屬性-表示頂點的法線值 |
gl_Vertex |
vec4 |
輸入屬性-表示物體空間的頂點位置 |
gl_MultiTexCoordn |
vec4 |
輸入屬性-表示頂點的第n個紋理的座標 |
gl_FogCoord |
float |
輸入屬性-表示頂點的霧座標 |
gl_Position |
vec4 |
輸出屬性-變換後的頂點的位置,用於後面的固定的裁剪等操做。全部的頂點着色器都必須寫這個值。 |
gl_ClipVertex |
vec4 |
輸出座標,用於用戶裁剪平面的裁剪 |
gl_PointSize |
float |
點的大小 |
gl_FrontColor |
vec4 |
正面的主顏色的varying輸出 |
gl_BackColor |
vec4 |
背面主顏色的varying輸出 |
gl_FrontSecondaryColor |
vec4 |
正面的輔助顏色的varying輸出 |
gl_BackSecondaryColor |
vec4 |
背面的輔助顏色的varying輸出 |
gl_TexCoord[] |
vec4 |
紋理座標的數組varying輸出 |
gl_FogFragCoord |
float |
霧座標的varying輸出 |
片元着色器中內置變量:
類型 |
描述 |
|
gl_Color |
包含主顏色的插值,只讀輸入
|
|
gl_SecondaryColor |
vec4 |
包含輔助顏色的插值,只讀輸入 |
gl_TexCoord[] |
vec4 |
包含紋理座標數組的插值,只讀輸入 |
gl_FogFragCoord |
float |
包含霧座標的插值,只讀輸入 |
gl_FragCoord |
vec4 |
窗口的x,y,z和1/w,只讀輸入 |
gl_FrontFacing |
bool |
只讀輸入,若是是窗口正面圖元的一部分,則這個值爲true |
gl_PointCoord |
vec2 |
點精靈的二維空間座標範圍在(0.0, 0.0)到(1.0, 1.0)之間,僅用於點圖元和點精靈開啓的狀況下。 |
gl_FragData[] |
vec4 |
使用glDrawBuffers輸出的數據數組。不能與gl_FragColor結合使用。 |
gl_FragColor |
vec4 |
輸出的顏色用於隨後的像素操做 |
gl_FragDepth |
float |
輸出的深度用於隨後的像素操做,若是這個值沒有被寫,則使用固定功能管線的深度值代替 |
操做符 |
描述 |
() |
用於表達式組合,函數調用,構造 |
[] |
數組下標,向量或矩陣的選擇器 |
. |
結構體和向量的成員選擇 |
++ – |
前綴或後綴的自增自減操做符 |
+ – ! |
一元操做符,表示正 負 邏輯非 |
* / |
乘 除操做符 |
+ - |
二元操做符 表示加 減操做 |
<> <= >= == != |
小於,大於,小於等於, 大於等於,等於,不等於 判斷符 |
&& || ^^ |
邏輯與 ,或, 異或 |
?: |
條件判斷符 |
= += –= *= /= |
賦值操做符 |
, |
表示序列 |
須要注意的是取地址符&和解引用的 * 操做在GLSL中是不存在的,由於GLSL不能直接操做地址。類型轉換操做也是不容許的。 位操做符(&,|,^,~, <<, >> ,&=, |=, ^=, <<=, >>=)是GLSL保留的操做符,未來可能會被使用。還有求模操做(%,%=)也是保留的。
結構體的字段以及數組的長度都是經過點(.)語法來訪問的,與c語言相似,對應結構體和數組僅一下幾種操做是合法的:
field or method selector |
. |
相等判斷 |
== != |
賦值 |
= |
索引訪問[僅數組] |
[] |
須要注意的是相等判斷和賦值運算都必須是兩個類型同樣,size相同的才能進行。
除了極少數例外,一般對於向量與矩陣的操做都等價於分別對其相應份量作出一樣的操做。好比:
vec3 u,v;
float f;
v = u + f;複製代碼
上面這段代碼就等價於:
vec3 u,v;
float f;
v.x = u.x + f;
v.y = u.y + f;
v.z = u.z + f;複製代碼
同理,代碼:
vec3 v, u, w;
w = v + u;複製代碼
等價於:
w.x = v.x + u.x;
w.y = v.y + u.y;
w.z = v.z + u.z;複製代碼
其餘的操做這裏就不作多的敘述,你們能夠參考線性代數或者3D數學。這裏簡單說一下向量份量的訪問:
向量中單獨的份量能夠經過{x,y,z,w},{r,g,b,a}或者{s,t,p,q}的記法來表示。這些不一樣的記法用於頂點座標,顏色成分,紋理座標。在份量訪問中,不能夠混合使用這些記法。其中{s,t,p,q}中的p替換了紋理的r座標,由於與顏色r重複了。好比:
vec4 v4;
v4.rgba; // is a vec4 and the same as just using v4,
v4.rgb; // is a vec3,
v4.b; // is a float,
v4.xy; // is a vec2,
v4.xgba; // is illegal 複製代碼
份量的順序能夠交換也能夠重複:好比:
vec4 pos = vec4(1.0, 2.0, 3.0, 4.0);
vec4 swiz= pos.wzyx; // swiz = (4.0, 3.0, 2.0, 1.0)
vec4 dup = pos.xxyy; // dup = (1.0, 1.0, 2.0, 2.0)複製代碼
這種表達方式一樣能夠用到表達式的左邊,只是不容許重複:
vec4 pos = vec4(1.0, 2.0, 3.0, 4.0);
pos.xw = vec2(5.0, 6.0); // pos = (5.0, 2.0, 3.0, 6.0)
pos.wx = vec2(7.0, 8.0); // pos = (8.0, 2.0, 3.0, 7.0)
pos.xx = vec2(3.0, 4.0); // illegal - 'x' used twice
pos.xy = vec3(1.0, 2.0, 3.0); // illegal - mismatch between vec2 and vec3複製代碼
對於矩陣能夠當作是向量的數組,可使用數組下標語法訪問矩陣的份量。 應用單個下標 到矩陣將矩陣視爲列向量的數組,並選擇一個單列,其類型爲與矩陣大小相同的向量。 最左邊的列是列0。而後第二個下標如先前爲向量所定義,對列向量進行運算。 所以,兩個下標選擇了一列, 而後又選擇了該列的一行。好比:
mat4 m;
m[1] = vec4(2.0); // sets the second column to all 2.0
m[0][0] = 1.0; // sets the upper left element to 1.0
m[2][3] = 2.0; // sets the 4th element of the third column to 2.0複製代碼
條件控制:也就是常說的if else 語句,須要注意的是,if(條件)的條件只能是bool類型的,而且不能在if else中聲明變量,變量必須聲明在外面,好比:
vec4 color = unlitColor;
if (numLights > 0)
{
color = litColor;
}else{
color = unlitColor;
}複製代碼
循環控制:與C語言相似支持for,while,do-while 三種寫法,能夠用contine跳出本次循環,用break跳出全部循環。
discard控制:片元着色器中有一種特殊的控制流成爲discard。使用discard會退出片元着色器,不執行後面的片元着色操做,也不會寫入幀緩衝區。
在每一個shader中必須有且只能有一個main函數。GLSL中的函數,必須是在全局範圍定義和聲明。不能在函數定義中聲明或定義函數。函數必須有返回類型,參數是可選的。參數的修飾符(in, out, inout, const等)是可選的。
結構體和數組也能夠做爲函數的參數。若是是數組做爲函數的參數,則必須制定其大小。在調用傳參時,只傳數組名就能夠了。
另外須要注意一下幾點:
最後這裏咱們只是說了一下GLSL的一些基本語法,不過對於iOS開發者來講其實已經基本足夠了,若是想要深刻了解GLSL能夠參考官方文檔