shader入門,圖形學心得


又是一個七天七夜。對於3D游戲、圖形卡原理;一個圖形學初哥總算弄明白一些了。但疑惑的更多,以至於每天都有“十萬個為什么”在腦海中翻騰;輾轉難眠。意念力已耗盡,必須休閑一段時間了。盡管,對於實時光線追蹤算法有了新的解決方案;但論證還是要放在后面的章節。下面內容,相當部分是網上抄錄整理的,以便后面對APO的GPU作規划。

 

 一、 3D圖形渲染(Rendering)

    渲染:就是將三維物體或三維場景的描述轉化為一幅二維圖像,生成的二維圖像能很好的反應三維物體或三維場景。過程:幾何變換、光柵化、着色。

 

頂點渲染單元(Vertex Shader):根據描述3D圖形外觀的三角形頂點數據確定3D圖形的形狀及位置關系; 作幾何變換、生成3D圖像的骨架。

 

光柵化:顯示的圖像是由像素組成的,我們需要將描述3D圖像骨架的一系列三角形通過一定的算法轉換到相應屏幕上的像素點。把一個矢量圖形轉換為一系列像素點的過程就稱為光柵化。例如,一條數學表示的斜線段,最終被轉化成階梯狀的連續像素點。

 

像素渲染(Pixel Shader):光照、光線追蹤、紋理帖圖、像素着色。 也就是對每個像素進行計算,從而確定每個像素的最終顏色。最后由ROP(光柵化引擎)完成像素的輸出,1幀渲染完畢后,被送到顯存幀緩沖區;然后經由D/A轉換輸出到顯示器上。

紋理帖圖:所有3D場景的對象都是由頂點形成。一個頂點是X、Y、Z坐標形成的3D空間中的一點,多個頂點聚在一起可形成一個多邊形,如三角形、立方體或更復雜的形狀,將材質貼在其上可使該組件(或幾個排好的組件)看起來更真實。紋理映射(texture mapping)工作由TMU(Texture mapping unit)單元完成對多邊形表面的帖圖。

 

頂點光照:在vetext shader中計算光照顏色,該過程將為每個頂點計算一次光照顏色,然后在通過頂點在多邊形所覆蓋的區域對像素顏色進行線性插值。現實中,光照值取決於光線角度,表面法線,和觀察點。

 

逐像素光照:是對所有光照元素進行單獨插值,簡單地說就是在pixel shader中計算顏色。

 

光線追蹤技術:現在游戲基本都沒有應用光線追蹤技術,光線都是由你能看到的亮光的物體自身發出的。電腦只是通過演算物體陰影和控制光線的強弱來“模擬”人眼看到的真實情況。盡管現在很多采用了HDR(高動態范圍)效果的游戲都有很不錯的光影效果,但是那遠非真實的光影效果。如果,視角前面有一個類似鏡子的物體,該物體的多個三角形鏡面反映的是背面的景象;就像汽車的后視鏡;但背面的物體GPU已經裁掉了。還有,像水面的物體倒影等;必須采用光線追蹤技術。由於從光源發出的光線有無窮多條,使得直接從光源出發對光線進行跟蹤變得非常困難。實際上,從光源發出的光線只有少數經由場景的反射和透射(折射)后到達觀察者的眼中。為此標准光線跟蹤算法采用逆向跟蹤技術完成整個場景的繪制;這便在最大程度上節省了計算資源。要想用光線追蹤算法渲染出達到現代游戲的畫面質量,同時跑出可流暢運行的幀數,每秒需要計算大概10億束光線。這包括每幀每像素大概需要30束不同 的光線用以分別計算着色、光照與其他特效。按這個公式推算,入門級的1024×768分辨率一共有786432個像素,乘以每像素30束光線以及每秒60幀,我們就需要每秒能計算14.1億束光線的硬件。而Intel雙路四核心處理器每秒也不過只能處理830萬束光線。如果將分辨率提升為現在主流的1920×1080,那所需要的運算量將不可想象。APO支持電影模式8192×4096,那就更不用活了。所以,必須有新的算法與硬件。

 

光線追蹤運算中會大量用到遞歸算法,如有時會出現這樣的情況:對每個光源射出一條光線來檢測是否處在陰影中,如果表面是反射面,生成反射光,將會運用遞歸繼續跟蹤;如果表面透明,生成折射光,還是運用遞歸繼續跟蹤。當前交點所在的物體表面為理想漫射面,跟蹤結束。遞歸算法是把問題轉化為規模縮小了的同類問題的子問題。然后遞歸調用函數(或過程)來表示問題的解。光線追蹤算法需要雙精度浮點運算的支持?不太了解。

 

二、流處理器SP(Stream Processor,就是可編程流式並行運算單元ALU)

ALU(邏輯算術單元,顧名思義,可以進行加、減、乘、除、乘加、開方、倒數,平方根倒數,log2, exp2,sin,cos等算術運算)。在APO中,SP的最小單元是管線,一個管線是一個ALU單元支持32位單精度浮點數的運算。雙精度浮點數的運算則需要2根管線,一條管道有8根管線,管道內是SIMD架構。每條管線都支持1D、2D、3D、4D到nD的向量和矩陣的單精度浮點數運算。數據的基本單元是Scalar(標量),就是指一個單獨的值,SP的ALU進行一次這種變量操作,被稱做1D標量。每條管線都可以按照動態流模式控制,智能的執行各種4D/3D/2D/1D指令,無論什么類型的指令執行效率都能接近於100%。SP有256條管道,多個管道單元都是根據不同的控制流程執行不同的操作,處理不同的數據,因此,SP是多指令流多數據流處理器,即管道間MIMD(Multiple Instruction Stream Multiple Data Stream,簡稱)架構,管道內部的8根管線是SIMD架構。一根管線的1D乘法、除法、開方、加、減運算速度是2G/S。4D向量與變換矩陣的乘加速度是0.125G/S,一條管道的速度是1G/S;一個SP(256條管道)全用來作矩陣變換的速度是256G/S。APO支持電影模式8192×4096,顏色是64位。有32M個像素,即使所有三角形都是最小的,對應變換后的像素只是3個頂點;那一個視錐體最多有32M/3個三角形。那6個方向,360度場景最多有6*32M/3 = 64M個三角形。APO支持28位表示的將近3億的三角形數場景。通常要處理的頂點數會小於1M個;如果一條管道的流水深度是1K個頂點,那么APO需要4次批數據存儲傳輸,幾何變換時間是:60幀*4*1K/1G/S = 0.24mS。APO中,當打開場景文件時,空間管理者CPU的SP就已經幫處理好幾何變換形成有序的文件給顯示管理者。顯示管理者CPU的SP只是多了光柵化單元、紋理單元等功能吧。其實,光照、光線跟蹤、像素着色等也可在APO的其它CPU部件進行。光柵化只能在顯示管理者的SP進行。當然,可編程的SP你可以有一部分管道做VS的功能,另一部分管道做PS的功能。3D圖形生成就是一個運算過程! 在3D圖形進行渲染時,其實就是改變RGBA四個通道或者XYZW四個坐標的數值。GS(幾何着色器Geometry Shader)、PS(像素着色器Pixel Shader)、VS(頂點着色器Vertex Shader)都是1D—4D的流運算吧。每個像素可以提供多種數據的像素着色器,由你的頂點着色器生成並由光柵化成線性插值。這允許你的像素着色器依照光照條件調整像素的顏色,添加反射,執行凹凸貼圖和紋理采樣等。你也可以用像素着色器應用后處理效果在整個要渲染的場景, 像亮度,色彩增強,飽和度和模糊。額外的,像素着色器可以改變像素深度。這個深度用在輸出合並時決定哪個像素被繪制哪個不被繪制。這個深度指示原始三角形離相機有多遠。但是,如果你想影響輸出合並的決定,你可以自己指定這個值。傳統的一條渲染管線是由包括Pixel Shader Unit(像素着色單元)+ TMU(紋理貼圖單元) + ROP(光柵化引擎)三部分組成的。用公式表達可以簡單寫作:PS = PSU+TMU+ROP 。從功能上看,PSU完成像素處理,TMU負責紋理渲染,而ROP則負責像素的最終輸出。所以,一條完整的像素管線意味着在一個時鍾周期完成至少進行1個PS運算,並輸出一次紋理。頂點着色器,取代固定渲染管線中的變換和光照部分,程序員可以自己控制頂點變換、光照等。

 

三、 三角形調整引擎

 

     軟件實現還是硬件實現在考慮中。當一個物體模型,可見面有幾千個三角形描述時;如果,被置於遠景,可能幾個三角形就可表述了;則應做三角形合並,從而剔除了幾千個頂點。反之,在近景時,就要做細分曲面(Tessellation)。在 DirectX中,還包含了其他着色器,如Hull Shader,Domain Shader(域着色器)用於曲面細分(有些地方叫做鑲嵌tessellation),Compute Shader用於計算。Hull Shader主要負責定義細分等級(LOD)和相關控制點在細分中的“形變”趨勢,需要說明的是這種形變僅僅是類似於曲率改變等小幅度的變化,而非大幅度的多邊形位移;Tessellator則負責根據Hull Shader傳輸下來的信息,通過“暴力”增加多邊形去實現Hull Shader的要求;Domain Shader負責的最重要的功能就是通過貼圖控制的方式,實現模型的形變。如果,一個由三個頂點組成的三角形占據整個屏幕,因此需要生成上百萬的片段;如果不拆分為多個三角形;光柵化單元就會從並行化變為串行化,效率大為降低。

 

      三角形調整位於幾何變換階段之后,剔除與裁剪階段之前。三角形調整階段結束后,便將一個新頂點數據組傳遞給頂點渲染器,頂點可能包含位置、紋理坐標、頂點顏色、法線等數據。頂點渲染器不能創建或刪除頂點,它處理結束后至少要輸出頂點中的位置數據。

 

face culling:  根據triangle的兩邊向量叉乘得到的面法線方向來確定是順時針還是逆時針,從而達到裁剪。背面剔除。


user clip planes:除了使用投影矩陣定義出的6個clipplane之外我們也可以額外自己定義對應的clipplane來剪裁。


frustum culling:視錐裁剪。

 

CVV culling:規范立方體(Canonical view volume,CVV)。CVV 的近平面(梯形體較小的矩形面)的X、Y 坐標對應屏幕像素坐標(左下角是0、0),Z 坐標則是代表畫面像素深度。多邊形裁剪就是CVV 中完成的。所以,從視點坐標空間到屏幕坐標空間(screen coordinate space)事實上是由三步組成:

1. 用透視變換矩陣把頂點從視錐體中變換到裁剪空間的 CVV 中;
2. 在 CVV 進行三角形裁剪;
3. 屏幕映射:將經過前述過程得到的坐標映射到屏幕坐標系上。

法向量從object space 到world space 的轉換矩陣是world matrix 的轉置矩陣的逆矩陣。

 

     所有的裁剪剔除計算都是為了減少需要繪制的頂點個數。處理三角形的過程被稱為Triangle Setup。到目前位置,我們得到了一堆在屏幕坐標上的三角面片,這些面片是用於做光柵化的(Rasterizing)。Z buffer又稱為depth buffer,即深度緩沖區,其中存放的是視點到每個像素所對應的空間點的距離衡量,稱之為Z 值或者深度值。可見物體的Z 值范圍位於【0,1】區間,默認情況下,最接近眼睛的頂點(近裁減面上)其Z 值為0.0,離眼睛最遠的頂點(遠裁減面上)其Z值為1.0。使用z buffer 可以用來判斷空間點的遮擋關系,著名的深度緩沖區算法(depth-buffer method,又稱Z 緩沖區算法)就是對投影平面上每個像素所對應的Z 值進行比較的。Z 值並非真正的笛卡兒空間坐標系中的歐幾里德距離(Euclidean distance),而是一種“頂點到視點距離”的相對度量。所謂相對度量,即這個值保留了與其他同類型值的相對大小關系。 大多數人所忽略的是,z buffer 中存放的z 值不一定是線性變化的。在正投影中同一圖元相鄰像素的Z 值是線性關系的,但在透視投影中卻不是的。在透視投影中這種關系是非線性的,而且非線性的程度隨着空間點到視點的距離增加而越發明顯。當3D 圖形處理器將基礎圖元(點、線、面)渲染到屏幕上時,需要以逐行掃描的方式進行光柵化。圖元頂點位置信息是在應用程序中指定的(頂點模型坐標),然后通過一系列的過程變換到屏幕空間,但是圖元內部點的屏幕坐標必須由已知的頂點信息插值而來。例如,當畫三角形的一條掃描線時,掃描線上的每個像素的信息,是對掃描線左右端點處已知信息值進行插值運算得到的,所以內部點的Z 值也是插值計算得到的。同一圖元相鄰像素點是線性關系(像素點是均勻分布的,所以一定是線性關系),但對應到空間線段上則存在非線性的情況,投影面上相等的步長,在空間中對應的步長會隨着離視點距離的增加而變長。所以如果對內部像素點的Z 值進行線性插值,得到的Z 值並不能反應真實的空間點的深度關系。Z 值的不准確,會導致物Z 精度之所以重要,是因為Z 值決定了物體之間的相互遮擋關系,如果沒有足夠的精度,則兩個相距很近的物體將會出現隨機遮擋的現象,這種現象通常稱為“flimmering”或”Z-fighting”。

 

四.         頂點變換(Vertex Transformation):


      頂點變換是圖形硬件渲染管線種的第一個處理階段。頂點變換在每個頂點上執行一系列的數學操作。這些操作包括把頂點位置變換到屏幕位置以便光柵器使用,為貼圖產生紋理坐標,以及照亮頂點以決定它的顏色。頂點變換中的一些坐標:

 

物體空間:

    應用程序在一個被稱為物體空間(也叫模型空間)的坐標系統里指定頂點位置。當一個美工人員創建了一個物體的三維模型的時候,他選擇了一個方便的方向、比例和位置來放置模型的組成頂點。一個物體的物體空間可以與其它物體的物體空間沒有任何關系。


世界空間:

一個物體的物體空間和其它對象沒有空間上的關系。世界空間的目的是為在你的場景中的所有物體提供一個絕對的參考。一個世界空間坐標系如何建立可以任意選擇。例如:你可以決定世界空間的原點是你房間的中心。然戶,房間里的物體就可以相對房間的中心和某個比例和某個方向放置了。


建模變換:
    在物體空間中指定的物體被放置到世界空間的方法要依靠建模變換。例如:你也許需要旋轉、平移和縮放一個椅子的三維模型,以使椅子可以正確地放置在你的房間 的世界坐標系統里。在同一個房間中的兩把椅子可以使用同樣的三維椅子模型,但使用不同的建模變換,以使每把椅子放在房間中不同的位置。


眼空間:
最后,你要從一個特殊的視點(“眼睛”)觀看你的場景。在稱為眼空間(或視覺空間)的坐標系統里,眼睛位於坐標系統的原點。朝“上”的方向通常是軸正方向。遵循標准慣例,你可以確定場景的方向使眼睛是從z軸向下看。


視變換:
    從世界空間位置到眼空間位置的變換時為視變換。典型的視變換結合了一個平移把眼睛在世界空間的位置移到眼空間的原點,然后適當地旋轉眼睛。通過這樣做,視變換定義了視點的位置和方向。我們通常把分別代表建模和視變換的兩個矩陣結合在一起,組成一個單獨的被稱為modelview的矩陣。你可以通過簡單地用建模矩陣乘以視矩陣把它們結合在一起。


剪裁空間:
    當位置在眼空間以后,下一步是決定什么位置是在你最終要渲染的圖像中可見的。在眼空間之后的坐標系統被稱為剪裁空間,在這個空間中的坐標系統稱為剪裁坐標。


投影變換:
   從眼空間坐標到剪裁空間的變換被稱為投影變換。投影變換定義了一個事先平截體(view frustum),代表了眼空間中物體的可見區域。只有在視線平截體中的多邊形、線段和點背光柵化到一幅圖形中時,才潛在的有可能被看得見。


標准化的設備坐標:
    剪裁坐標是齊次形式的,但我們需要計算一個二維位置(一對x和y)和一個深度值(深度值是為了進行深度緩沖)。


透視除法:
    用w除x,y和z能完成這項工作。生成的結果坐標被稱為標准化的設備坐標。現在所有的幾何數據都標准化為[-1,1]之間。


窗口坐標:
    最后一步是取每個頂點的標准化的設備坐標,然后把它們轉換為使用像素度量x和x的最后的坐標系統。這一步驟命名為視圖變換,它為圖形處理器的光柵器提供數據。然后光柵器從頂點組成點、線段或多邊形,並生成決定最后圖像的片段。另一個被稱為深度范圍變換的變換,縮放頂點的z值到在深度緩沖中使用的深度緩存的 范圍內。

 

五.  圖元裝配(Primitive Assembly)和光柵化(Rasterization)

 

    經過變換的頂點流按照順序被送到下一個被稱為圖元裝配和光柵化的 階段。首先,在圖元裝配階段根據伴隨頂點序列的幾何圖元分類信息把頂點裝配成幾何圖元。這將產生一序列的三角形、線段和點。這些圖元需要經過裁剪到可視平截體(三維空間中一個可見的區域)和任何有效地應用程序指定的裁剪平面。光柵器還可以根據多邊形的朝前或朝后來丟棄一些多邊形。這個過程被稱為挑選 (culling)。 經過裁剪和挑選剩下的多邊形必須被光柵化。光柵化是一個決定哪些像素被幾何圖元覆蓋的過程。多邊形、線段和點根據為每種圖元指定的規則分別被光柵化。光柵化的結果是像素位置的集合和片段的集合。當光柵化后,一個圖元擁有的頂點數目和產生的片段之間沒有任何關系。例如,一個由三個頂點組成的三角形占據整個屏幕,因此需要生成上百萬的片段。

 

    片段和像素之間的區別變得非常重要。術語像素(Pixel)是圖像元素的簡稱。一個像素代表幀緩存中某個指定位置的內容,例如顏色,深度和其它與這個位置相關聯的值。一個片段(Fragment)是更新一個特定像素潛在需要的一個狀態。

 

    之所以術語片段是因為光柵化會把每個幾何圖元(例如三角形)所覆蓋的像素分解成像素大小的片段。一個片段有一個與之相關聯的像素位置、深度值和經過插值的參數,例如顏色,第二(反射)顏色和一個或多個紋理坐標集。這些 各種各樣的經過插值的參數是來自變換過的頂點,這些頂點組成了某個用來生成片段的幾何圖元。你可以把片段看成是潛在的像素。如果一個片段通過了各種各樣的光柵化測試,這個片段將被用於更新幀緩存中的像素。

 

六.   插值、貼圖和着色

 

    當 一個圖元被光柵化為一堆零個或多個片段的時候,插值、貼圖和着色階段就在片段屬性需要的時候插值,執行一系列的貼圖和數學操作,然后為每個片段確定一個最終的顏色。除了確定片段的最終顏色,這個階段還確定一個新的深度,或者甚至丟棄這個片段以避免更新幀緩存對應的像素。允許這個階段可能丟棄片段,這個階段 為它接收到的每個輸入片段產生一個或不產生着過色的片段。

 

七.光柵操作(Raster Operations)

 

    光柵操作階段在最后更新幀緩存之前,執行最后一系列的針對每個片段的操作。在這個階段,隱藏面通過一個被稱為深度測試的過程而消除。其它一些效果,例如混合和基於模板的陰影也發生在這個階段。

 

    光柵操作階段根據許多測試來檢查每個片段,這些測試包括剪切、alpha、模板和深度等測試。這些測試涉及了片段最后的顏色或深度,像素的位置和一些像素值(像素的深度值和模板值)。如果任何一項測試失敗了,片段就 會在這個階段被丟棄,而更新像素的顏色值(雖然一個模板寫入的操作也許會發生)。通過了深度測試就可以用片段的深度值代替像素深度值了。在這些測試之后, 一個混合操作將把片段的最后顏色和對應像素的顏色結合在一起。最后,一個幀緩存寫操作用混合的顏色代替像素的顏色。

第七章 <wbr> <wbr> <wbr>圖形學習心得

 

原文鏈接:http://blog.csdn.net/visdk/article/details/45443837


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM