在這一章,咱們會學習什麼是着色器(Shader),什麼是着色器語言(OpenGL Shading Language-GLSL),以及着色器怎麼和OpenGL程序交互。html
首先咱們先來看看什麼叫着色器。編程
Shader(着色器)是用來實現圖像渲染的,用來替代固定渲染管線的可編程程序。緩存
着色器替代了傳統的固定渲染管線,能夠實現3D圖形學計算中的相關計算,因爲其可編程性,能夠實現各類各樣的圖像效果而不用受顯卡的固定渲染管線限制。這極大的提升了圖像的畫質。框架
在上一篇文章( http://www.cnblogs.com/MyGameAndYOU/p/4681710.html )編程語言
關於OpenGL的第一個例子中,咱們已經接觸過頂點着色器(Vertex Shader)以及片斷着色器(Fragment Shader)的相關代碼。另外,有些書籍或者文章也將片斷着色器稱爲像素着色器(Pixel Shader)。函數
話說回來,在咱們瞭解着色器以前,讓咱們先了解固定渲染管線(fixed-function pipeline)到底是什麼。性能
渲染管線,也稱之爲渲染流水線,能夠理解爲工廠的流水線工做,而在這裏它的工做是讓計算機把模型經過一系列的處理最終生成圖像的過程,學習
網上也有人這麼描述它:渲染管線是顯示芯片內部處理圖形信號相互獨立的的並行處理單元。頂點管線在GPU中的做用就是處理幾何數據,並將3D數據投射到二維的屏幕上。借用一個網友說的簡單例子來通俗的說明一下頂點管線和像素渲染管線的做用。一個畫家在作畫的時候,都須要先把所畫人或物的輪廓,框架畫出來,這裏咱們稱之爲「構圖」;而後再根據光照進行着色,這裏咱們稱之爲「渲染」。頂點管線和像素渲染管線所起的就是這兩個做用,頂點管線和引擎負責把「輪廓、框架」畫出來,而像素渲染管線和引擎則負責對畫好的「輪廓、框架」根據光照等因素進行着色,構成一幅完整的圖形。渲染管線直接關係到顯卡對畫面的渲染性能。測試
那爲什麼稱之爲固定呢?這是說芯片上一組電路已經固定實現了特定的運算功能,程序能作的只是提供場景數據以及微調運算功能的參數。咱們只能經過調用不一樣的API組合實現特定效果,可是比較死板。.net
那麼問題又來了,流水線的處理過程分哪些步驟呢?
關於OpenGL的流水線,你們能夠看這裏的圖形流水線教程,很是詳細。CSDN博客地址:http://blog.csdn.net/racehorse/article/details/6593719
在這裏,我藉助前人的經驗,把相關的知識再進一步分享給你們。
一個固定渲染管線包括以下功能:
一、頂點變換(Vertex Transformation)
這裏的頂點是信息的集合,包含空間中的位置、顏色、法線、紋理座標等等。主要用於頂點位置變換、對每一個頂點計算光照、紋理座標的生成以及變換。
二、圖元組合和光柵化(Primitive Assembly and Rasterization)
該階段處理的是上一個階段輸出的變換後的頂點以及它們的鏈接信息。鏈接信息用來描述頂點如何組成圖元(三角形、四邊形等等)。利用在頂點變換階段計算出的數據,結合鏈接信息計算出片斷的數據。(例如,每一個頂點包含一個變換後的位置,當它們組成圖元時,就能夠用來計算圖元的片段位置。另外一個例子是使用顏色,若是多邊形的每一個頂點都有本身的顏色值,那麼多邊形內部片段的顏色值就是各個頂點顏色插值獲得的。)另外此階段還負責視錐體(view frustum)的剪裁和背面剔除。
光柵化決定了片段(fragment),以及圖元的像素位置。這裏的片段是指一塊數據,用來更新幀緩存(frame buffer)中特定位置的一個像素。一個片段除了包含顏色,還有法線和紋理座標等屬性,這些信息用來計算新的像素顏色值。本階段的輸出包括幀緩存中片斷的位置,以及通過插值後的片斷信息。
三、片段紋理化和色彩化(Fragment Texturing and Coloring)
此階段的輸入是通過插值的片斷信息。在前一階段已經經過插值計算了紋理座標和一個顏色值,這個顏色在本階段能夠用來和紋理元素進行組合。此外,這一階段還能夠進行霧化處理。一般最後的輸出是片段的顏色值以及深度信息。
四、光柵操做(Raster Operations)
此階段的輸入包括像素位置、片段深度和顏色值。這個階段對片斷進行一系列的測試,包括:剪切測試(scissor test)、Alpha測試、模版測試、深度測試。
若是測試成功,則根據當前的混合模式(blend mode)用片斷信息來更新像素值。注意混合只能在此階段進行,由於片段紋理化和顏色化階段不能訪問幀緩存。幀緩存只能在此階段訪問。
一幅圖總結固定功能流水線(Visual Summary of the Fixed Functionality)
下圖直觀地總結了上述流水線的各個階段:
該圖的出處http://blog.csdn.net/racehorse/article/details/6593719
而在咱們即將進行的着色器編程中,上述的流程,有兩個階段被編程替代
一、頂點變換(Vertex Transformation) 這個階段使用頂點着色器實現。
二、片段紋理化和色彩化(Fragment Texturing and Coloring) 這個階段使用片斷着色器實現。
在OpenGL 3.0版本以前(包含3.0),或者使用了兼容模式(compatibility profile)的OpenGL環境下,咱們還可使用以前的固定渲染管線,在不使用着色器的狀況下處理幾何與像素數據。
但從3.1版本開始,固定渲染管線從核心模式(core profile)去除,因此若是使用該版本以後的核心模式來編程的話,咱們必須使用着色器。
GLSL在OpenGL 2.0版本左右發佈的(在以前是屬於擴展功能)。與OpenGL與時俱進,它是一種專門爲圖形開發設計的編程語言,但咱們能夠從其身上找到C/C++的影子。
每個着色器代碼看起來像是一個完整的C程序,一樣有一個main入口函數。可是與C不一樣的是,着色器的main函數沒有任何參數,在某個着色階段中的輸入和輸出的全部數據都是經過着色器中的特殊全局變量來傳遞的。最重要一點是,不要把它們與應用程序中的全局變量混淆,它們二者沒有任何關係。
#version 430 core in vec4 vPosition in vec4 vColor; out vec4 color; uniform mat4 ModelViewProjectionMatrix; void main(){ color = vColor; gl_Position = ModelViewProjectionMatrix * vPosition; }
正如上面的代碼,OpenGL會使用輸入和輸出變量來傳遞着色器所須要的數據,變量的值會在OpenGL每次執行着色器的時候更新。
還有一種是變量是直接從OpenGL應用程序中接收數據的,稱爲uniform變量。uniform表示惟一,對全部幾何圖元的值都是一致的,除非應用程序對它執行了更新,不然着色器是並不會影響它的值的變化的。
在這一小節中,咱們主要了解什麼是着色器,爲何會出現着色器,它和固定管線有什麼區別。另外,還有圖形流水線知識,下一小節,咱們會繼續學習GLSL的基本變量以及相關操做。
2015.08.12
廣州