GLSL初識

什麼是GLSL?

        GLSL 全稱爲 OpenGL Shading Language ,是用來在OpenGL中編寫着色器程序的語言。用GLSL編寫的着色器程序是在圖形卡的GPU (Graphic Processor Unit圖形處理單元)上執行的,代替了固定的渲染管線的一部分,使渲染管線中不一樣層次具備可編程性。好比:視圖轉換、投影轉換、顏色混合等等。GLSL(GL Shading Language)的着色器代碼分紅2個部分:Vertex Shader(頂點着色器)和Fragment(片元着色器),有時還會有Geometry Shader(幾何着色器)。
程序員

GLSL語法初探

標識符

      標識符其實就是程序員自定義的變量名、函數名等等。變量名能夠由下劃線、數組、字母組成,咱們能夠隨便用下劃線、數組、字母定義變量名可是須要注意一下幾點:編程

  1. 不能以數字開頭
  2. 不能以gl_開頭,gl_是GLSL保留的前綴,用於GLSL的內部變量,好比gl_Position等等;
  3. 另外關鍵字和一些GLSL內部保留的名稱也是不可以做爲變量名的

數據類型

     在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

mat3x2

a floating-point matrix with 3 columns and 2 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

編譯時常量,其值必須在聲明時初始化,或只讀的函數參數。

attribute

爲每一個頂點數據鏈接頂點着色器和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

vec4

包含主顏色的插值,只讀輸入

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能夠參考官方文檔

相關文章
相關標籤/搜索