圖形學(xué)原理與U3D渲染管線優(yōu)化

前言
今天要分享的主題是圖形學(xué)原理與U3D渲染管線,本文除了講解傳統(tǒng)的圖形學(xué)原理以外,還會講到U3D最新的可編程渲染管線
版權(quán)聲明
本文為“優(yōu)夢創(chuàng)客”原創(chuàng)文章,您可以自由轉(zhuǎn)載,但必須加入完整的版權(quán)聲明
更多學(xué)習(xí)資源請加QQ:1517069595或WX:alice17173獲?。ㄆ髽I(yè)級性能優(yōu)化/熱更新/Shader特效/服務(wù)器/商業(yè)項(xiàng)目實(shí)戰(zhàn)/每周直播/一對一指導(dǎo))
點(diǎn)贊、關(guān)注、分享可免費(fèi)獲得配套學(xué)習(xí)資源
3D圖形渲染流水線

圖形學(xué)解決了什么問題?
圖形學(xué)解決的問題就是使用程序控制顯卡將場景中的游戲模型全部渲染出來
這其中還涉及了幾個(gè)方面的知識
游戲模型
寫程序來控制物體渲染,發(fā)送數(shù)據(jù)到圖形渲染管線里
理解圖形渲染管線
上圖是3D圖形渲染流水線的流程圖,這張圖將整個(gè)渲染流水線分成了11個(gè)步驟

這11個(gè)步驟又可以劃分為3塊
第一塊是游戲的數(shù)據(jù),數(shù)據(jù)被送到顯卡的渲染流水線里面
第二塊內(nèi)容是一些頂點(diǎn)處理,因?yàn)槊拦ぷ龊玫哪P臀募写鎯Φ木褪悄P兔恳粋€(gè)頂點(diǎn)的各種信息,比如位置信息、方向信息、紋理坐標(biāo)等等,這些信息送到顯卡的渲染流水線里面經(jīng)過2、3、4、5、6、7這六個(gè)步驟處理后就變成了一個(gè)個(gè)像素點(diǎn)
這些像素點(diǎn)在處理時(shí)要經(jīng)過8、9、10這3個(gè)像素階段,也就是上圖中的第三塊內(nèi)容,經(jīng)過這些像素階段處理后輸出的就是屏幕上最終顯示的3D畫面
渲染步驟下面的圖介紹了模型在經(jīng)過一系列渲染時(shí)發(fā)生的變化

圖中的第一個(gè)小房子是美工制作的模型,這個(gè)模型在頂點(diǎn)處理階段進(jìn)行頂點(diǎn)的位置變換和頂點(diǎn)的光照計(jì)算,現(xiàn)在的光照計(jì)算一般都是放在像素管線里進(jìn)行的,因?yàn)橄袼毓芫€渲染出的效果比較精細(xì)啊
上面第二張圖就是燈光計(jì)算環(huán)節(jié),可以看到圖中一盞燈光對游戲場景進(jìn)行照射,其實(shí)在這張圖還有一項(xiàng)處理,也就是模型的位置變換,將這些三維空間中的這些房子模型放置在游戲世界的某一角落里,經(jīng)過位置變換后,模型被攝像機(jī)照射時(shí)就能把模型渲染出來了
像素頂點(diǎn)處理階段到像素處理階段中有一個(gè)重要的步驟叫做光柵化,光柵化的算法是比較復(fù)雜的,它內(nèi)部需要經(jīng)過一些掃描線格處理,當(dāng)然了,我們并不需要關(guān)心那么復(fù)雜的東西,只要知道有一個(gè)步驟是頂點(diǎn)到像素的轉(zhuǎn)換步驟是叫做光柵化
光柵化以后,就對物體的表面進(jìn)行了填充,上圖中最后畫面里的小房子上有一個(gè)個(gè)點(diǎn)狀的,像像素點(diǎn)一樣的花紋,這就是光柵化步驟的算法要實(shí)現(xiàn)的功能,在圖形學(xué)課程中,上面這些是整整一章的內(nèi)容,但是它的目的就只有一個(gè),就是把頂點(diǎn)變成一些像素
變成像素后就會進(jìn)入到像素處理階段,像素處理階段主要是干幾個(gè)事情
1,基于像素的光照運(yùn)算
2,基于像素的貼圖運(yùn)算
把上面這些步驟都走完以后,還有一些比較細(xì)節(jié)的步驟,比如渲染的背面裁剪、阿爾法測試、模板測試、一些誤效處理、阿爾法混合等等,經(jīng)過這些處理以后就能看到屏幕上面顯示的一個(gè)又一個(gè)的三角形了
其實(shí)3D流水線和工廠造車這種概念是非常類似的,下面就進(jìn)一步帶大家,就像用放大鏡一樣看看流水線里每一個(gè)車間是干什么事兒的,但因?yàn)槠P(guān)系,沒有辦法帶大家把每一個(gè)車間都看一遍,就重點(diǎn)看一下最基本的和最重要的兩個(gè)環(huán)節(jié),也就是頂點(diǎn)著色器和像素著色器
世界變換

頂點(diǎn)著色器所處理的三維空間變換可以劃分為四個(gè)空間三個(gè)階段
每一個(gè)物體都有自己的坐標(biāo)空間,這個(gè)坐標(biāo)空間可以叫做模型空間,假設(shè)將自己看成是游戲中的一個(gè)角色,那么以我們自己的坐標(biāo)位置為中心點(diǎn)來觀察世界,這時(shí)我們所處的空間就叫做模型空間,模型空間是物體自身的坐標(biāo)空間
上圖中最上方畫了3個(gè)茶壺,它們都有自身的坐標(biāo)空間,但如果把這三個(gè)茶壺放在同一個(gè)游戲世界里,那么這些茶壺在游戲世界當(dāng)中不可能每一個(gè)都有坐標(biāo)空間,它們必須處于同一個(gè)坐標(biāo)空間中,這個(gè)坐標(biāo)空間就是世界坐標(biāo)空間
也就是說這3個(gè)茶壺從自己的視角來看都是世界的中心,但如果站在游戲世界的角度來看,那么每一個(gè)物體都不是世界的中心,世界的中心只有一個(gè),就是世界空間的原點(diǎn),這時(shí)再把茶壺放在游戲世界的各個(gè)角落(如上圖最下方的圖片)里,那么它們的方向、位置都不一樣
圖形學(xué)要解決的第一個(gè)問題就是怎樣把這些茶壺放到游戲世界的某一個(gè)角落上面去,這需要經(jīng)過一系列的圖形學(xué)計(jì)算,這樣的計(jì)算可以叫做矩陣變換
經(jīng)過矩陣變換后,物體就能夠被顯卡渲染在游戲世界的某一角落,程序員只需要告訴顯卡游戲模型在游戲世界里的位置(Position)和模型是否進(jìn)行旋轉(zhuǎn)(Rotation)以及要不要進(jìn)行縮放(Scale),將這3個(gè)信息告訴顯卡,顯卡就會生成一個(gè)4行4列的世界空間矩陣
顯卡是不能識別游戲模型的,它看不出來它所渲染的是茶壺,還是人物角色,顯卡只知道你輸入了一批三角形,因?yàn)槊恳粋€(gè)模型都是由三角形面片構(gòu)成的,只要將模型所有的三角形面片輸入到顯卡中,顯卡再經(jīng)過矩陣變換就能把三角形面片的每一個(gè)頂點(diǎn)渲染在程序員設(shè)置的位置上
視圖變換

在游戲世界里從某一個(gè)視角去觀察物體時(shí)就發(fā)生了第二個(gè)坐標(biāo)變換,物體所在的空間由世界空間變換到了視圖空間,在一些術(shù)語里被翻譯成攝像機(jī)空間
將世界空間里的物體轉(zhuǎn)換到視圖空間里去的變換過程叫做視圖變換,有的術(shù)語叫做攝像機(jī)變換,這個(gè)步驟需要做各種各樣的矩陣變換,關(guān)于矩陣如何構(gòu)造本文先不談,那么如果不用矩證表示的話,我必須向顯卡輸入什么信息呢?
一,攝像機(jī)所處位置
二,攝像機(jī)的方向
三,攝像機(jī)的視角是廣角攝像機(jī)還是普通角度攝像機(jī),它的視角有多大?
四,攝像機(jī)橫重比是多少?
其實(shí)上面這些信息在Unity中都能找到對應(yīng)的攝像機(jī)參數(shù),所以在學(xué)習(xí)Unity時(shí)千萬不能浮于表面,只是知道Unity需要提供4個(gè)參數(shù),卻不知道這四個(gè)參數(shù)背后所對應(yīng)的圖形學(xué)原理
投影變換

上個(gè)世紀(jì)80年代的老式照相機(jī)的原理與圖形學(xué)里的投影變換非常相似,老式照相機(jī)在拍照片時(shí)會把景象全部生成到底片上去,其實(shí)這也是投影變換要做的事情
攝像機(jī)的投影方式有兩種
1,平行投影
平行投影就是物體本身是多大最終顯示出的畫面就有多大(如上面PPT中的平行投影圖),此投影方式顯示出的畫面不會因?yàn)槲矬w遠(yuǎn)近而變化
2,透視投影
透視投影是符合人眼的視覺的,它顯示出的畫面會因?yàn)槲矬w遠(yuǎn)近而變化,遵循近大遠(yuǎn)小(如上面PPT中的透視投影圖)
平行投影常常用在2D游戲里面,因?yàn)?D游戲的攝像機(jī)都是平行投影的,還有一種情況就是一些3D斜45度視角的游戲,有的是為了模擬那種2D斜視角風(fēng)格
透視投影常用于3D游戲,如果想做一個(gè)寫實(shí)的3D游戲就肯定要用到透視投影

上圖也是投影變換的概念圖,只是更具體一點(diǎn),是從一些數(shù)學(xué)計(jì)算的角度來看的,在Unity里也有這些選項(xiàng),比如設(shè)置攝像機(jī)的近裁剪平面、遠(yuǎn)裁剪平面,設(shè)置攝像機(jī)視口的寬度和橫重比
設(shè)置這些東西以后投影變換就能正常工作了,使物體能夠進(jìn)行近大遠(yuǎn)小的透視投影
屏幕變換

使用拍立得拍到的照片會拍到照片紙上,如果想要將照片放大就需要送去沖印,同樣的,在三維世界里拍到的游戲世界場景實(shí)際上也是拍在一個(gè)X坐標(biāo)介于-1到1之間、Y坐標(biāo)介于-1到1之間、Z坐標(biāo)介于-1到1之間(如果使用的是OpenGL是-1到1,如果是DirectX3D則是0到1之間)的投影空間中
這個(gè)投影空間的坐標(biāo)范圍很小,橫向、縱向都是兩個(gè)單位,而正常情況下的游戲至少也是800乘600的分辨率,所以需要將這一塊非常小的投影空間經(jīng)過圖形學(xué)放大,放大到游戲所需的屏幕分辨率
總結(jié):頂點(diǎn)變換流程

每一個(gè)物體都有自己的坐標(biāo)空間,叫做模型空間,有的術(shù)語翻譯為對象空間,模型空間經(jīng)過世界空間變換以后,模型空間就變換到世界空間了,也就是放在游戲世界的某一個(gè)角落
在場景里架設(shè)一臺攝像機(jī),由攝像機(jī)去看游戲場景,這時(shí)就要把整個(gè)游戲世界切換到攝像機(jī)空間,進(jìn)入攝像機(jī)空間里的物體會有一些透視效果,需要經(jīng)過透視變換
因?yàn)橥队翱臻g的范圍比較小,所以要將圖像顯示在屏幕上的時(shí)候就需要對它進(jìn)行放大,就像沖印底片一樣,之后就可以得到在屏幕上所能看到的圖像了
像素階段
紋理貼圖

像素著色的大致流程
如何將紋理貼圖貼到游戲模型上呢?這是在像素處理需要考慮的問題,必須確定每一個(gè)物體的頂點(diǎn)與像素圖位置的對應(yīng)關(guān)系
上圖模型的(x0,y0,z0)、(x1,y1,z1)、(x2,y2,z2)是物體的頂點(diǎn)坐標(biāo),它們對應(yīng)了上圖右邊紋理圖的UV坐標(biāo)

確定了物體的頂點(diǎn)坐標(biāo)點(diǎn)和貼圖的坐標(biāo)點(diǎn)后,就可以明確的把紋理貼圖的左上角(由(u0~2,v0~2)構(gòu)成的三角形)貼在模型盒子左上角的三角形上(由(x0~2,y0~2,z0~2)構(gòu)成的三角形),這就是顯卡貼圖的過程
在這個(gè)過程中程序員需要提供每一個(gè)頂點(diǎn)的UV坐標(biāo),有了這些信息以后,顯卡就能確定頂點(diǎn)和它對應(yīng)的圖片位置關(guān)系
像素光照

如果不進(jìn)行貼圖,只進(jìn)行光照運(yùn)算和光柵化,最終得到的圖像就是上圖中的白色飛龍圖片,這個(gè)飛龍沒有任何細(xì)節(jié)表現(xiàn),看上去就像是塑料,為了表現(xiàn)模型的細(xì)節(jié),就需要為模型貼上貼圖,貼上貼圖以后的飛龍模型就是上圖中帶有顏色花紋的圖像
但這樣的圖像看上去還是有點(diǎn)假,因?yàn)閺囊曈X角度來看,這個(gè)模型并沒有光照明暗信息,這需要用到一種次世代技術(shù),叫做逐像素光照
逐像素光照是基于每一個(gè)像素點(diǎn)計(jì)算每個(gè)像素點(diǎn)的光照反射、折射、燈光的遮蔽、光照的方向等等信息,使用逐像素光照,再加上凹凸貼圖、遮擋貼圖、金屬貼圖、反射貼圖等等一堆貼圖就能實(shí)現(xiàn)基于PBR的渲染
通過自定義渲染管線提升渲染性能

剛才講的是顯卡的渲染流水線是比較低級的流水線,只能識別并針對三角形進(jìn)行渲染,如果要進(jìn)行性能優(yōu)化的話也只能針對這些三角形的緩沖來進(jìn)行優(yōu)化,沒有辦法進(jìn)一步提升性能
那么應(yīng)該怎么辦呢?
其實(shí)Unity游戲引擎通過提供一個(gè)更高級別的渲染流水線來讓程序員對渲染過程進(jìn)行優(yōu)化,這就是下面要講的主題:通過自定義的渲染管線來提升渲染性能
它是一個(gè)新技術(shù),叫做SRP(可編程渲染管線技術(shù)),它不是比較底層的Shader可編程,而是Unity引擎層面的可編程

渲染管線的級別中最低級的是GPU,GPU無法識別物體,只是基于三角形構(gòu)成的三角形緩沖區(qū)級別來進(jìn)行渲染
引擎級別的渲染管線就是Unity,Unity能識別游戲中的每一個(gè)物件,然后針對這些物件做各種各樣的處理,比如遮擋剔除、LOD優(yōu)化等等
Unity渲染管線的種類

Unity的渲染管線種類有三種,在Unity5.x階段使用的是Built-in,Unity2018之后增加了SRP渲染管線
Built-in渲染管線是不能做過多的控制的,只能做一些簡單的控制,這叫做內(nèi)置渲染管線
Unity2018之后增加的SRP可編程渲染管線能控制的方面就比較多,但是傳統(tǒng)項(xiàng)目是不能使用SRP的,而SRP又是性能優(yōu)化的一個(gè)關(guān)鍵點(diǎn),所以就必須把項(xiàng)目升級到使用LWRP(URP)或者HDRP這兩種渲染管線之一
IWRP在平時(shí)開發(fā)中可能會用的多一點(diǎn),因?yàn)槌悄愕挠布阅芎芎茫駝t一般都會用IWRP。LWRP翻譯成中文叫做輕量級渲染管線,從功能的角度來說,LWRP適用于移動平臺和VR平臺,因?yàn)閂R的渲染負(fù)擔(dān)比較大,再簡單的畫面都需要渲染兩次
HDRP適用于主機(jī)平臺,比如PC、游戲主機(jī)都可以使用HDRP

給大家看一下程序的效果,這個(gè)場景里面有N多個(gè)游戲角色,想要將這些角色全部同屏渲染出來的開銷是很大的。要進(jìn)行優(yōu)化就需要用到GPUInstance(GPU實(shí)例化)技術(shù),GPUInstance的原理就是針對相同模型、相同材質(zhì)的角色進(jìn)行批處理優(yōu)化
在這個(gè)場景中直接使用GPUInstance進(jìn)行優(yōu)化是無效的,因?yàn)镚PUInstance的優(yōu)化原理是進(jìn)行同材質(zhì)的角色合批,而場景中的角色和陰影的渲染是交錯(cuò)進(jìn)行的,從而無法合批
優(yōu)化方法

優(yōu)化方法
1,通過輕量級渲染管線對渲染進(jìn)行重新排序,從而實(shí)現(xiàn)優(yōu)化
2,盡量保證合批
上圖顯示的場景是通過自定義渲染管線SRP進(jìn)行合批后的效果,一共只有20個(gè)DrawCall
SRP還能做什么?

SRP可以用來做半透明處理優(yōu)化,其實(shí)在筆試面試時(shí)經(jīng)常會問到的問題就是半透明的渲染問題,因?yàn)榘胪该魑矬w在渲染時(shí)的性能很差,因?yàn)榘胪该魑矬w渲染時(shí)必須要關(guān)閉深度寫入,深度寫入關(guān)掉以后會造成渲染時(shí)必須要把所有的物體從后到前全部渲染一遍
要解決這個(gè)問題可以先開啟深度寫入渲染所有不透明物體,渲染完以后再關(guān)閉深度寫入將半透明物體按照距離攝像機(jī)遠(yuǎn)近排序,從后到前渲染
寫在最后
更多學(xué)習(xí)資源請加QQ:1517069595或WX:alice17173獲?。ㄆ髽I(yè)級性能優(yōu)化/熱更新/Shader特效/服務(wù)器/商業(yè)項(xiàng)目實(shí)戰(zhàn)/每周直播/一對一指導(dǎo))
點(diǎn)贊、關(guān)注、分享可免費(fèi)獲得配套學(xué)習(xí)資源