在這一章,我們會學(xué)習(xí)什么是著色器(Shader),什么是著色器語言(OpenGL Shading Language-GLSL),以及著色器怎么和OpenGL程序交互。
首先我們先來看看什么叫著色器。 Shader(著色器)是用來實(shí)現(xiàn)圖像渲染的,用來替代固定渲染管線的可編程程序。 著色器替代了傳統(tǒng)的固定渲染管線,可以實(shí)現(xiàn)3D圖形學(xué)計算中的相關(guān)計算,由于其可編程性,可以實(shí)現(xiàn)各種各樣的圖像效果而不用受顯卡的固定渲染管線限制。這極大的提高了圖像的畫質(zhì)。 在上一篇文章( http://www.cnblogs.com/MyGameAndYOU/p/4681710.html ) 關(guān)于OpenGL的第一個例子中,我們已經(jīng)接觸過頂點(diǎn)著色器(Vertex Shader)以及片段著色器(Fragment Shader)的相關(guān)代碼。另外,有些書籍或者文章也將片段著色器稱為像素著色器(Pixel Shader)。
話說回來,在我們了解著色器之前,讓我們先了解固定渲染管線(fixed-function pipeline)究竟是什么。 渲染管線,也稱之為渲染流水線,可以理解為工廠的流水線工作,而在這里它的工作是讓計算機(jī)把模型通過一系列的處理最終生成圖像的過程, 網(wǎng)上也有人這么描述它:渲染管線是顯示芯片內(nèi)部處理圖形信號相互獨(dú)立的的并行處理單元。頂點(diǎn)管線在GPU中的作用就是處理幾何數(shù)據(jù),并將3D數(shù)據(jù)投射到二維的屏幕上。借用一個網(wǎng)友說的簡單例子來通俗的說明一下頂點(diǎn)管線和像素渲染管線的作用。一個畫家在做畫的時候,都需要先把所畫人或物的輪廓,框架畫出來,這里我們稱之為“構(gòu)圖”;然后再根據(jù)光照進(jìn)行著色,這里我們稱之為“渲染”。頂點(diǎn)管線和像素渲染管線所起的就是這兩個作用,頂點(diǎn)管線和引擎負(fù)責(zé)把“輪廓、框架”畫出來,而像素渲染管線和引擎則負(fù)責(zé)對畫好的“輪廓、框架”根據(jù)光照等因素進(jìn)行著色,構(gòu)成一幅完整的圖形。渲染管線直接關(guān)系到顯卡對畫面的渲染性能。 那為何稱之為固定呢?這是說芯片上一組電路已經(jīng)固定實(shí)現(xiàn)了特定的運(yùn)算功能,程序能做的只是提供場景數(shù)據(jù)以及微調(diào)運(yùn)算功能的參數(shù)。我們只能通過調(diào)用不同的API組合實(shí)現(xiàn)特定效果,但是比較死板。
那么問題又來了,流水線的處理過程分哪些步驟呢? 關(guān)于OpenGL的流水線,大家可以看這里的圖形流水線教程,非常詳細(xì)。CSDN博客地址:http://blog.csdn.net/racehorse/article/details/6593719 在這里,我借助前人的經(jīng)驗(yàn),把相關(guān)的知識再進(jìn)一步分享給大家。
一個固定渲染管線包括如下功能: 1、頂點(diǎn)變換(Vertex Transformation) 這里的頂點(diǎn)是信息的集合,包含空間中的位置、顏色、法線、紋理坐標(biāo)等等。主要用于頂點(diǎn)位置變換、對每個頂點(diǎn)計算光照、紋理坐標(biāo)的生成以及變換。 2、圖元組合和光柵化(Primitive Assembly and Rasterization) 該階段處理的是上一個階段輸出的變換后的頂點(diǎn)以及它們的連接信息。連接信息用來描述頂點(diǎn)如何組成圖元(三角形、四邊形等等)。利用在頂點(diǎn)變換階段計算出的數(shù)據(jù),結(jié)合連接信息計算出片段的數(shù)據(jù)。(例如,每個頂點(diǎn)包含一個變換后的位置,當(dāng)它們組成圖元時,就可以用來計算圖元的片斷位置。另一個例子是使用顏色,如果多邊形的每個頂點(diǎn)都有自己的顏色值,那么多邊形內(nèi)部片斷的顏色值就是各個頂點(diǎn)顏色插值得到的。)另外此階段還負(fù)責(zé)視錐體(view frustum)的剪裁和背面剔除。 光柵化決定了片斷(fragment),以及圖元的像素位置。這里的片斷是指一塊數(shù)據(jù),用來更新幀緩存(frame buffer)中特定位置的一個像素。一個片斷除了包含顏色,還有法線和紋理坐標(biāo)等屬性,這些信息用來計算新的像素顏色值。本階段的輸出包括幀緩存中片段的位置,以及經(jīng)過插值后的片段信息。 3、片斷紋理化和色彩化(Fragment Texturing and Coloring) 此階段的輸入是經(jīng)過插值的片段信息。在前一階段已經(jīng)通過插值計算了紋理坐標(biāo)和一個顏色值,這個顏色在本階段可以用來和紋理元素進(jìn)行組合。此外,這一階段還可以進(jìn)行霧化處理。通常最后的輸出是片斷的顏色值以及深度信息。 4、光柵操作(Raster Operations) 此階段的輸入包括像素位置、片斷深度和顏色值。這個階段對片段進(jìn)行一系列的測試,包括:剪切測試(scissor test)、Alpha測試、模版測試、深度測試。 如果測試成功,則根據(jù)當(dāng)前的混合模式(blend mode)用片段信息來更新像素值。注意混合只能在此階段進(jìn)行,因?yàn)槠瑪嗉y理化和顏色化階段不能訪問幀緩存。幀緩存只能在此階段訪問。
一幅圖總結(jié)固定功能流水線(Visual Summary of the Fixed Functionality) 下圖直觀地總結(jié)了上述流水線的各個階段: 該圖的出處http://blog.csdn.net/racehorse/article/details/6593719
而在我們即將進(jìn)行的著色器編程中,上述的流程,有兩個階段被編程替代 1、頂點(diǎn)變換(Vertex Transformation) 這個階段使用頂點(diǎn)著色器實(shí)現(xiàn)。 2、片斷紋理化和色彩化(Fragment Texturing and Coloring) 這個階段使用片段著色器實(shí)現(xiàn)。
在OpenGL 3.0版本之前(包含3.0),或者使用了兼容模式(compatibility profile)的OpenGL環(huán)境下,我們還可以使用之前的固定渲染管線,在不使用著色器的情況下處理幾何與像素數(shù)據(jù)。 但從3.1版本開始,固定渲染管線從核心模式(core profile)去除,所以如果使用該版本之后的核心模式來編程的話,我們必須使用著色器。
GLSL在OpenGL 2.0版本左右發(fā)布的(在之前是屬于擴(kuò)展功能)。與OpenGL與時俱進(jìn),它是一種專門為圖形開發(fā)設(shè)計的編程語言,但我們可以從其身上找到C/C++的影子。 每一個著色器代碼看起來像是一個完整的C程序,同樣有一個main入口函數(shù)。但是與C不同的是,著色器的main函數(shù)沒有任何參數(shù),在某個著色階段中的輸入和輸出的所有數(shù)據(jù)都是通過著色器中的特殊全局變量來傳遞的。最重要一點(diǎn)是,不要把它們與應(yīng)用程序中的全局變量混淆,它們兩者沒有任何關(guān)系。
正如上面的代碼,OpenGL會使用輸入和輸出變量來傳遞著色器所需要的數(shù)據(jù),變量的值會在OpenGL每次執(zhí)行著色器的時候更新。 還有一種是變量是直接從OpenGL應(yīng)用程序中接收數(shù)據(jù)的,稱為uniform變量。uniform表示唯一,對所有幾何圖元的值都是一致的,除非應(yīng)用程序?qū)λ鼒?zhí)行了更新,否則著色器是并不會影響它的值的變化的。
在這一小節(jié)中,我們主要了解什么是著色器,為什么會出現(xiàn)著色器,它和固定管線有什么區(qū)別。另外,還有圖形流水線知識,下一小節(jié),我們會繼續(xù)學(xué)習(xí)GLSL的基本變量以及相關(guān)操作。
2015.08.12 廣州
|
|