渲染管线概论
什么是渲染管線
渲染管線(渲染流水線)是將三維場(chǎng)景模型轉(zhuǎn)換到屏幕像素空間輸出的過程。圖形渲染管線主要包括兩個(gè)功能:一是將物體3D坐標(biāo)轉(zhuǎn)變?yōu)槠聊豢臻g2D坐標(biāo),二是為屏幕每個(gè)像素點(diǎn)進(jìn)行著色。
渲染管線的流程
渲染管線的一般流程如下圖所示。分別是:頂點(diǎn)數(shù)據(jù)的輸入、頂點(diǎn)著色器、曲面細(xì)分過程、幾何著色器、圖元組裝、裁剪剔除、光柵化、片段著色器以及混合測(cè)試。
此外還可以抽象為4個(gè)階段
應(yīng)用階段:由CPU主要負(fù)責(zé)的階段,且完全由開發(fā)人員掌控。CPU將決定遞給GPU什么樣的數(shù)據(jù)(目標(biāo)場(chǎng)景的燈光、模型),有時(shí)候還會(huì)對(duì)這些數(shù)據(jù)進(jìn)行處理(將攝像機(jī)不可見的元素被**剔除(culling)**出去),并且告訴GPU這些數(shù)據(jù)的渲染狀態(tài)(譬如紋理、材質(zhì)、著色器等)。
這一階段最重要的輸出是渲染所需的幾何信息,即渲染圖元(通俗來講可以是點(diǎn)、線、面等)
幾何階段:負(fù)責(zé)大部分多邊形操作和頂點(diǎn)操作,將三維空間的數(shù)據(jù)轉(zhuǎn)換為二維空間的數(shù)據(jù)。
光柵化階段:決定每個(gè)渲染圖元中哪些像素應(yīng)該被繪制在屏幕上,它需要對(duì)上一階段得到的逐頂點(diǎn)數(shù)據(jù)進(jìn)行插值
像素處理階段:給每一個(gè)像素正確配色,最后繪制出整幅圖像
應(yīng)用程序階段在CPU端完成,后面的所有階段都是在GPU端完成(所以又稱GPU渲染管線)
特點(diǎn)
渲染管線的一個(gè)特點(diǎn)就是每個(gè)階段都會(huì)把前一個(gè)階段的輸出作為該階段的輸入。
例如,片段著色器會(huì)將光柵化后的片段(以及片段的數(shù)據(jù)塊)作為輸入進(jìn)行光照計(jì)算。除了圖元組裝和光柵化幾個(gè)階段是由硬件自動(dòng)完成之外,管線的其他階段管線都是可編程/可配置的。
各個(gè)階段的功能
應(yīng)用階段
渲染管線的起點(diǎn)是CPU,CPU與GPU的通信即上文的應(yīng)用階段
(1)把數(shù)據(jù)加載到顯存:將數(shù)據(jù)加載到顯存中能使GPU更快的訪問這些數(shù)據(jù),當(dāng)把數(shù)據(jù)加載到顯存后,便可以釋放了數(shù)據(jù),但一些數(shù)據(jù)仍需留在內(nèi)存中,如CPU需要網(wǎng)格數(shù)據(jù)進(jìn)行碰撞檢測(cè)。
(2)設(shè)置渲染狀態(tài):渲染狀態(tài)的一個(gè)通俗解釋就是,定義了場(chǎng)景中的網(wǎng)格是怎樣被渲染的。例如,使用哪個(gè)頂點(diǎn)著色器/片段著色器、光源屬性、材質(zhì)等。如果不設(shè)置渲染狀態(tài),那所有的網(wǎng)格將使用同一種渲染,顯然這是不希望得到的結(jié)果。
(3)調(diào)用Draw Call:當(dāng)所有的數(shù)據(jù)準(zhǔn)備好后,CPU就需要調(diào)用一個(gè)渲染指令告訴GPU,按照上述設(shè)置進(jìn)行渲染,這個(gè)渲染命令就是Draw Call。Draw Call命令僅僅指向被渲染的圖元列表,而不包含任何材質(zhì)信息
在實(shí)際的渲染中,GPU的渲染速度往往超過了CPU提交命令的速度,這導(dǎo)致渲染中大部分時(shí)間都消耗在了CPU提交Draw Call上。有一種解決這種問題的方法是使用批處理(Batching),即把要渲染的模型合并在一起提交給GPU
GPU渲染管線
綠色表示開發(fā)者可以完全編程控制的部分,虛線外框表示此階段不是必需的,黃色表示開發(fā)者無法完全控制的部分(但可以進(jìn)行一些配置),紫色表示開發(fā)者無法控制的階段(已經(jīng)由GPU固定實(shí)現(xiàn))
幾何階段
頂點(diǎn)著色器
頂點(diǎn)著色器的處理單位是頂點(diǎn),但是每次處理都是獨(dú)立的,因此無法創(chuàng)建或銷毀任何一個(gè)頂點(diǎn),也不能得到與其他頂點(diǎn)的關(guān)系
頂點(diǎn)著色器主要功能是進(jìn)行坐標(biāo)變換。將輸入的局部坐標(biāo)變換到世界坐標(biāo)、觀察坐標(biāo)和裁剪坐標(biāo)。
雖然我們也會(huì)在頂點(diǎn)著色器進(jìn)行光照計(jì)算(稱作高洛德著色),然后經(jīng)過光柵化插值得到各個(gè)片段的顏色,但這種得到的光照比較不自然,所以一般在片段著色器進(jìn)行光照計(jì)算
曲面細(xì)分著色器
曲面細(xì)分是利用鑲嵌化處理技術(shù)對(duì)三角面進(jìn)行細(xì)分,以此來增加物體表面的三角面的數(shù)量,是渲染管線一個(gè)可選的階段
幾何著色器
在這個(gè)階段,開發(fā)者可以控制GPU對(duì)頂點(diǎn)進(jìn)行增刪改操作
投影
GPU將頂點(diǎn)從攝像機(jī)觀察空間轉(zhuǎn)換到裁剪空間(又被稱為齊次裁剪空間),為之后的剔除過程以及投射到二維平面做準(zhǔn)備。
常見的投影方式有透視投影與正交投影。
在三維中原有的三個(gè)分量x、y、z上又額外增加了w=1分量,使得可以通過矩陣乘的方式為三維坐標(biāo)實(shí)現(xiàn)平移的效果。
裁剪
只有當(dāng)圖元部分或全部位于視椎體內(nèi)時(shí),我們才會(huì)將它送到流水線的下個(gè)階段,也就是光柵化階段。對(duì)于部分位于視椎體的圖元,位于外部的頂點(diǎn)將被裁剪掉,而且在視椎體與線段的交界處產(chǎn)生新的頂點(diǎn)。
在把不需要的頂點(diǎn)裁剪掉后,GPU需要把頂點(diǎn)映射到屏幕空間,這是一個(gè)從三維空間轉(zhuǎn)換到二維空間的操作。
-
對(duì)于透視裁剪空間,GPU需要對(duì)裁剪空間中的頂點(diǎn)執(zhí)行齊次除法(將齊次坐標(biāo)系中的w分量除x、y、z分量),得到頂點(diǎn)的歸一化的設(shè)備坐標(biāo)(NDC)
通過透視除法后,我們得到了NDC坐標(biāo),獲得NDC坐標(biāo)是為了實(shí)現(xiàn)屏幕坐標(biāo)的轉(zhuǎn)換與硬件無關(guān)。
-
正交裁剪空間只需要把w分量去掉即可。
此時(shí)頂點(diǎn)的x、y坐標(biāo)接近于在屏幕上所處的位置了,此時(shí)z分量不會(huì)被丟棄而是被寫入了深度緩沖(z-buffer)
屏幕映射
屏幕映射的任務(wù)就是將每個(gè)圖元的x、y值變換到屏幕坐標(biāo)系,對(duì)于z坐標(biāo)不做任何處理(實(shí)際上屏幕坐標(biāo)系和z坐標(biāo)一起構(gòu)成窗口坐標(biāo)系),這些值會(huì)被一起傳遞到光柵化階段
一般來說,屏幕坐標(biāo)是2D的概念,只用于表示屏幕XY坐標(biāo),而窗口坐標(biāo)是2.5D的概念,它還帶有深度信息,也就是經(jīng)過變換后的Z軸的信息。
使用齊次坐標(biāo)的意義,其實(shí)就是為了正確記錄下投影變換前(觀察空間)中物體的深度信息,也就是Z坐標(biāo)的值。
光柵化階段
光柵化會(huì)確定圖元所覆蓋的片段,利用頂點(diǎn)屬性插值得到片段的屬性信息,然后送到片段著色器進(jìn)行顏色計(jì)算,我們這里需要注意到片段是像素的候選者,只有通過后續(xù)的測(cè)試,片段才會(huì)成為最終顯示的像素點(diǎn)。
三角形設(shè)置(Triangle Setup)
這個(gè)過程做的工作就是把頂點(diǎn)數(shù)據(jù)收集并組裝為簡(jiǎn)單的基本體(線、點(diǎn)或三角形)
三角形遍歷(Triangle Traversal)
這個(gè)過程將檢驗(yàn)屏幕上的某個(gè)像素是否被一個(gè)三角形網(wǎng)格所覆蓋,被覆蓋的區(qū)域?qū)⑸梢粋€(gè)片元(Fragment)
片元不是真正意義上的像素,而是包含了很多種狀態(tài)的集合(譬如屏幕坐標(biāo)、深度、法線、紋理等)
而片元的劃分依據(jù)(像素塊被覆蓋到何種程度才被劃分)不管怎么樣都會(huì)產(chǎn)生鋸齒,這就有許多抗鋸齒的采樣方式(比如MSAA)
片段著色器
片元著色器的輸入是上一個(gè)階段對(duì)頂點(diǎn)信息進(jìn)行插值的結(jié)果(是根據(jù)從頂點(diǎn)著色器輸出的數(shù)據(jù)插值得到的),而它的輸出是像素顏色值
這個(gè)階段我們能進(jìn)行很多渲染技術(shù),比如根據(jù)頂點(diǎn)法線或者UV計(jì)算顏色,接受陰影或者是進(jìn)行紋理采樣(紋理坐標(biāo)是通過前述階段的頂點(diǎn)數(shù)據(jù)插值得到的)
逐片元計(jì)算
對(duì)每個(gè)片元進(jìn)行操作,將它們的顏色以某種形式合并,得到最終在屏幕上像素顯示的顏色。主要的工作有兩個(gè):對(duì)片元進(jìn)行測(cè)試(Test)并進(jìn)行合并(Merge)。
裁切測(cè)試
在裁剪測(cè)試中,允許程序員開設(shè)一個(gè)裁剪框,只有在裁剪框內(nèi)的片元才會(huì)被顯示出來,在裁剪框外的片元皆被剔除。
模板測(cè)試
模板測(cè)試通常用來限制渲染的區(qū)域,渲染陰影,輪廓渲染等
在模板測(cè)試中,GPU將讀取片元的模板值與模板緩沖區(qū)的模板值進(jìn)行比較,比較函數(shù)由開發(fā)者指定,如果比較不通過,這個(gè)片元將被舍棄
深度測(cè)試
現(xiàn)實(shí)生活中,近的物體會(huì)遮擋住遠(yuǎn)處的物體,深度緩沖就是用來實(shí)現(xiàn)這種效果的。
GPU將讀取片元的深度值(就是我們前面留下來的坐標(biāo)z分量)與緩沖區(qū)的深度值進(jìn)行比較,和模板測(cè)試一樣,如何渲染物體之間的遮擋關(guān)系也是自定義的(可以讓GPU把沒有被遮擋的部分隱藏了,讓被遮擋的部分顯示出來的。)
大量的被遮擋片元直到深度測(cè)試階段才會(huì)被剔除,而在此之前它們同樣地被計(jì)算,這占用了GPU大量的資源。
因此有種優(yōu)化技術(shù)是將深度測(cè)試提前(Early-Z)。但這帶來了與透明度測(cè)試的沖突,例如某個(gè)片元甲雖然遮擋了另一個(gè)片元乙,但甲卻是透明的,GPU應(yīng)當(dāng)渲染的是片元乙,這就產(chǎn)生了矛盾,這就是透明度測(cè)試會(huì)導(dǎo)致性能下降的原因
合并
一個(gè)片元通過了所有測(cè)試,片元顏色就會(huì)被送到顏色緩沖區(qū),到達(dá)了合并環(huán)節(jié)
合并有兩種主要的方式,一種是直接進(jìn)行顏色的替換,另一種是根據(jù)不透明度進(jìn)行混合(Blend)
如果開啟了混合,GPU會(huì)取出片元著色器得到的顏色(源顏色)和顏色緩沖區(qū)存在的顏色(目標(biāo)顏色),之后按照設(shè)定的函數(shù)進(jìn)行混合,可以設(shè)定透明度通道進(jìn)行相加,相減還是相乘。
最后GPU會(huì)使用雙重緩沖(Double Buffering)的策略,即屏幕上顯示前置緩沖(Front Buffer),而渲染好的顏色先被送入后置緩沖(Back Buffer),再替換前置緩沖,以此避免在屏幕上顯示正在光柵化的圖元
渲染管線中的坐標(biāo)系變換
- 我們從建模工具得到的是物體的局部坐標(biāo)(Local Coordinate),
- 局部坐標(biāo)通過模型矩陣Model變換到世界坐標(biāo)(World Coordinate),
? 光照計(jì)算一般都是在世界空間進(jìn)行的,所以輸入的頂點(diǎn)坐標(biāo)需要通過乘以模型矩陣變換到世界空間。在模型變換時(shí),通常還需要將法線變換到世界空間中,對(duì)于法線變換不能簡(jiǎn)單的使用模型變換矩陣來變換法線,對(duì)于包含非均勻縮放的變換,需要求解模型變換的逆轉(zhuǎn)置矩陣
-
世界坐標(biāo)通過觀察矩陣View變換到觀察坐標(biāo)(View Coordinate),
虛擬攝像機(jī)定義了我們的觀察空間。虛擬攝像機(jī)的位置是坐標(biāo)的原點(diǎn),觀察方向沿著Z軸的負(fù)方向。我們可以通過攝像機(jī)的位置(EyePosition)、觀察目標(biāo)點(diǎn)(FocusPosition)和向上的方向向量(UpDirection)來構(gòu)建觀察矩陣。
-
觀察坐標(biāo)經(jīng)過投影矩陣Projection變換到裁剪坐標(biāo)(Clip Coordinate),
? 裁剪空間的目標(biāo)是能夠方便的對(duì)圖元進(jìn)行裁剪,這塊空間是由視錐體決定的,視錐體外為看不到的區(qū)域,也就是被裁剪的部分。當(dāng)時(shí)不同的視錐體有不同的處理過程,而且透視投影判斷點(diǎn)是否在視錐體內(nèi)比較麻煩,通過一個(gè)投影矩陣將頂點(diǎn)轉(zhuǎn)換到裁剪空間中是一種通用、方便的方式。——常見的投影矩陣有透視投影和正交投影
? 投影矩陣并沒有真正的進(jìn)行投影工作,而是為投影做準(zhǔn)備,真正的投影發(fā)生在齊次除法過程中,這發(fā)生在屏幕空間映射階段
-
裁剪坐標(biāo)經(jīng)過透射除法(Perspective Division)得到標(biāo)準(zhǔn)設(shè)備空間(Normalized Device Coordinates,NDC),
-
NDC坐標(biāo)通過視口變換(Viewport Transformation)變換到窗口坐標(biāo)進(jìn)行顯示
總結(jié)
- 上一篇: Subplot函数
- 下一篇: 《软件过程管理》 第二章 软件过程成熟