概念渲染流水線
應(yīng)用階段
由CPU實(shí)現(xiàn),在這個(gè)階段侍瑟,開(kāi)發(fā)者占有絕對(duì)的控制權(quán)唐片。
此階段實(shí)現(xiàn)3個(gè)任務(wù):
1 準(zhǔn)備好場(chǎng)景的數(shù)據(jù),例如:攝像機(jī)的位置涨颜、視錐體费韭、包含的模型、包含的光源庭瑰;
2 粗粒度剔除(culling)把不可見(jiàn)得物體剔除出去(這樣就不需要交給幾何階段進(jìn)行處理了)星持;
3 設(shè)置好每個(gè)模型的渲染狀態(tài),渲染狀態(tài)包括:材質(zhì)(漫反射顏色弹灭、高光反射顏色)督暂、使用紋理、使用Shader等
此階段輸出渲染需要的幾何信息 =>即是 渲染圖元(渲染圖元可以是:點(diǎn)穷吮、線逻翁、polygon)
這一階段主要是由開(kāi)發(fā)者決定的。
幾何階段
通常在GPU上進(jìn)行
幾何階段負(fù)責(zé)和每一個(gè)渲染圖元操作捡鱼,進(jìn)行逐頂點(diǎn)八回、逐多邊形的操作。幾何階段的重要任務(wù)就是把頂點(diǎn)坐標(biāo)變換到屏幕空間中驾诈,再交給光柵器處理缠诅。通過(guò)多步處理這一階段會(huì)輸出屏幕的二維頂點(diǎn)坐標(biāo)、每個(gè)頂點(diǎn)對(duì)應(yīng)的深度值翘鸭、著色相關(guān)信息滴铅,傳遞給下一個(gè)階段。
光柵化階段
依據(jù)上一個(gè)階段的數(shù)據(jù)在屏幕上產(chǎn)生相應(yīng)的像素就乓,并且輸出最終的圖像。這一階段也是在GPU上進(jìn)行的拱烁。光柵化主要決定每個(gè)渲染圖元中的哪些像素應(yīng)該被繪制在屏幕上生蚁。需要對(duì)幾何階段的頂點(diǎn)數(shù)據(jù)(包括紋理坐標(biāo),頂點(diǎn)顏色等)進(jìn)行差值戏自,然后進(jìn)行像素處理邦投。
*以上的是概念性的流水線,接下來(lái)是實(shí)際在硬件中發(fā)生的流水線擅笔。
CPU 和 GPU 之間的通信
可分為三個(gè)階段:
<1>把數(shù)據(jù)加載到顯存中
所有的渲染所需數(shù)據(jù)全部從硬盤(pán)(Hard Disk Drive志衣, HDD)中加載到系統(tǒng)內(nèi)存(Random Access Memory屯援,RAM)中。然后念脯,網(wǎng)格和紋理這樣的數(shù)據(jù)(包括:位置信息狞洋、法線方向、頂點(diǎn)顏色绿店、紋理坐標(biāo))有被加載到顯卡的儲(chǔ)存空間—顯存上(Video Random Access Memory吉懊,VRAM)中。這是源于假勿,顯卡對(duì)于顯存的訪問(wèn)速度更快借嗽,而且大多數(shù)的顯卡對(duì)于RAM無(wú)直接的訪問(wèn)權(quán)限。
<2>設(shè)置渲染狀態(tài)
狀態(tài)定義了場(chǎng)景中的網(wǎng)格是會(huì)被再怎樣渲染转培。例如:使用哪個(gè)頂點(diǎn)著色器(Vertex Shader)/ 片元著色器(Fragment Shader)恶导、光源屬性、材質(zhì)等的浸须。如果不設(shè)置渲染狀態(tài)甲锡,所有的網(wǎng)格都將進(jìn)行同樣的一種渲染狀態(tài)。
<3>調(diào)用Draw Call
Draw Call就是一個(gè)命令羽戒,發(fā)起方是CPU缤沦,接收方是GPU。命令只會(huì)指向一個(gè)需要被渲染出來(lái)的圖元(primitives)列表易稠,不會(huì)包含任何材質(zhì)信息缸废。給定了Draw Call后GPU會(huì)根據(jù)渲染狀態(tài)來(lái)進(jìn)行計(jì)算。
GPU的計(jì)算過(guò)程就是GPU內(nèi)部的流水線驶社。
GPU流水線
GPU渲染過(guò)程就是GPU流水線
代表概念流程中的幾何階段和光柵化階段
綠色的區(qū)塊表示:可以完全編輯程序控制的企量;黃色的區(qū)塊表示:可以配置但是不可以編程;藍(lán)色的區(qū)塊表示:由GPU固定實(shí)現(xiàn)開(kāi)發(fā)者沒(méi)有控制權(quán)亡电。實(shí)線表示shader必須由開(kāi)發(fā)者編程實(shí)現(xiàn)届巩,虛線表示這個(gè)shader是可以選擇的。
1.頂點(diǎn)著色器(Vertex Shader)
完全可編程
通常用于實(shí)現(xiàn)頂點(diǎn)的空間變換份乒、頂點(diǎn)著色等功能恕汇。
頂點(diǎn)著色器是流水線的第一個(gè)階段,它的輸入來(lái)自于CPU或辖。頂點(diǎn)著色器的處理單位是頂點(diǎn)瘾英,輸入進(jìn)來(lái)的每個(gè)頂點(diǎn)都會(huì)調(diào)用一次頂點(diǎn)著色器。頂點(diǎn)著色器本身并不會(huì)創(chuàng)建或者銷毀頂點(diǎn)颂暇,而且無(wú)法得到頂點(diǎn)與頂點(diǎn)之間的關(guān)系缺谴。
例如:我們無(wú)法得知兩個(gè)頂點(diǎn)是否屬于一個(gè)三角網(wǎng)格。正因?yàn)檫@樣的相互獨(dú)立性耳鸯,GPU可以利用本身的特性并行化處理每一個(gè)頂點(diǎn)湿蛔。
頂點(diǎn)著色器需要完成的工作主要有:坐標(biāo)變換和頂點(diǎn)光照膀曾。當(dāng)然還可以輸出后續(xù)階段所需的數(shù)據(jù)。
坐標(biāo)變換
對(duì)頂點(diǎn)的坐標(biāo)進(jìn)行某種變換阳啥。頂點(diǎn)著色器可以在這一部中改變定點(diǎn)的位置添谊,這在頂點(diǎn)動(dòng)畫(huà)中非常有用。例如:我們可以通過(guò)改變頂點(diǎn)位置模擬水面和布料的效果苫纤。
無(wú)論如何在頂點(diǎn)著色器中怎么樣改變定點(diǎn)位置碉钠,一個(gè)最基本的頂點(diǎn)著色器必須完成的一個(gè)工作是,把頂點(diǎn)坐標(biāo)從模型空間轉(zhuǎn)換到齊次裁剪空間卷拘。
能夠常見(jiàn)的代碼:
o.pos = mul(UNITY_MVP, ?v.position);
類似的代碼就是將頂點(diǎn)坐標(biāo)轉(zhuǎn)換到齊次坐標(biāo)系下喊废,接著再由硬件做透視出發(fā)后,最終得到歸一化的設(shè)備坐標(biāo)栗弟。
2.裁剪(Clipping)
可配置
這一階段的目的是將那些不再攝像機(jī)視野內(nèi)的頂點(diǎn)裁減掉污筷,并剔除某些三角圖元的面片。
目的:處理不在攝像機(jī)視野范圍內(nèi)的物體乍赫。
一個(gè)圖元和攝像機(jī)視野有三種關(guān)系:完全在視野內(nèi)瓣蛀、部分在視野內(nèi)、完全在視野外雷厂。完全在視野內(nèi)的圖元即系傳遞給下一個(gè)流水線階段惋增,完全在視野外的圖元就不會(huì)向下傳遞,因?yàn)椴恍枰讳秩靖啮辍6切┎糠衷谝曇皟?nèi)的圖元就需要進(jìn)行一個(gè)處理诈皿,那就是裁剪。
和頂點(diǎn)著色器不同像棘,這一步是不可編程的稽亏。無(wú)法通過(guò)編程來(lái)控制裁剪的過(guò)程,是硬件上的固定操作
但是可以自定義一個(gè)剪裁操作來(lái)對(duì)這一步進(jìn)行配置
3.屏幕映射(Screen Mapping)
不可配置和編程的
這一步輸入的坐標(biāo)仍然是三維坐標(biāo)系下的坐標(biāo)缕题。
負(fù)責(zé)把每個(gè)圖元的坐標(biāo)轉(zhuǎn)換到屏幕坐標(biāo)系中截歉。
4.三角形設(shè)置(Triangle Setup)和三角形變量(Triangle Traversal)階段都是固定函數(shù)(Fixed-Function)的階段
這一階段開(kāi)始進(jìn)入光柵化階段。從上一個(gè)階段輸出的信息是屏幕坐標(biāo)系下的頂點(diǎn)位置以及和它們相關(guān)的額外信息烟零,如:深度值(Z)瘪松、法線方向、視角方向等瓶摆。
光柵化階段有兩個(gè)重要的目標(biāo):計(jì)算每個(gè)圖元的覆蓋了哪些像素凉逛,以及為這些像素計(jì)算顏色。
三角形設(shè)置:計(jì)算光柵化一個(gè)三角網(wǎng)格所需的信息群井。具體來(lái)講,上一個(gè)階段輸出的都是三角網(wǎng)格的頂點(diǎn)毫胜,即我們得到的是三角網(wǎng)格每條邊的兩個(gè)頂點(diǎn)书斜。但是如果要得到整個(gè)三角形網(wǎng)格對(duì)像素的覆蓋情況诬辈,我們就必須計(jì)算每條邊上的像素坐標(biāo)。為了能夠計(jì)算邊界像素的坐標(biāo)信息荐吉,我們就需要得到三角形邊界的表示方式焙糟。這樣一個(gè)計(jì)算三角形網(wǎng)格表示數(shù)據(jù)的過(guò)程叫做三角形設(shè)置。
三角形遍歷
檢查每個(gè)像素是否被一個(gè)三角網(wǎng)格所覆蓋样屠。如果覆蓋的話穿撮,就會(huì)生成一個(gè)片段(fragment)。這樣一個(gè)找到哪些像素被三角網(wǎng)格覆蓋的過(guò)程就是三角形遍歷痪欲,這個(gè)階段也被稱為掃描變換(Scan Conversion)悦穿。
片段并不是真正意義上的像素,而是包含了很多狀態(tài)的集合业踢,這些狀態(tài)用于計(jì)算每個(gè)像素的最終顏色栗柒。
5.片元著色器(Fragment Shader)
完全可編程
用于實(shí)現(xiàn)逐片元(Per-Fragment)的著色操作。
片段著色器的輸入是上一個(gè)階段對(duì)頂點(diǎn)信息插值得到的結(jié)果知举,更具體來(lái)說(shuō)瞬沦,是根據(jù)那些從頂點(diǎn)著色器中輸出的數(shù)據(jù)插值得到的。輸出的是一個(gè)或者多個(gè)顏色值雇锡。
這一個(gè)階段可以完成很多重要的渲染技術(shù)逛钻,其中最重要的技術(shù)之一就是紋理采樣。為了在片段著色器中進(jìn)行紋理采樣锰提,通常會(huì)在頂點(diǎn)著色器階段輸出每個(gè)頂點(diǎn)對(duì)應(yīng)的紋理坐標(biāo)曙痘,然后經(jīng)過(guò)光柵化階段對(duì)三角網(wǎng)格的3個(gè)頂點(diǎn)對(duì)應(yīng)的紋理進(jìn)行插值后,就可以得到其覆蓋的片段的紋理坐標(biāo)了欲账。
6.逐片元操作(Per-Fragment Operations)
不可編程屡江,但具有很高的可配置性
負(fù)責(zé)執(zhí)行很多重要的操作,例如:修改顏色赛不、深度緩沖惩嘉、進(jìn)行混合等。
這一階段OpenGL-逐片元操作 DirectX-輸出合并階段
這一階段有幾個(gè)重要的任務(wù):
(1) 決定每個(gè)片元的可見(jiàn)性:這涉及了很多測(cè)試工作踢故,例如:深度測(cè)試文黎、模板測(cè)試
(2) 如果一個(gè)片元通過(guò)了所有的測(cè)試,就需要把這個(gè)片元的顏色值和已經(jīng)儲(chǔ)存在顏色緩沖區(qū)中的顏色進(jìn)行合并殿较,或是說(shuō)混合
如果片元沒(méi)有通過(guò)測(cè)試將無(wú)法與顏色緩沖區(qū)進(jìn)行混合耸峭。