OpenGL--GLSL基礎

Shader簡介

首先簡單介紹一下Shader是什麼,Shader意爲着色器,只是整個圖形渲染管線流程中的某幾個單元,也能夠理解爲圖形渲染管線中的幾處會被執行的代碼,Shader主要包括:頂點Shader,片斷Shader以及幾何Shader這3種。程序員

那麼頂點,片斷和幾何分別是什麼呢?頂點很好理解,如要繪製一張圖片,通常是一個由四個頂點組成的圖形。就是咱們讀書那會幾何學裏的頂點一個意思。數組

片斷簡單點理解就是要繪製這張圖片的每個像素。(這種叫法通常指在渲染管線的着色階段的像素,片斷和像素是有區別的,如在重疊的狀況下,一個像素上能夠渲染多個片斷)app

幾何指的是要繪製的形狀,一樣的4個點,能夠組成兩個三角形、一個四邊形或者兩條線。函數

咱們一般說的圖形渲染其實就是一個固定流水線流程,即一張圖片從無到有怎麼顯示到顯示器上的一個過程。Shader就是這個過程當中咱們程序員惟一能動態操做改變的部分。操做的橋樑就是語言了,DirectX中是HLSL,OpenGL中使用的是GLSL語言來編寫Shader腳本,能夠寫出各類炫酷的效果~測試

圖形渲染管線

下面咱們來大體講講圖形渲染管線流程的具體的幾個步驟:
1.準備好頂點數據和頂點連通性數據。頂點數據包括頂點的位置、顏色、紋理座標、法線等數據,而頂點連通性數據則是描述頂點之間如何鏈接組合的數據,如這邊兩個頂點是連成一條線,這邊三個頂點組成一個三角形。ui

2.將第一步獲取的頂點數據進行處理,包括頂點位置變換,頂點光照計算,生成紋理座標等操做,處理完後輸出到下一步。(頂點着色器負責階段spa

3.根據上面提供的頂點數據和頂點連通性數據,將點連成線,線連成面。把零零散散的頂點組裝成一個一個的圖元,而且將圖元進行柵格化,即處理成一個一個的像素格子,而且決定了每一個像素格子的位置,這就是咱們說的片斷。
被肯定的除了片斷的位置以外,還可能包含片斷的顏色,OpenGL會根據圖元各個頂點的顏色,紋理座標進行插值,得出每一個片斷的顏色插值。這個階段還會對不在視口範圍中的內容進行裁剪背面剔除操做也會在這個階段執行。(幾何着色器負責階段,這個咱們通常不會用到,由於通常不須要咱們再去實現一套新的圖元組裝規則)code

4.對第三步輸出的片斷進行處理,包括對顏色處理,或者丟棄片斷,霧化也是在這個階段執行的。(片斷着色器負責階段orm

5.爲即將呈現到屏幕上的內容進行最後的處理,即對每一個片斷進行一系列的測試圖片

  • 裁剪測試,激活GL_SCISSOR_TEST時開啓,判斷是否在設定的裁剪窗口中,如是則經過,不然不渲染當前片斷。
  • Alpha測試,激活GL_ALPHA_TEST時開啓,判斷當前片斷的透明度是否符合glAlphaFunc設定的條件(如透明度大於0.5),如是則經過,不然不渲染當前片斷。
  • 模版測試,激活GL_STENCIL_TEST時開啓,判斷當前片斷模版值與模版緩衝區中對應的模版值是否符合glStencilFunc()函數設定的條件,如是則經過,不然不渲染當前片斷。
  • 深度測試,激活GL_DEPTH_TEST時開啓,用於判斷片斷的先後遮擋關係,判斷當前片斷的深度值和深度緩衝區中對應的值是否符合glDepthFunc()函數設定的條件,如是則經過,不然不渲染當前片斷。

最後,若是測試都經過了的話,會根據當前的混合模式將片斷更新到幀緩衝區裏對應的像素中,當屏幕刷新時,幀緩衝區的內容會被渲染到屏幕上。這就是咱們看到一個圖像如何顯示到屏幕上的整個過程。

GLSL基礎語法

下面咱們看看怎麼編寫Shader腳本,GLSL語法相似C語言,頂點着色器和片斷着色器都是使用GLSL編寫的。
一:數據類型和變量
1.基礎類型
GLSL支持如下三種基本數據類型:float、int、bool
須要特別注意的是,假設有一個float變量,在着色器中將其賦值爲1,在一些顯卡上可能會崩潰!由於1是整數不是浮點數,因此須要將1.0賦給浮點型變量。能夠這樣使用基本類型變量:

int a, b;
float c = 3.0;
bool d = true;

2.向量類型
上面3種基本數據類型分別對應3種向量:
vec二、vec三、vec4:浮點型向量,能夠存儲2~4個浮點數。
ivec二、ivec三、ivec4:整數向量。
bvec二、bvec三、bvec4:布爾型向量。
向量的操做是很靈活的,可使用下標來訪問向量的份量,也可使用x、y、z、w字段來訪問向量的成員,使用r、g、b、a字段能夠訪問顏色向量,使用s、t、p、q字段能夠訪問紋理座標向量。若是要訪問向量的x、y、z3個字段,還能夠連續使用字段。下面來代碼演示下:

vec2 a = vec2(1.0, 2.0);
vec3 b = vec3(3.0, 4.0, 5.0);
vec3 color = b.rgb;    //使用rgb來操做b的三個份量
float c = a[0];        //使用下標的方式來訪問a的第一個變量
vec3 d = vec3(a, c);   //使用一個vec2和一個float初始化vec3
float e = float(d);    //d的x份量被賦值給了e

3.矩陣類型
GLSL提供了2✖️2,3✖️3,4✖️4共3種矩陣類型,分別使用mat2,mat3,mat4表示。此外還支持2~4✖️2~4的任意矩陣,如mat3✖️二、mat4✖️3等。用法和向量相似。

4.採樣器
GLSL提供了一組採樣器,這是一種用於訪問紋理的特殊類型,在讀取紋理值時會用到,主要有下面幾種採樣器。

  • sampler1D:一維紋理採樣器
  • sampler2D:二維紋理採樣器
  • sampler3D:三維紋理採樣器
  • samplerCube:立方體映射紋理採樣器
  • sampler1DShadow:一維陰影映射採樣器
  • sampler2DShadow:二維陰影映射採樣器

5.數組和結構體
在GLSL中,能夠像C語言同樣聲明和訪問數組,但不能在聲明時直接初始化數組,數組下標從0開始,如:

int a[3];
a[0] = 1;

GLSL還能夠定義結構體,定義和初始化以下:

struct xxx
{
    vec3 pos;
    vec3 color;
};

xxx st1;
xxx st2 = xxx(vec3(0.0, 0.0, 0.0), vec3(1.0, 1.0, 0.0));
st2.pos = vec3(0.0, 1.0, 0.0);

二:操做符

=<+-*/&&||.等等這些基本和c語言操做符一致,不做過多介紹。

三:變量修飾符
變量修飾符放在變量類型以前,用於修飾變量,GLSL經常使用的有如下變量修飾符。

  • const:編譯時期的常量,不可被修改
  • attribute:屬性變量
  • uniform:統一變量
  • varying:易變變量

屬性變量和統一變量都是隻讀的全局變量(不能定義在函數內),都是由OpenGL應用程序設置的變量,即值由底層操做,咱們只需定義使用。
屬性變量是針對每一個頂點的數據,因此只能在頂點着色器中定義,通常會將頂點的顏色、位置、法線等頂點數據做爲屬性變量傳遞給頂點着色器。
統一變量是針對整個圖元的數據,既能夠在頂點着色器中使用,也能夠在片斷着色器中使用。咱們把統一變量做爲中間媒介,經過統一變量傳遞應用程序中的變量給着色器使用

易變變量是着色器中最神奇的變量,也最不容易理解。主要用於存儲插值數據,必須同時在頂點着色器和片斷着色器中定義同一個易變變量,在頂點着色器中寫入易變變量的值,而後在片斷着色器中獲取易變變量的值(片斷着色器中,易變變量是隻讀的)。
在頂點着色器中寫入頂點的插值,而後到了插值計算階段會根據這些頂點的插值會進行插值運算,計算出頂點之間片斷的值。簡單的講就是對數據進行插值計算。

四:語句與函數
GLSL語句和函數基本和c語言一致,支持if-else,for,while,do-while語句,同時支持break和continue關鍵字。在片斷着色器中,還可使用discard語句來丟棄當前片斷。
着色器程序由函數組成,每一個着色器都須要有一個main()函數,和c同樣這是程序的入口。
函數返回值能夠是任意類型,但不能是數組。函數參數有3種修飾符,分別是in,out,inout,分別表示輸入、輸出、既輸入又輸出。沒有指定默認爲in。函數還容許重載。

bool areyouhappy(in float money)
{
    if(money < 1000000000.0)
        return false;
    else
        return true;
}

五:Shader簡單示例
簡單的顏色Shader腳本:

//頂點Shader
//輸入頂點和顏色數據
attribute vec4 vVertex;
attribute vec4 vColor;
//輸出顏色插值到vVaryingColor中
varying vec4  vVaryingColor;
void main()
{
    vVaryingColor = vColor;
    gl_Position = vVertex;
}
//片斷Shader
//拿到通過插值後的vVaryingColor,將它設置到最終輸出的gl_FragColor變量中
varying vec4 vVaryingColor;
void main()
{
    gl_FragColor = vVaryingColor;
}

頂點着色器最主要的職責就是計算位置,因此頂點着色器至少須要寫入一個變量gl_Position,這個是GLSL內置的位置變量,須要將變換後的頂點座標賦予該變量。

片斷着色器主要職責是計算片斷顏色,因此須要將片斷最終顏色寫入內置的gl_FragColor變量中(或者將該片斷拋棄)。

相關文章
相關標籤/搜索