圖形學(xué)(渲染管線)學(xué)習(xí)日記
作用:1.物體3D坐標(biāo)轉(zhuǎn)成屏幕2D坐標(biāo) 2.對屏幕每個像素點進(jìn)行著色
流程:頂點數(shù)據(jù)的輸入、頂點著色器、曲面細(xì)分過程、幾何著色器、圖元組裝、裁剪剔除、光柵化、片段著色器以及混合測試(每個前一階段輸出均為該階段輸入)(頂點著色器、曲面細(xì)分相關(guān)著色器、幾何著色器和片段著色器可以編程)
頂點數(shù)據(jù):頂點坐標(biāo)、紋理坐標(biāo)、頂點法線和頂點顏色。
頂點著色器:將輸入局部坐標(biāo)變換為世界坐標(biāo),觀察坐標(biāo)和裁剪坐標(biāo)。輸入:頂點及其屬性。輸出:變換后的頂點
曲面細(xì)分(可選):利用鑲嵌化處理技術(shù)對三角面進(jìn)行細(xì)分從而增加物體表面的三角面的數(shù)量,實現(xiàn)離攝像機(jī)近物品細(xì)節(jié)多,遠(yuǎn)細(xì)節(jié)少。
幾何著色器(可選):輸入:完整圖元 輸出:0個或1個或多個其他圖元。 作用是將輸入的點/線拓展為多邊形。
圖元組裝:頂點組裝為指定圖元。 會進(jìn)行裁剪,背面剔除優(yōu)化,減少輸入光柵化圖元數(shù)量。在光柵化之前需要屏幕映射(透視除法和視口變換,由硬件實現(xiàn))
光柵化:將連續(xù)3D物體離散為屏幕像素點。過程:確定圖元覆蓋的片段,利用頂點屬性插值得到片段的屬性信息,然后送到片段著色器進(jìn)行顏色計算(片段是像素的候選,通過測試才能成為像素點)
片段著色器:決定屏幕中像素最終顏色。(進(jìn)行光照計算和陰影處理,產(chǎn)生高級效果)
測試混合階段:裁切測試、Alpha測試,模板測試和深度測試。(未通過測試片段被丟棄,通過測試片段進(jìn)行alpha混合,alpha=0完全透明,=1完全不透明)通過OpenGL或directX定制測試和混合方式

《Real Time Rendering》將渲染管線劃分為4階段
應(yīng)用程序:碰撞檢測、動畫物理模擬以及視椎體剔除,將頂點數(shù)據(jù)送入渲染管線
幾何處理:頂點著色器,圖元組裝(可以理解為先變換頂點,再將變換后頂點進(jìn)行裁剪,拼接為圖元,映射至屏幕)
光柵化:連續(xù)圖元離散化為片段。
像素處理:像素著色和混合。
對于幾萬面的復(fù)雜模型,通過加載建模工具(Blender,3dmax,maya)產(chǎn)生的數(shù)據(jù),提高效率。有大量三角面共用頂點,通過使用頂點緩存對象來避免頂點間數(shù)據(jù)冗余。
頂點著色器
從建模工具中得到的是局部坐標(biāo),通過模型矩陣變換成世界坐標(biāo),再通過觀察矩陣變換成觀察坐標(biāo),通過投影矩陣變換成裁剪坐標(biāo),通過透視除法變換成NDC(標(biāo)準(zhǔn)設(shè)備坐標(biāo)),通過視口變換變換至窗口坐標(biāo)進(jìn)行顯示。
視錐體
由近平面,遠(yuǎn)平面,垂直視場角,屏幕縱橫比四個參數(shù)定義。

在OpenGL中分別用glm:ortho()和glm:perspective()創(chuàng)建正交投影和透視投影矩陣。
根據(jù)光照計算不同,有平面著色、高洛德著色和馮氏著色。
平面著色是使用一個頂點顏色來代表整個三角面的顏色,默認(rèn)使用索引第一個頂點顏色,無法展示高光效果。性能開銷最小。
高洛德著色在頂點著色器中計算三個頂點的光照信息,然后在光柵化階段插值得到三角形內(nèi)部各個片段的光照信息。由于高光部分非線性,故插值表現(xiàn)差。
馮氏著色,效果最好但性能開銷最高。根據(jù)輸入的頂點法線信息在光柵化階段插值得到各個片段的法線信息,然后在片段著色器中利用法線、紋理坐標(biāo)、位置等信息計算每個片段的光照信息
曲面細(xì)分著色器(可選)
利用鑲嵌化處理技術(shù)對三角面進(jìn)行細(xì)分,以此來增加物體表面的三角面的數(shù)量。
不用創(chuàng)建高模來豐富網(wǎng)格信息?;贕PU可以實現(xiàn)動態(tài)的LOD技術(shù),可以根據(jù)物體距離攝像機(jī)的遠(yuǎn)近來調(diào)整多邊形網(wǎng)格的細(xì)節(jié)。遠(yuǎn)的時候用高模渲染就浪費。拉近的時候使用連續(xù)鑲嵌就可以。先保存低維信息,有需求再GPU動態(tài)加細(xì)節(jié),可以節(jié)省內(nèi)存。
幾何著色器(可選)
可以創(chuàng)建或銷毀幾何圖元。通常用來實現(xiàn)一種叫做公告欄的視覺效果。
圖元組裝
裁剪:完全位于視椎體外部的圖元會被裁剪掉,不會對它們進(jìn)行渲染。
背面剔除:剔除那些背對攝像機(jī)的圖元。默認(rèn)不開啟,用glEnable(GL_CULL_FACE)開啟優(yōu)化。僅可對完全不透明對象使用。

屏幕映射(透視除法+視口變換)
透視除法:實現(xiàn)透射投影中近大遠(yuǎn)小的視覺效果,由硬件自動執(zhí)行。
視口變換:獲取窗口坐標(biāo),帶有變換后的z軸信息。glViewport() 設(shè)定視口的坐標(biāo)和寬高。如果視口小于屏幕空間,會造成多余的像素被渲染

光柵化(三角形組裝+三角形遍歷)
三角形組裝:對頂點輸入數(shù)據(jù)(法線、紋理坐標(biāo))插值,獲取片段對應(yīng)數(shù)值(法線、紋理坐標(biāo))。很少插顏色值而通過片段著色器著色。

三角形遍歷:通過屏幕空間坐標(biāo)組建三角形,遍歷這些三角形所覆蓋的片段采樣點,獲取對應(yīng)片元。
片段著色器
計算光照使用模型-phong
將物體光照分為漫反射分量、鏡面高光和環(huán)境光來計算
環(huán)境光:疊加一個較小光照,來表示來自其他物體反射的間接光照
漫反射光:無論觀察者從哪個方向進(jìn)行觀察,漫反射效果相同,與觀察位置無關(guān)。在原來的代碼加上float hLambert = difLight * 0.5 + 0.5。即可升級為半朗伯模型。將之前的漫反射系數(shù)從[0,1]變到[0.5,1]

鏡面反射需要知道觀察者位置,進(jìn)而表現(xiàn)金屬反射出的高光。
鋸齒和抗鋸齒
3d連續(xù)物體離散化成2d像素點會產(chǎn)生鋸齒。
超級采樣抗鋸齒(ssaa)最直接最好,800x600的屏幕渲染到1600x1200的緩沖區(qū)再下采樣回800x600。計算量很大。這個用的4*ssaa,使得光柵化和片段著色器都是原來的4倍,渲染緩存的大小也是原來的4倍。
測試和混合
裁切測試:避免當(dāng)視口比屏幕窗口小時造成的渲染浪費。當(dāng)視口的大小和屏幕空間一樣大就不用。默認(rèn)不開啟裁切測試,glEnable(GL_SCISSOR_TEST)開啟,glScissor()指定裁切區(qū)域
alpha測試:顏色一般采用RGBA,a代表透明度,根據(jù)片段顏色的 Alpha值來裁剪片段。消耗大性能低,必要才用。

Early-Z Culling:深度/模板測試是在片段著色器之后進(jìn)行的,所以導(dǎo)致著色器計算資源的浪費(著色無用被遮擋片段)不能修改深度緩沖否則gpu無法開啟early-z。alpha測試會讓他失效所以效率低。
模板測試:通過mask的值來控制那些片段的可見性,無法通過mask的片段將被丟棄。默認(rèn)不開啟,通過glEnable(GL_STENCIL_TEST)開啟,用glStencilMask設(shè)置mask,用glStencilFunc和glStencilOp設(shè)置模板函數(shù),控制測試成功/失敗時的行為??蓪崿F(xiàn)平面鏡效果、平面陰影和物體輪廓。

深度測試:片段深度值是否比深度緩沖預(yù)設(shè)值小,若是,則更新深度緩沖和顏色緩沖,若否,則丟棄片段不更新緩沖區(qū)值。默認(rèn)不開啟。通過glEnable(GL_DEPTH_TEST)開啟。glDepthFunc() 來設(shè)置深度比較運算符,默認(rèn)為GL_LESS(前面的物體會蓋住后面的物體)
Alpha混合
用于實現(xiàn)半透明效果,通過glEnable(GL_BLEND)開啟。通過 glBlendFuncSeparate() 、glBlendFunc() 和glBlendEquation() 來設(shè)置各種混合效果。通過下面混合方程調(diào)整效果。

先渲染不透明再渲染半透明,因為透過半透明能看不透明,渲染半透明需要不透明圖層信息,才能精確混合。
學(xué)習(xí)自https://positiveczp.github.io/