WebGL中的OpenGL著色器語言

紙異獸發表於2015-06-22

在webgl中,呼叫了OpenGL-ES-2.0的API,而在OpenGL-ES專為嵌入式裝置設計,其和其它裝置一樣,都是使用GLSL(GL Shading Language)來編寫片段程式並執行於GPU的著色器上,來完成對物件的渲染。GLSL在其中起著相當重要的作用,所以要玩好webgl,我們就得把GLSL搞懂,本文主要介紹shader的基礎使用及組成。

整個管線處理過程:

1.指定幾何物件

  1. 頂點陣列(直接將頂點資料傳送至shader裡)
  2. 頂點索引(將頂點資料儲存於緩衝區中,用索引來從緩衝區獲取資料傳入shader)

2.逐個頂點操作

3.圖元組裝

根據指定的圖元組裝方式將若干頂點組成一個圖元,OpenGL支援的幾何圖元有點、線、不閉合折線、閉合折線、多邊形、三角形、線型連續填充三角形、扇形連續填充三角形、四邊形以及連續填充四邊形。

而webgl支援的圖元為POINTS(點), LINE_STRIP(不閉合折線), LINE_LOOP(閉合折線), LINES(獨立的線段), TRIANGLE_STRIP(頂點按順序相連的三角形), TRIANGLE_FAN(扇形順序組合三角形), TRIANGLES(每三個頂點組合成一個三角形)。

繪製三角形序列的三種方式解釋了三種三角形繪製方法之間的不同。

4.圖元處理

5.柵格化(生成片元fragment)

6.片元處理

7.逐個片元操作

8.幀緩衝區操作

在這八個步驟中,我們最重要的是對頂點和片元的操作,在整個管線中,我們可以加入的自己程式的部分則是頂點著色器和片元著色器部分。

著色器

頂點著色器:

操作的是頂點值和其關聯的資料,它可完成下面這些操作:

  • 頂點變換
  • 法線變換以及規格化
  • 紋理座標生成
  • 紋理座標變換
  • 光照
  • 彩色材質應用

頂點著色器必須計算座標在裁剪空間中的齊次位置並將結果儲存在特殊的輸出變數gl_Position中,它還有特殊的輸出變數gl_ClipVertex,gl_PointSize。

頂點處理器的輸出將被髮送到後續的處理階段,即:圖元組裝,使用者裁剪,平截裁剪,透視劃分,視口貼圖,多邊形偏移,多邊形模式,陰影模式,消隱等。

片元著色器:

處理片元值及其相關聯資料,它可執行傳統的圖形操作,如:

在插值等到的值上的操作

  • 訪問紋理
  • 應用紋理
  • 霧化
  • 顏色彙總

片元著色器其有特殊的輸入變數gl_FragCoord(片元的視窗相對座標)和gl_FrontFacing(正面圖元為true,反之為false),經過計算顏色和深度將這些值寫入特殊的輸出變數gl_FragColor和gl_FragDepth中,或者完全丟棄(使用discard關鍵字)片元。

片元處理器的一大優點是它可以任意多次地訪問紋理記憶體,並可以任意方式結合所讀取的值,一次紋理訪問的結果可作為執行另一次紋理訪問的基礎。

有三個精度可選擇:lowp highp mediump

精度可指定於變數或設定預設精度

頂點著色器中的float和init預設精度為highp

片元著色器中float沒有預設精度,所以必須為其指定預設精度,如:precision mediump float;

著色器多個執行是可並行發生的,針對每個頂點都會執行一次頂點著色器,針對每個片元都會執行一次片元著色器。

限定符

我們要向著色器中傳入資料,則要了解其裡面變數的組成和輸入方式

屬性變數(attribute):

這些變數代表了非常頻繁地從應用程式傳遞到頂點處理器的值,只應用於程式中定義頂點資料,所以只允許作為頂點著色器的一部分,該值可以像每個頂點那樣經常變動

一致變數(uniform):

用來將資料值從應用程式傳遞到頂點處理器或片元處理器,一致變數通常用來提供不頻繁變動的值。

易變變數(varying):

定義了從頂點處理器傳遞到片元處理器的資料。

常量變數(const):

如C中的常量變數

資料型別

標量:

支援使用浮點數(float)、整數(int)和布林值(bool)

向量:

浮點數向量:

vec2  (2個浮點數的向量)

vec3  (3個浮點數的向量)

vec4  (4個浮點數的向量)

整數向量:

ivec2  (2個整數的向量)

ivec3  (3個整數的向量)

ivec4  (4個整數的向量)

布林向量:

bvec2  (2個布林值的向量)

bvec3  (3個布林值的向量)

bvec4  (4個布林值的向量)

矩陣:

mat2  (2×2的浮點數矩陣)

mat3  (3×3的浮點數矩陣)

mat4  (4×4的浮點數矩陣)

mat矩陣就像是一個vec陣列,它也可以使用陣列來進行訪問。

取樣器:

sampler1D  (訪問一個一維紋理)

sampler2D  (訪問一個二維紋理)

sampler3D  (訪問一個三維紋理)

samplerCube  (訪問一個立方貼圖紋理)

sampler1DShadow  (訪問一個帶對比的一維深度紋理)

sampler2DShadow  (訪問一個帶對比的二維深度紋理)

只能通過uniform限定的取樣器從應用程式接收取樣器

使用時:  uniform sampler2D texture;

操作

如果要對向量進行部分操作,則可用訪問向量中的部分來使用,在shader中,共有三組組合供使用:

  •   x  y  z  w
  •   s  t  p  q
  •   r  g  b  a

這四個值只是分別讀取向量中的第一個、第二個、第三個、第四個值,只是為了編寫方便,語義化了三組組合,分別為座標、紋理、顏色,但是使用它們去讀取出來的值是一樣的,如:

vec4 values = vec4(1.0,2.0,3.0,4.0);
values.z;    //3.0
values.p;    //3.0
values.b;    //3.0
values[2];   //3.0

這三組使用時必須成組出現,不能混組出現,如:

vec4 values = vec4(1.0,2.0,3.0,4.0);
vec2 combination1 = values.xy;      //同一組,正確
vec3 combination2 = values.rgb;      //同一組,正確
vec3 combination3 = values.xt;     //不同組,不正確

對矩陣的讀取可以像陣列一樣:

vec2 x,y;
mat2 matrix;
x = matrix[0];
y = matrix[1];

運算

對於向量的計算:

vec3 v,u,w;
w = v + u;

//計算過程等價於

w.x = v.x + u.x;
w.y = v.y + u.y;
w.z = v.z + w.z;

對於矩陣和向量的計算:

//該過程遵守線性代數中的計算規定,即做點乘的兩個矩陣,前一個矩陣的行數等於後一個矩陣的列數

vec4 v,u;
mat4 m;
v * m;    //行向量與矩陣相乘
m * v;    //矩陣與列向量相乘
m * m;    //矩陣與矩陣相乘

運算順序:

//當多個矩陣同時施加加頂點向量上時,則要以相反的順序矩陣相乘
//如想實現先Ma再Mb的運算

vec4 v,u;
mat4 Ma,Mb;

u = Mb * (Ma * v);
//即
u = (Mb * Ma) * v;
//即
u = Mb * Ma * v;

與C和C++差異

著色語言作為一種處理數字的語言,而不是處理字元或字串資料的語言,在其中沒有包含對指標、字串、字元或基於這些型別的任何操作支援。

並且為了使編譯器和圖形硬體的實現負擔更小,該語言不支援雙精度浮點數、位元組、短整數、長整數或者這些型別的無符號變化形式。

其包括了C++的一些重要語言特性:支援函式過載,支援基本型別bool。

注:

在向頂點著色器中進行傳值時,頂點著色器會從快取中依次讀取每個頂點,如果使用的是頂點陣列方法:

如傳入:new Float32Array([1.0,1.0,1.0,0.0,

0.5,0.5,0.5,0.0]);

那麼在shader中,假設有attribute vec4 position;

會從快取中依次讀取四個數來作為position進行處理,則總共執行了兩次頂點著色器,共兩個頂點。

如果在shader中有attribute vec2 position;

則會從快取中依次讀取兩個數來作為position進行處理,共四個頂點,頂點著色器執行四次。

附:

WebGL-1.0參考卡片:http://files.cnblogs.com/files/zhiyishou/webgl-reference-card-1_0.pdf

OpenGL-ES-2.0參考卡片:http://files.cnblogs.com/files/zhiyishou/OpenGL-ES-2_0-Reference-card.pdf

相關文章