歡迎前往個人博客 駑馬點滴 和視頻空間 嗶哩嗶哩-《挨踢日志》
2.1 綜述
流水線
在工業(yè)上赂蠢,流水線被用在裝配線上像吻。未引入流水線之前掌实,一個產(chǎn)品的生產(chǎn)有多個環(huán)節(jié)仪缸,需要等上一個環(huán)節(jié)完成敷待,才能進(jìn)入下一個環(huán)節(jié)匿乃。生產(chǎn)的時間等于各個環(huán)節(jié)的時間之和色迂。在引入流水線后霞捡,各個環(huán)節(jié)同時進(jìn)行蚀狰,正常運行時愉昆,生產(chǎn)的時間由最慢的那一環(huán)節(jié)決定。
渲染流水線
在 Real-Time Rendering, Third Edition 一書中麻蹋,將渲染流程按先后順序分為三個階段:應(yīng)用階段跛溉、幾何階段、光柵化階段扮授。
應(yīng)用階段由應(yīng)用主導(dǎo)(開發(fā)者控制)芳室,一般在 CPU 中進(jìn)行。首先刹勃,要準(zhǔn)備好場景數(shù)據(jù)堪侯,例如攝像機位置、視錐體荔仁、場景中包含哪些模型伍宦、使用了哪些光源等等;其次乏梁,為了提高渲染性能次洼,需要做粗粒度剔除(culling),避免將工作移交給幾何階段處理遇骑;最后卖毁,需要設(shè)置好每個模型的渲染狀態(tài),這些狀態(tài)包括但不限于材質(zhì)(漫反射顏色落萎、高光反射顏色)亥啦、紋理、Shader模暗;應(yīng)用階段輸出的內(nèi)容為渲染所需的幾何信息(簡單說就是點禁悠、線、三角面等信息)兑宇,即渲染圖元(Rendering Primitive)碍侦,這些信息會被傳遞給渲染的下一個階段——幾何階段。
應(yīng)用階段從 CPU 和 GPU 交互層面來說,可以分為三個階段:
- 把數(shù)據(jù)加載到顯存中瓷产;
- 設(shè)置渲染狀態(tài)站玄;
- 調(diào)用 Draw Call;
幾何階段處理所有和我們要繪制的幾何相關(guān)的事情濒旦。例如株旷,決定需要繪制的圖元有哪些、怎樣繪制這些圖元晾剖、在哪里繪制它們齿尽。這一階段通常在 GPU 上進(jìn)行。幾何階段的一個重要任務(wù)是把頂點坐標(biāo)轉(zhuǎn)化到屏幕坐標(biāo),再交付給光柵器處理全跨。通過對輸入的渲染圖元進(jìn)行多步處理后盒使,這一階段將會輸出屏幕空間的二維頂點坐標(biāo)苞慢、每個頂點對應(yīng)的深度值、著色等相關(guān)信息辑畦,并傳遞給下一個階段——光柵化階段。
光柵化階段會使用上一階段傳遞的數(shù)據(jù)來產(chǎn)生屏幕上的像素,并渲染出最終的圖像陨收。這一階段也是在 GPU 上運行的它褪。光柵化的主要任務(wù)是決定每個渲染圖元中的哪些像素應(yīng)該被繪制在屏幕上宏悦。它需要對上一個階段得到的逐頂點數(shù)據(jù)(例如紋理坐標(biāo)诗越、頂點顏色等)進(jìn)行插值块促,然后進(jìn)行逐像素處理薇搁。
2.2 CPU 和 GPU 之間的通信
渲染流水線的起點是應(yīng)用階段。應(yīng)用階段大致分為一下三個部分:
把數(shù)據(jù)加載到顯存中;
設(shè)置渲染狀態(tài)粮宛;
調(diào)用 Draw Call貌踏;
2.2.1 把數(shù)據(jù)加載到顯存中
所有數(shù)據(jù)都是從硬盤(HDD, Hard Disk Drive)中加載到內(nèi)存(RAM, Random Access Memory)中,然后網(wǎng)格窟勃、紋理等數(shù)據(jù)又被加載到顯存(VRAM, Video Random Access Memory)中祖乳。這是因為,顯卡對顯存的訪問速度更快秉氧,而大多數(shù)顯卡對 RAM 沒有直接的訪問權(quán)限眷昆。
2.2.2 設(shè)置渲染狀態(tài)
什么是渲染狀態(tài)?通俗的解釋是汁咏,這些狀態(tài)定義了場景中的網(wǎng)格是怎樣被渲染的亚斋。例如,使用了哪個頂點著色器/片元著色器攘滩、光源帅刊、材質(zhì)等。如果沒有更改渲染狀態(tài)漂问,那么所有的網(wǎng)格將使用同一種渲染狀態(tài)(五角星赖瞒、三角形、圓形顯示出相同的效果蚤假,只是形狀不一樣)栏饮。
2.2.3 調(diào)用 Draw Call
Draw Call 是一個由 CPU 向 GPU 發(fā)起的指令。渲染狀態(tài)已經(jīng)準(zhǔn)備就緒磷仰,CPU 向 GPU 發(fā)起 Draw Call 指令袍嬉,指令指向一個渲染圖元列表。GPU 根據(jù)渲染狀態(tài)和所有輸入的頂點信息灶平,最終輸出成屏幕上顯示的像素伺通,該過程即是 GPU 流水線。
2.3 GPU 流水線
2.3.1 概述
頂點數(shù)據(jù) ->(幾何階段:頂點著色器->曲面細(xì)分著色器->幾何著色器->裁剪->屏幕映射)->
(光柵化階段:三角形設(shè)置->三角形遍歷->片元著色器->逐片元操作)->屏幕圖像
2.3.2 頂點著色器
頂點著色器(Vertext Shader)是流水線的第一個階段逢享,主要完成的功能有:坐標(biāo)變換罐监、逐頂點光照、輸出后續(xù)階段所需要的數(shù)據(jù)拼苍。
坐標(biāo)變換:把頂點坐標(biāo)從模型空間轉(zhuǎn)換到齊次剪裁空間笑诅。NDC (Normalized Device Coordinates)
2.3.3 裁剪
裁剪(Clipping):將部分在視野內(nèi)的圖元進(jìn)行處理调缨。將圖元裁剪到單位立方體中疮鲫。
2.3.4 屏幕映射
屏幕映射的輸入仍然是三維坐標(biāo),其任務(wù)是把每個圖元的 x 和 y 坐標(biāo)轉(zhuǎn)換到屏幕坐標(biāo)系(Screen Coordinates)下弦叶。而 z 坐標(biāo)不會被處理俊犯,屏幕坐標(biāo)和 z 坐標(biāo)一起構(gòu)成了窗口坐標(biāo)系(Window Coordinates)。這些值會被傳遞到光柵化階段伤哺。
注意:屏幕坐標(biāo)系在 OpenGL 和 DirectX 之間的差異燕侠。OpenGL 以屏幕左下角為原點者祖,DirectX 以屏幕左上角為原點。
2.3.5 三角形設(shè)置
三角形設(shè)置這步開始绢彤,就進(jìn)入光柵化階段了七问。上一步驟的輸出是屏幕坐標(biāo)系下的三角網(wǎng)格的各個頂點信息。為了渲染出三角網(wǎng)格對應(yīng)屏幕上的像素點的情況茫舶,需要計算三角網(wǎng)格每條邊的表示方式械巡。這樣一個計算三角網(wǎng)格表示數(shù)據(jù)的過程就叫做三角形設(shè)置。
2.3.6 三角形遍歷
三角形遍歷階段會檢查每個像素是否被一個三角網(wǎng)格所覆蓋饶氏。如果被覆蓋讥耗,就會生成一個片元(fragment)。而這樣一個找到哪些像素被三角網(wǎng)格覆蓋的過程就是三角形遍歷疹启。該階段也稱為掃描變換(Scan Conversion)古程。
三角形遍歷會使用三角網(wǎng)格3個頂點信息對其覆蓋的像素進(jìn)行插值。
三角形遍歷的輸出:片元序列喊崖。一個片元是包含了很多狀態(tài)的集合挣磨。(片元)=(屏幕坐標(biāo)、深度信息荤懂、頂點信息(法線趋急、紋理坐標(biāo)等))。
2.3.7 片元著色器
片元著色器(Fragment Shader)的輸入是上一個階段對頂點信息插值得到的結(jié)果势誊。它的輸出是一個或者多個顏色值呜达。
片元著色器完成的一個重要任務(wù)是紋理采樣。
2.3.8 逐片元操作
逐片元操作(Per-Fragment Operations)是 OpenGL 中的說法粟耻,在 DirectX 中查近,這一階段被稱為輸出合并階段(Output-Merger)。
這個階段首先解決片元可見性問題挤忙。通過 片元->模版測試->深度測試->混合->顏色緩沖區(qū) 的操作進(jìn)行霜威。
事實上,測試順序并不是唯一的册烈,GPU 會盡可能在進(jìn)行片元著色器之前進(jìn)行這些工作(比如說 Early-Z 技術(shù))戈泼。
歡迎前往個人博客 駑馬點滴 和視頻空間 嗶哩嗶哩-《挨踢日志》