GLSL基礎

OpenGL Shading Language GLSL作爲一種着色語言是純粹的和GPU打交道的計算機語言。因爲GPU是多線程並行處理器,所以GLSL直接面向SIMD模型的多線程計算。GLSL編寫的着色器函數是對每個數據同時執行的。每個頂點都會由頂點着色器中的算法處理,每個像素也都會由片段着色器中的算法處理。因此,初學者在編寫自己的着色器時,需要考慮到SIMD的併發特定,並用並行計算的思路來思考問題

最常見的用法是在頂點着色器生成所需要的值,然後傳遞給片段着色器使用。

GLSL能做什麼?

  • 日益逼真的材質 – 金屬、岩石、木頭、油漆等。
  • 日益逼真的光照效果 – 區域光和軟陰影。
  • 非現實材質 – 美術效果、鋼筆畫、水墨畫和對插畫技術的模擬。
  • 針對紋理內存的新用途。
  • 更少的紋理訪問。
  • 圖形處理 – 選擇、邊緣鈍化遮蔽和複雜混合。
  • 動畫效果 – 關鍵幀插值、粒子系統。
  • 用戶可編程的反走樣方法。

GLSL注意

  • GLSL支持函數重載
  • GLSL不存在數據類型的自動提升,類型必須嚴格保持一致。
  • GLSL不支持指針、字符串、字符,它基本上是一種處理數字數據的語言。
  • GLSL不支持聯合、枚舉類型、結構體位字段及按位運算符。

數據類型


GLSL有三種基本數據類型:float,int和bool,以及這些數據類型組成的數組和結構體。
需要注意的是:GLSL並不支持指針。與C/C++不同的是,GLSL將向量和矩陣作爲基本數據類型。
注意:GLSL不存在數據類型的自動提升,類型必須嚴格保持一致。

標量

  • float
  • int
  • bool
42    // 十進制
042   // 八進制
0x2A  // 十六進制

GLSL不存在數據類型的自動轉換,必須嚴格保持一致

矢量

矢量可以和標量甚至矩陣做加減乘除(必須符合規則)

 vec2,  vec3,  vec4 // 包含2/3/4個浮點數的矢量
ivec2, ivec3, ivec4 // 包含2/3/4個整數的矢量
bvec2, bvec3, bvec4 // 包含2/3/4個布爾值的矢量

聲明:

vec3 v;             //聲明三維浮點型向量v  
v[1]=3.0;           //給向量v的第二個元素賦值  

// 下面兩種等價
vec3 v = vec3(0.6);
vec3 v = vec3(0.6, 0.6, 0.6);

注意:除了用索引的方式外,還可以用選擇運算符的方式來使用向量。選擇運算符是對於向量的各個元素(最多爲4個)約定俗稱的名稱,用一個小寫拉丁字母來表示。根據向量表示對象的意義不同,可以使用以下選擇運算符:

  • 表示頂點可以用(x、y、z、w)。
  • 表示顏色可以用(r、g、b、a)。
  • 表示紋理座標用(s、t、r、q)。
    用戶可以選擇其中任意一種選擇運算符,它們的作用是等效的。
    也即是說,如果v是一個向量,那麼v[0]、v.r、v.x和v.s都是指向量v的第一個元素。例如:
vec4 v1=vec4(1.0, 2.0, 3.0, 4.0);   //用構造函數的方式聲明並初始化四維浮點型
vec4 v2;  
v2.xy=v1.yz;                    //將v1的第二個和第三個元素複製到v2的第一個和第二個元素 
v2.z=2.0;                       //給v2的第三個元素賦值  
v2.xy=v1.yx;                    //將v1的頭兩個元素互換,再複製到v2的頭兩個元素中

矩陣

mat2,mat3,mat4 – 2x2/3x3/4x4 的矩陣
矩陣式按列順序組織的,先列後行。
例如:

mat4 m;             //聲明四維浮點型方陣m  
m[2][3]=2.0;        //給方陣的第三列、第四行元素賦值 

// 下面兩種等價,初始化矩陣對角
mat2 m = mat2(1.0)
mat2 m = mat2(1.0, 0.0, 0.0, 1.0);

取樣器(Sampler)

紋理查找需要指定哪個紋理或者紋理單元將指定查找。

sampler1D           // 訪問一個一維紋理
sampler2D           // 訪問一個二維紋理           
sampler3D           // 訪問一個三維紋理
samplerCube         // 訪問一個立方貼圖紋理
sampler1DShadow     // 訪問一個帶對比的一維深度紋理
sampler2DShadow     // 訪問一個帶對比的二維深度紋理
uniform sampler2D grass;

vcc2 coord = vec2(100, 100);
vec4 color = texture2D(grass, coord);

如果一個着色器要在程序裏結合多個紋理,可以使用取樣器數組

const int tex_nums = 4;
uniform sampler2D textures[tex_nums];

for(int i = 0; i < tex_nums; ++i) {
    sampler2D tex = textures[i];
    // todo ...
}

結構體

這是唯一的用戶定義類型

struct light  
{  
    vec3 position;  
    vec3 color;  
};  

light ceiling_light;

數組

數組索引是從0開始的,而沒有指針概念

// 創建一個10個元素的數組  
vec4 points[10];  

// 創建一個不指定大小的數組
vec4 points[]; 
points[2] = vec4(1.0);  // points現在大小爲3
points[7] = vec4(2.0);  // points現在大小爲8

void

只能用於聲明函數返回值

類型轉換

必須明確地進行類型轉換,不會自動轉換提升。

float f = 2.3; 
bool b = bool(f); // b is true

限定符


GLSL中有4個限定符(varable qualifiers)可供使用,它們限定了被標記的變量不能被更改的“範圍”。

  • const
  • attribute
  • uniform
  • varying

const

const和C++裏差不多,定義不可變常量,表示限定的變量在編譯時不可被修改。

attribute

attribute是應用程序傳給頂點着色器用的。不允許生命時初始化,attribute限定符標記的是一種全局變量,該變量在頂點着色器中是隻讀(read-only)的,該變量被用作從OpenGL應用程序向頂點着色器中傳遞參數,因此該限定符僅能用於頂點着色器。

uniform

uniform一般是應用程序用於設定頂點着色器和片段着色器相關初始化值。不允許聲明時初始化,uniform限定符標記的是一種全局變量,該變量對於一個圖元(primitivie)來說是不可更改的,它可以從OpengGL應用程序中接受傳遞來的參數。

varying

varying用於傳遞頂點着色器的值給片段着色器。不允許聲明時初始化,它提供了從頂點着色器向片段着色器傳遞數據的方法,varying限定符可以再頂點着色器中定義變量,然後再傳遞給光柵化器,光柵化器對數據插值後,再將每個片段的的值交給片段着色器。

限制


  • 不能再if-else中生命變量
  • 用於判斷的條件必須是bool類型(if,while,for…)
  • (?:)操作符後兩個參數必須類型相同
  • 不支持switch語句
vec4 toonify(in float intensify) 
{
    vec4 color;
    color = vec4(0.8,0.8,0.8,0.8)
    return color;
}

discard


discard關鍵字可以避免片段更新幀緩衝區,當流控制遇到這個關鍵字時,正在處理的片段就會被標記位丟

函數


  • 函數名可以通過參數類型重載,但是和返回類型值無關
  • 所有參數必須完全匹配,參數不會自動
  • 函數不能被遞歸調用
  • 函數返回值不能是數組

hanshu參數標示符

in:進複製到函數中,但不返回的參數(默認)
out:不將參數複製到函數中,單返回參數
inout:複製到函數中並返回

混合操作


通過選擇器(.)後列出各分量名,就可以選擇這些分量

vec4 v4;
v4.rgba;    // 得到vec4
v4.rgb;     // 得到vec3
v4.b;       // 得到float
v4.xy;      // 得到vec2
v4.xgba;    // 錯誤!分量名不是同一類

v4.wxyz;    // 打亂原有分量順序
v4.xxyy;    // 重複分量
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章