「技美之路」图形 1.1 渲染流水线
今日起開始分享學習技美之路專欄,文章來源聽課筆記以及業界大佬分享的經驗文章,主要來自CSDN_知乎等。技美路漫長 一定要堅持??開始吧!
一.整體流程
整體流程(渲染管線可分為四個階段)每一個階段的輸出為下一個階段的輸入
?
應用階段:準備的是場景,你的對象的基本數據,比如說場景里面的物體他們的位置朝向、大小以及物體對應的模型里邊每一個頂點的位置,法線、切線等等;場景光源的位置朝向和一些基本屬性,還有攝像機的位置朝向等等。這些數據用處在哪里,進入下一個階段
幾何階段:首先在頂點著色器里,我們有可能需要計算頂點光照,那么頂點光照就需要知道光源的位置和朝向以及攝像機的位置和朝向,還有當前頂點的世界位置,通過這些數據來進行計算,曲面細分著色器,需要通過現有的頂點來生成更多的頂點,那么也需要知道現有頂點在模型里的位置信息。幾何著色器,需要通過現有的圖元來做一些幾何方面的操作,生成更多的頂點和圖元比如對現有圖源所在的平面生成法線 那么同樣需要知道現有圖源的頂點的位置,同樣的幾何階段要為光柵化階段準備數據
比如要干掉看不到的屏幕以外的頂點,這就是頂點裁剪
還需要把頂點位置從 3D坐標空間轉換到2D坐標空間,這就是屏幕映射
光柵化階段:拿到映射到2D空間里的頂點位置,我們要把它組裝成三角形,這就是三角形設置然后還要知道三角形包含了哪些2D空間的像素點,這就是三角形遍歷最后我們要對這些點使用它們包含的數據來著色,并且為后面的逐片元著色準備數據
逐片元操作:我們的操作對象就變成了光柵化操作輸出的片元數據,片元可以理解成為屏幕上的某一個像素點,對于這些片元我們需要進行一系列的測試。比如透明度測試,深度測試和模板測試,通過測試的片元就保留起來,否則就丟棄掉,然后在2D屏幕坐標系當中,同一個位置上的像素點有可能會對應于多個不同的片元,那么我們可能還需要把這些通過測試的片元的顏色進行一個混合操作,從而得到像素點最終輸出的顏色,逐片元操作完成以后,我們就得到了一個類似于貼圖的數據保存在內存里,然后我們對這個數據還可以做一個后處理,可以理解成為圖像處理,比如模糊、景深、高光等等,那么這樣的話渲染管線每個階段之間的關系大概就講清楚了。
二.分階段介紹
?
應用階段
?
在渲染管線中,應用階段是在CPU中進行處理的
?
- 首先是準備場景,從磁盤或是內存上讀取模型或者貼圖數據,將其加載進應用程序中,對象為基本數據:包括不限于場景中的物體的位置,朝向,大小,物體網格數據,頂點位置,UV貼圖,法線,切線等;場景的光源位置朝向,類型,參數屬性等;攝像機位置朝向,模式,視口長寬比等等…
補充:光源和陰影
設置光源:
1.方向光,顏色,方向等
2.點光源:顏色,位置,范圍等
3.聚光源:顏色,位置,方向,內外圓錐角等
設置陰影:
1.是否需要陰影:判斷該光源可見范圍內是否有可投陰影的物體
2.陰影參數:對應光源序號,陰影強度,級聯參數,深度偏移,近平面偏移等
逐光源繪制陰影范圍:
1.近平面偏移
2.逐級聯
計算當前光源+級聯對應的觀察矩陣,投影矩陣,以及對應到陰影貼圖里的視口區域
繪制到陰影貼圖
?
- 加速算法,粗粒度剔除:處理遮擋的問題,不會看到的,就不渲染,降低渲染成本,提高渲染性能
- 可見光裁剪:點光和聚光有衰減,聚光錐體有區域;若離相機距離較遠,或者光錐與相機的視錐體不相交,則剔除渲染;
- 可見場景物體裁剪:遮擋啥的,相關算法:八叉樹,BSP樹,k-D樹,PVH包圍盒等
- 說起裁剪就不由想起圖形學里的經典裁剪算法:Liang-Barsky算法,Cohen-Sutherland算法(編碼裁剪算法)這兩個算法是用于將圖像裁剪到可見范圍內
- 設置渲染狀態,準備渲染參數:渲染UI和場景,其參數和模式可能不一樣,通俗解釋:場景中的網格如何被渲染,渲染順序是啥,使用哪個頂點著色器/片元著色器,光源屬性,材質,最后會渲染到哪里,渲染模式等等…
- 繪制設置:使用著色器,合批方式(gpu 動態合批)
- 繪制物體順序:相對相機距離,材質RenderQueue, UICanvas等
- 渲染目標:FrameBuffer, RenderTexture...
- 渲染模式:前向渲染(ForwardBase ForwardAdd),延遲渲染
- 調用DrawCall,輸出渲染圖元到顯存:圖元從CPU邁向GPU
- DrawCall是一個命令,發起方是CPU,接收方是GPU。僅指向一個需要被渲染的圖元(Primitives)列表。
- 頂點數據:位置,顏色,法線,紋理uv坐標,其他頂點數據
- 其他數據:MVP變換矩陣,紋理貼圖,其他數據
幾何階段
?
- 頂點著色器(VertexShader):完全可編程,實現頂點的空間變換、頂點著色等
- 曲面細分著色器(TessellationShader):可選著色器,用于細分圖元
- 幾何著色器(GeometryShader)可選著色器,執行逐圖元著色操作
- 裁剪(Clipping):將不在相機視野內的頂點裁剪掉,可配置
- 屏幕映射(ScreenMapping):不可配置和編程
幾何階段,光柵化,逐片元這些操作都是在GPU中進行處理的,那么在講幾何階段前,我們先聊聊為什么要用GPU渲染?
答:GPU的特點是并行性較好。當我們在對頂點數據進行處理時,他們雖然數據不同,但光照,幾何運算方式啥都一樣的時候,那么我們將他們放在GPU的不同工作單元上進行同時執行,速度會更快。
?
頂點著色器:必須完成的一個工作:將頂點坐標從模型空間轉換到齊次裁剪空間(投影坐標系),同時它還有計算頂點光照的功能,這需要獲取應用階段中光源位置朝向,攝像機位置朝向,當前頂點的世界位置(獲取該位置需知道頂點在模型空間的位置,模型本身的位置旋轉縮放…);
?
頂點著色器-視圖變換:模型坐標系--(模型變換) --> 世界坐標系--(視圖變換)-->視圖坐標系 --(投影變換)-->投影坐標系--(視口變換)-->視口坐標系 上圖中的前三個變換對應MVP(model view projection)矩陣,在頂點著色器中,頂點從模型坐標系轉換到投影坐標系,最后一步由Unity幫忙完成
曲面細分著色器:通過現有頂點生成更多的頂點,需獲取頂點在模型中的位置信息
它是一個可選著色器,使用頂點著色器輸出的頂點,按照一定規則算法生成更多頂點,將現有的網格和圖元細分(其效果類似于MAYA中的“平滑”效果,模型圓滑了但面數增大了)
幾何著色器(基于圖元):通過現有的圖元做些幾何方面操作,二手手機號出售生成更多頂點和圖元,比如對現有圖元所在平面生成法線,需獲取現有圖元頂點位置
圖元是啥?
答:可以為頂點,線段,倆頂點,三角形...基礎的幾何圖形
投影:將3D空間投到2D空間
對于頂點在裁剪空間里的位置,xyzw進行透視除法:xyz除以w完成投影。使其從投影坐標系轉換到標準設備坐標系(NDC);
由于正交和透視視角下w值不同,故而呈現效果不同,正交顯得像截圖,透視則近大遠小
頂點裁剪:消去屏幕外的頂點;
不在相機視野內的物體不需要被處理。一個圖元和相機視野有3種關系:
完全在視野內:繼續傳遞給下一階段
部分在視野內:需要進行裁剪(Clipping),使用新的頂點來代替
完全在視野外:不會向下傳遞
?
- 投影里又說要進行除法操作,當xyz超過-1~1范圍,則判斷其不在范圍內,
舍棄進行經典的圖形學裁剪算法;
- 投影和頂點裁剪在《Shader入門精要》中都是歸屬于裁剪一節中,這個操作過程無法由代碼控制,是硬件上固定操作,但可以自定裁剪操作進行配置
- 設備坐標系在opengl和DirectX中不一樣,opengl xyz三維度取值范圍都是-1~1,DirectX只有xy是-1~1,z為0~1
屏幕映射:
將頂點位置從3D坐標空間轉換到2D坐標空間;
屏幕映射(ScreenMapping)的任務是把每個圖元x和y坐標轉換到屏幕坐標系(ScreenCoordinates)。不處理z坐標。opengl和DirectX原點不同,opengl左下方,DirectX左上方
?
按照《Shader入門精要》所言:屏幕映射任務是把每個圖元的x和y坐標轉換到屏幕坐標系。
如應用階段為幾何階段準備數據一樣,幾何階段同樣會為光柵化階段準備數據
光刪化階段
三角形設置:拿到映射于2D空間里的頂點位置,組裝成三角形;
三角形遍歷:尋找被三角形覆蓋的所有像素的過程,知曉包含哪些2D空間像素點
《Shader入門精要》:三角形遍歷階段將檢查每個像素是否被一個三角網格所覆蓋,若覆蓋,則生成一個片元。
片元非像素,它是包含很多狀態的集合,這些狀態用于計算每個像素的最終顏色,這些狀態包含不限于,屏幕坐標,深度信息,從幾何階段輸出的頂點信息,法線,紋理坐標等。屏幕同一個像素位置可能有對應多個三角形的不同片元(如兩片重疊的交集)
抗鋸齒(MSAA):
1.SSAA:
渲染到一個分辨率放大n倍的buffer:屏幕分辨率1024x1024,渲染得到buffer可為2048x2048,放大四倍,對其采樣后再輸出屏幕
對方打n倍的buffer下采樣
2.MSAA
只有它發生在光柵化階段
計算多個覆蓋樣本:覆蓋測試看子采樣點是否在三角形以內,遮擋測試看這個子采樣度的深度和,即與深度緩存中數值進行比較,看能否通過,若能通過兩測試,則說明采樣點屬于三角形,得到覆蓋信息并保存,用于之后的著色混合
3.FXAA/TXAA
后處理技術
逐片元操作
?
決定可見性:
模板測試(StencilTest):將片元位置的模板值,和參考值進行比較
深度測試(DepthTest):將片元的深度值,和深度緩沖區的深度值進行比較
合并顏色。對于不透明物體,可以關閉混合,用片元著色器得到的顏色值覆蓋顏色緩沖區的像素值。對于半透明物體,要混合。
如果在執行片元著色器之前就進行這些測試,可以提高GPU性能,早點知道那些片元會被舍棄。深度測試提前執行的技術Early-Z。透明度測試會導致禁用提前測試,使性能下降。
為了避免我們看到正在進行光柵化的圖元,GPU會使用雙重緩沖(DoubleBuffering)。渲染在幕后,在后置緩沖(BackBuffer)中,一旦完成,GPU會交換后置緩沖區和前置緩沖(FrontBuffer)的內容。
后處理
Bloom,HDR,FXAA,景深,邊緣檢測,徑向模糊
什么是OpenGL/DirectX
OpenGL/DirectX圖像應用編程接口。運行在CPU上的應用程序->調用OpenGL/DirectX等圖形接口,將數據存在顯存,
發出DrawCall->顯卡驅動翻譯成GPU能理解的代碼。
?
什么是HLSL、GLSL、CG
著色語言(ShadingLanguage):
DirectX的HLSL(HighLevelShadingLanguage)
OpenGL的GLSL(OpenGLShadingLanguage)
NVIDIA的CG(C for Graphic)
在UnityShader中,可以選擇使用哪種,但有所區別。
什么是DrawCall
DrawCall,CPU調用圖像編程接口,以命令GPU進行渲染的操作。
問題一:CPU和GPU是如何實現并行工作的?
命令緩沖區(CommandBuffer),讓CPU和GPU可以并行工作。CPU向其中添加命令,GPU從中讀取命令,添加和讀取的過程是相互獨立的。
?
問題二:為什么DrawCall多了會影響幀率?
GPU渲染能力很強,速度往往快于CPU提交命令的速度。如果DrawCall的數量太多,CPU會耗費大量時間造成過載。
?
問題三:如何減少DrawCall?
這里討論批處理方法(Batching)。把很多小的DrawCall合并成一個大的DrawCall,更適合合并靜態的物體,因為只需合并一次。
?
為了減少DrawCall的開銷,需要注意:
避免使用大量很小的網格,合并小網格
避免使用過多的材質,盡量在不同網格之間共用同一個材質
什么是固定管線渲染
固定函數的流水線(Fixed-Function Pipeline),簡稱為固定管線,只給開發者一些配置操作。隨著時代的發展,可編程渲染管線應運而生,如頂點著色器、片元著色器。
那么,你明白什么是Shader了嗎
Shader所在階段,就是渲染流水線的一部分:
GPU流水線上一些可高度編程的階段,由著色器編譯出來的最終代碼會在GPU上運行
有一些特定類型的著色器,如頂點著色器、片元著色器
依靠著色器我們可以控制流水線中的渲染細節
總結
以上是生活随笔為你收集整理的「技美之路」图形 1.1 渲染流水线的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 「技美之路」图形 1.2.1 向量基础
- 下一篇: 设计总结:腾讯光子《和平精英》全新UI