OpenGL着色語言(GLSL――OpenGL Shading Language)是用來在OpenGL中着色編程的語言,
也即開發人員寫的短小的自定義程序,他們是在圖形卡的GPU (Graphic Processor Unit圖形處理單元)
上執行的,代替了固定的渲染管線的一部分。比如:視圖轉換、投影轉換等。GLSL(GL Shading Language)
的着色器代碼分成2個部分:Vertex Shader(頂點着色器)和Fragment(片斷着色器)
,有時還會有Geometry Shader(幾何着色器)。負責運行頂點着色的是頂點着色器。
它可以得到當前OpenGL 中的狀態,GLSL內置變量進行傳遞。
先看下vertex shader,起設計目的是對應用層輸入的頂點數據做處理,我們可以以一個簡單的
代碼來看下定點處理的過程,可以把下面的過程看成是顯卡處理定點數據的過程:
void process( const Vertex& position,Vertex& gl_Position) { gl_Position = gl_ModelViewProjectionMatrix * position; } for (int i = 0 ;i < vertexCnt ; ++ i ) { Vertex gl_Position; process( position[i],Vertex& gl_Position); //! 對定點數據做其他的處理 }
上面的代碼中process函數,就是我們要寫的shader函數,里面對頂點數據進行處理,處理完成
后交給下一個渲染流程。下面的for循環函數,是又顯卡內部控制,當然也是在顯卡內完成,即當
我們在應用層調用OpenGL的函數 glVertex**或者glNormal等函數的時候,就是把頂點數據從
cpu傳遞給GPU,就會調用Process函數進行處理(實際遠比我說的復雜)。假設應用層有10萬
個頂點做計算,那么Process函數就會被調用10萬次。試想這該是多么大的計算量,當然這個相比
紋理來說還是小意思,當我們繪制一個圖片處理的時候,每一個像素的繪制都要調用一個類似的處理
過程函數進行處理,假設有一個1024 × 1024 的圖片繪制出來,需要的計算量大家可想而知,說
這個的道理在於我們要認識到顯卡的強大計算能力。
廢話不說,看下面的一個代碼片段,我們進行分析:
void main( void ) { gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; }
上述的代碼是一個最簡單的頂點shader:
gl_Position:是GLSL的一個內置變量,即輸出的丁點位置
gl_Vertex:是GLSL的一個內置變量,輸入的頂點位置。
gl_ModelViewProjectionMatrix:GLSL的內置變量:
保存了 Project Matrix * View Matrix * Model Matrix的結果
Model Matrix:保存了當前對頂點數據的縮放,旋轉,平移等操作
View Matrix :觀察矩陣 ,
Project Matrix:就是正交投影,或者透視投影的矩陣(調用 :glOrtho,或者 gluPerspective)
通過上面的介紹,想必大家已經多shader的工作原理已經有所了解了,下面介紹shader的使用步驟:
1.首先編寫一個shader,當然是文本方式(其實也可以是匯編方式,或者bin方式,后面介紹)
2.調用glCreateShaderObjectARB創建一個shader對象
3.將源文件(就是shader 的程序)給shader對象
4.進行編譯
單獨的一個shader對象還不能使用,要想使用它,還需要創建一個shader program 對象,然后進行關聯
可以這樣來理解,shader object 類似我們編譯c++生成的obj文件,將obj文件連接生成一個exe.這個exe
就是shader program了。
5.建立一個shader program
6.關聯shader object 到 shader program
7.進行鏈接
8.使用這個程序。
const char *source[1]; source[0] = vertexShaderSource; //1 創建一個定點shader,理解成對源碼進行編譯 g_vertexShader = glCreateShaderObjectARB( GL_VERTEX_SHADER_ARB ); //2 指定數據(就是代碼) glShaderSourceARB( g_vertexShader, 1, source, NULL ); //3 編譯 glCompileShaderARB( g_vertexShader); //4 看編譯成功了沒有 glGetObjectParameterivARB( g_vertexShader, GL_OBJECT_COMPILE_STATUS_ARB, &bVertCompiled ); //5 編譯失敗,打印錯誤的原因 if( bVertCompiled == false ) { glGetInfoLogARB(g_vertexShader, sizeof(temp), NULL, temp); MessageBoxA( NULL, temp, "Vertex Shader Compile Error", MB_OK|MB_ICONEXCLAMATION ); } //6 創建一個程序對象,可以理解成exe _programObj = glCreateProgramObjectARB(); //7 將頂點shader與程序綁定 glAttachObjectARB( _programObj, g_vertexShader ); //8 鏈接過程 glLinkProgramARB( _programObj ); glGetObjectParameterivARB( _programObj, GL_OBJECT_LINK_STATUS_ARB, &bLinked );