本書系列html
接下去的內容對渲染的過程進行粗略介紹。遇到的部份內容不是很明白也沒有關係,在接下去的章節中,會被具體闡述。shell
你在電腦屏幕上看到的任何東西,包括你如今閱讀的文字是簡單的二維像素點的集合。若是你在屏幕上截圖,並放很大,就會看到一個個的方格。編程
Figure8. An Image數組
沒一個格子就是一個像素。pixel單詞,是從Picture Element中提取出來的。你屏幕上的沒一個像素都有一個獨立的顏色。二維的像素數組就組成了 圖像性能
所以,任何一種圖像操做的目的都是肯定將什麼顏色放到哪一個像素上。不一樣顏色在不一樣像素位置的設定造成了文字,窗口,等其餘東西。學習
既然全部的圖像都是二維的像素組成的,那麼3D圖像是怎麼來的呢?3D圖像是一系列帶顏色的像素組成的,而且給人的視覺上看上去像是一個3D的世界,而不是單純的2D的圖。這個將3D的世界轉變成2D圖像的過程叫作 渲染 。spa
3D圖像的渲染有不一樣的方法。實時圖形顯卡中引入了一種很巧妙的方法來實現渲染。這個過程被稱爲光柵化,實現光柵化的系統被成爲 光柵器(rasterizer) 。設計
經過光柵,你看到的全部的對象都是空殼。有一些技術能夠用來將這些空殼打開,可是這樣也僅僅是用一部分殼替換了另外一部分的殼。其實全部的東西都是殼(shell)。orm
上面這段話,能夠理解成,全部的對象都是由不一樣的等直面組成的,就比如在一個雞蛋殼裏面,有雞蛋殼,一層套這一層,當將最外面的殼打開後,你可以看到裏面的殼(等值面)。
這些殼都是由三角形組成的。即便是那些看起來很是平滑的曲面,若是很靠近的去觀察它,能夠發現它其實也是由殼組成的。有技術能夠產生更多的三角形,使得物體之間看起來更加接近或是更加大,以致於觀察者幾乎看不到物體的側面。不過,它們也都是由三角形組成的。
上面這段話意思是,雞蛋殼,經過光柵器,看到的並是不光滑的面,而是由一個個小三角形組成的,而且靠近觀察者的地方,小三角形看起來比較大,而在遠離觀察者的地方,如靠近側面,小三角形看起來就比較密。另外一面的內容,你沒法看到,可是它仍是由許多小三角形組成的。
注意事項
一些光柵的實現使用的是平面四邊形:擁有四條邊,而且全部的點都在一個平面上。硬件使用的光柵在原理上使用三角形的緣由是,三角形可以保證全部的邊都可以在一個平面上。這樣能夠很大程度的簡化光柵化的過程。
一個對象的外表面是由一系列相鄰的三角形組成的。這樣的一系列的三角形一般被稱爲 geometry , model 或者是 mesh 。這些術語會被交換的使用。
光柵化的過程擁有幾個階段。這些階段按順序納入到一個pipeline中,最開始的是輸入的一系列三角形,最終輸出的是2D圖。這也是回升麼光柵化的過程是易於硬件加速的:按照特定的順序,每一次都對一個三角形進行操做。三角形能夠在pipeline的開始階段輸入,然而更早輸入的三角形也能夠出如今光柵化的某個階段。
三角形和各類網格的輸入順序會影響它的輸出結果。須要記住的是,無論你怎樣輸入三角形網格數據,光柵都將以必定的順序處理各個三角形,當前一個三角形被處理完了以後,纔會處理下一個三角形。
OpenGL有獲取基於硬件的光柵的API。正由於這樣,它會使得模型適用於光柵化的渲染。光柵會接受用戶輸入的一些列三角形,而後針對這些三角形進行操做,並將像素結果輸出。這個過程簡單描述了OpenGL中光柵的工做機制,但,對於咱們而言是足夠了。
三角形和頂點. 三角形包括三個頂點。 頂點能夠是任何數值。爲了簡單起見,咱們約定頂點是三維空間上有值的點。任何三個再也不一條直線上的點能夠組成一個三角形。所以,咱們能夠獲得的信息是,一個三角形包含3個有三個維度的點。
三維空間中的一個點,含有三個份量,分別是x,y,z軸。一般用一下形式表示\((X,Y,Z)\)。
光柵化的流程對於現代硬件來講是很是複雜的。這裏很是簡單的概述了整個流程。在咱們進一步經過OpenGL學習渲染以前,有必要對這個流程有一個初步的認識。更詳細的人榮處理更高層次的概述,是沒有辦法講清楚的。
裁剪空間轉換 光柵化的第一步是將三角形中的每個頂點轉化到特定的空間區域。在空間體中的任何東西都會被渲染到輸出圖像中,在空間體外的其餘內容是不會渲染到圖像中的。這個區域與用戶想要渲染的位置有關。
這個三角形即將被轉換到的空間,在OpenGL中的稱呼爲, 裁剪空間 clip space 。三角形的定點在裁剪空間中的位置被稱爲 裁剪座標 。
裁剪座標和常規的點有一點區別。一個點在3D空間中有三個座標軸。一個點在裁剪空間有4個座標軸。前三個是X,Y,Z,第四個被稱爲W。最後一個座標實際上定義了這個定點的裁剪空間的範圍。
在裁剪空間,X的正方向是向右,Y的正方向是上,Z的正方向是原理觀察者。
頂點位置轉換到裁剪空間的過程有不少途徑。OpenGL提供了不少靈活的方式。對於這個過程在之後的章節中會詳細的介紹。
由於裁剪空間是世界中的可見部分轉換而來的,因此任何在這個區域外的三角形會被拋棄掉。任何部分在裁剪空間外的三角形,都有經歷 裁剪 的過程。這個過程將一個三角形分割成一些小的三角形,使得全部的三角形都可以在裁剪空間中。所以,這個空間就被稱爲「裁剪空間」。
標準化座標 裁剪空間比較有意思,可是並非很方便。這個空間的大小對每個頂點來講是不同的,這使得一個三角形的可視化變得很是困難。所以,裁剪空間會被轉換成更加合理的座標空間: 標準化設備空間 。
這個過程很是發簡單,就是將每個頂點的X,Y,Z除以W,就可以獲得標準化設備空間。
標準化設備空間,除了它的X,Y,Z座標範圍爲[-1,1]之外,其實就能夠理解成裁剪空間。兩個空間座標系的方向是一致的。除數W,在將3D的三角形投影到2D的圖像的時候,起到了很是重要的做用;咱們將在後續的內容中進一步說明。
Figure9. Normalized Device Coordinate Space
這個立方體,表示標準設備空間的邊界。
窗口轉換 接下去的一個階段是再次變換每一個三角形的頂點。這一次是將標準設備座標系轉換到 窗口座標系 。從名字上能夠看出,窗口座標系就是OpenGL運行的窗口。
儘管它指的是窗口,但仍然是三維的座標系。和裁剪空間同樣,X是右方向,Y是上方向,Z是遠離觀察者的方向。惟一不一樣的是,這些軸的範圍依賴於看到的窗口。還有一點須要注意的是,雖然這些點都在窗口座標系中,可是點的精度並無損失。點並無成爲整數點,依然是浮點數,所以點的精度和單個像素是不同的。
Z的範圍是[0,1],0表示最近的,1表示最遠的。在這個範圍之外的點是不可見的。
須要注意的是,窗口座標系中,左下角的位置是原點(0,0)。這個與用戶一般認知中的屏幕座標系,左上角是原點是不同的。若是你想要,經過必定的更改,能夠將變換變換到左上角是原點的座標系中。
這個過程會在輔助材料中進行詳細討論。
掃描轉換 Scan Conversion 將三角形的頂點轉換到窗口座標系後,這個三角形還得經歷 掃描轉換 的過程。這個過程就是依據三角形覆蓋的像素點的位置,將三角形分解成不一樣的像素的過程。
Figure10. Scan Converted Triangle
中間的圖顯示了輸出圖像的像素格子的大小;圓圈表示了每一個像素的中心位置。每個像素的中心表示一個 取樣(sample) :像素區域內的離散位置。在掃描轉換中,一個三角形將會在三角形3D區域內部每個像素取樣的位置產生一個 碎片(fragment) 。
右邊的圖像顯示的就是經過掃描轉換產生的碎片。這個產生了三角形形狀的一個近似。
待渲染的三角形有公共的邊是一個很常見的事情。只要公共的定點是相同的,OpenGL就可以保證掃描轉換出來的結果中,兩個三角形之間沒有采樣間隔。
Figure11. Shared Edge Scan Conversion
爲了更簡單的使用掃描轉換,OpenGL同時也保證相同的輸入,可以獲得徹底相同的渲染輸出。這個也被稱爲, 不變性保證 。所以,須要用戶保證使用相同的輸入點,來得到沒有間隔的掃描轉換。
掃描轉換是一個固有的2D操做。這個過程僅僅使用了三角形在窗口座標系中的X和Y的值,來肯定須要產生哪些碎片。不要忘了Z值,可是Z值和三角形掃描轉換並無直接的關係。
三角形掃描變化的結果是覆蓋在三角形上的有順序的碎片。每個碎片都有一個數值與它關聯。這個數值包括了碎片在窗口座標系中的2D位置,同時也有Z的位置。Z值是碎片的深度。還有一些與碎片相關的其餘參數,這將在後續的內容中闡述。
碎片處理(Fragment Processing)
這個階段,經過掃描轉換將獲得的碎片設置一種或更多的顏色,和一個深度值。單個三角形中的碎片被處理的順序是可有可無的,由於一個三角形位於同一個平面上,產生的碎片不會有重疊的可能。可是,可能和另外一個三角形的碎片發生重疊。因爲光柵器中順序的重要性,使得一個三角形中的碎片必須在另外一個三角形的碎片處理以前處理完。
這個階段有很大的自由性,OpenGL的用戶有各類不一樣的選擇來決定要賦予碎片的顏色。在輔助教材中,咱們會展開詳細的論述。
碎片輸出(fragment writing) 在產生一個或多個顏色值和一個深度信息以後,這個碎片會輸出到目標圖像中。這個過程不僅僅是將顏色信息賦值到圖像上。須要通過計算,才能將碎片的將顏色和深度信息以及圖像中已經有的顏色信息一塊兒融合到一塊。在不一樣的章節中都會涉及到這部分的內容。
正如前面所述,一個像素表示圖中擁有特定顏色的一個元素。一個顏色能夠以不少不一樣的方式展示。
在計算機圖形學中,對顏色的描述一般是不一樣通道下[0,1]範圍內的數字組成。最終的顏色是各個通道下顏色的組合。
各個通道下顏色的集合叫作 顏色空間 。最多見的顏色空間就是RGB顏色空間,該顏色空間有三個顏色通道,分別是紅,綠,藍。針對打印的顏色空間一般是CMYK(Cyan青色,Magenta洋紅,Yellow黃色,Black黑色)。因爲咱們處理的場景是將圖像渲染到屏幕上,所以咱們使用的顏色空間是RGB顏色空間。
注意
你也能夠對可編程的着色器進行一些特殊的處理,來容許你對不一樣的顏色空間進行操做。所以,從技術上來講,咱們僅僅須要將結果輸出到線性的RGB顏色空間便可。
所以,在OpenGL中一個像素有三個[0,1]範圍的值,用來表示RGB顏色空間中的RGB三個份量。將這三個顏色的不一樣大小進行組合,咱們可以獲得成千上萬的不一樣的顏色。當咱們處理透明度的時候,這個還會獲得進一步的擴展。
着色器 被設計用來在渲染器上運行部分操渲染操做的程序。無論使用的渲染系統的類型,着色器只能在渲染過程當中特定的過程被使用。這些 着色階段(shader stages) 指的是用戶能夠添加任意算法實現特別視覺效果的位置。
根據上面總結出來的光柵化過程,有幾個着色階段的實現既保證了運行的性能,有向用戶提供了可編程的簡易性。例如,將定點轉換到裁剪座標系,有好比將碎片設定特定的顏色和深度。
OpenGL的着色器是運行在渲染硬件上的。這樣可將CPU空置出來執行其餘的任務,或者若是沒有執行任意代碼的靈活性,那麼簡單的執行一些操做也將是困難的事情。這樣的缺點是,着色器的使用是有必定限制的,而CPU是沒有限制的。
目前有各類各樣的着色器語言。本書中使用的是OpenGL的主要的着色器語言,被稱爲「OpenGL Shading Language」,簡稱GLSL。它的語法看着很是像C語言,但並非C語言。