技術(shù)美術(shù)TA面試題匯總

1. 渲染分幾個(gè)階段?
渲染3個(gè)階段:應(yīng)用階段.幾何階段.光柵化階段.
應(yīng)用階段:由CPU處理。把視野外的物體剔除掉,然后設(shè)置要渲染的狀態(tài)(材質(zhì)紋理、紋理、Shader等),然后把圖元(點(diǎn)、線、三角面)傳遞到幾何階段。
幾何階段:由GPU處理。處理傳來的頂點(diǎn)和三角面。這個(gè)階段重要任務(wù)就是把模型坐標(biāo)轉(zhuǎn)換到屏幕坐標(biāo)。這一階段會(huì)輸出屏幕空間的二維頂點(diǎn)坐標(biāo)、頂點(diǎn)的深度值、顏色等相關(guān)屬性。
光柵化階段:由GPU處理。圖元所包含的像素進(jìn)行處理。然后哪些像素要被輸出到屏幕上。
2. 什么是DrawCall?
CPU設(shè)置好了渲染狀態(tài),然后告訴GPU要渲染什么。這一告訴的階段被稱之為DrawCall。
3. GPU渲染的過程?
頂點(diǎn)數(shù)據(jù)->頂點(diǎn)著色器->曲面細(xì)分->幾何處理->裁剪->屏幕映射->三角形設(shè)置->三角形遍歷->片元著色器->逐片元操作->打印屏幕圖像
頂點(diǎn)著色器:可完全編程。最主要的是把模型空間的位置轉(zhuǎn)換到裁剪空間。同時(shí)處理頂點(diǎn)顏色。
曲面細(xì)分:可完全編程。這個(gè)階段細(xì)分圖元用的。比如實(shí)現(xiàn)LOD效果,加頂點(diǎn)實(shí)現(xiàn)更細(xì)節(jié)的動(dòng)畫,用低模加細(xì)分在運(yùn)行的時(shí)候?qū)崿F(xiàn)高模效果。
曲面細(xì)分詳細(xì)分為三個(gè)階段。Hull Shader Stage、Tessellator Stage、Domain Shader Stage。
Hull Shader Stage基本是配置的。告訴第二個(gè)階段(Tess)要怎么細(xì)分。比如用是用三角形,還是四邊形細(xì)分。細(xì)分的每個(gè)邊有分成幾個(gè)點(diǎn)。
Tessellator Stage是自動(dòng)完成的。通過HS配置的數(shù)據(jù),利用重心坐標(biāo)系、貝賽爾曲線等生成新的面。
Domain Shader Stage是處理新產(chǎn)生的面。比如設(shè)置它們的Normal之類的。
幾何著色器。是完全可編程的。在頂點(diǎn)著色器階段我們不能得知頂點(diǎn)和頂點(diǎn)的關(guān)系,但是在幾何著色器可以。幾何著色器主要是添加或者減少圖元。
裁剪階段。是只能配置的。在裁剪坐標(biāo)系(其次坐標(biāo)系)下裁減掉不再視野外的圖元。如果一個(gè)圖元一半在視野內(nèi),一半在視野外。則會(huì)裁剪掉視野外的然后添加新的頂點(diǎn)完成。比如實(shí)現(xiàn)雙面效果,我們可以用兩個(gè)Pass 分別Cull Front Cull Back來實(shí)現(xiàn)。
屏幕映射:不能配置和編程。即每個(gè)圖元的X和Y坐標(biāo)轉(zhuǎn)換到二維的屏幕坐標(biāo)系。坐標(biāo)跟分辨率有關(guān)。OpenGL和DirectX的頂點(diǎn)和方向不一樣,需要用UV_STARTS_AT_TOP宏來判斷。
三角形設(shè)置:不能配置和編程。計(jì)算三角網(wǎng)格表示數(shù)據(jù)的過程。
三角遍歷:不能配置和編程。一個(gè)三角形所覆蓋的片元情況。此時(shí)片元還不是真正的像素。
片元著色器:可完全變成。進(jìn)行片元的效果處理。
逐片元操作:只能配置。先進(jìn)行測(cè)試工作,比如模版測(cè)試->深度測(cè)試->透明測(cè)試。如果通過所有測(cè)試還要進(jìn)行顏色混合。當(dāng)然如果沒有透明的話片元測(cè)試會(huì)在片元著色器前面。最后輸出像素到顏色緩沖區(qū)。
屏幕映射:利用雙重緩沖技術(shù),把顏色打印到屏幕上。
4. CommandBuffer是什么做什么用?
可以利用指令渲染一些東西,不用攝像機(jī)。比如直接在一個(gè)RT用指令渲染一個(gè)人。
5. 也可以用CommandBuffer和GrabPass?
GrabPass和CommandBuffer 都可以進(jìn)行捕捉。GrabPass只有在每幀第一次的時(shí)候進(jìn)行捕捉,CommandBuffer可以每幀多次捕捉。
6. 人物描邊的幾種做法?
一.屏幕后處理方法。先用獲取深度圖,再比較點(diǎn)和周圍八個(gè)點(diǎn)的Normal和Depth是否大于一定的閥值,如果是則是邊,添加顏色。
二.視角和法線的點(diǎn)積,進(jìn)行描邊。
三.寫兩個(gè)Pass, 然后第一個(gè)pass的頂點(diǎn)根據(jù)法線外移一定的量進(jìn)行描邊。
7. 屏幕模糊處理?
一.壓縮像素模糊。獲取屏幕圖片,然后放在低像素的RT進(jìn)行壓縮,再放回到原像素。
二.快速模糊。獲取屏幕圖片,像素點(diǎn)取周圍4或8個(gè)點(diǎn)的顏色累加,然后再除以4或8。
三.卷積核模糊(高斯模糊)。獲取屏幕圖片,按照周圍的點(diǎn)用一定的卷積核(按權(quán)系數(shù))進(jìn)行平均顏色。
四.運(yùn)動(dòng)模糊1。儲(chǔ)存多幀圖片。圖片按權(quán)融合作為最后的屏幕圖片。
五.運(yùn)動(dòng)模糊2。獲取上一幀和當(dāng)前幀的深度紋理。建立當(dāng)前片元的NDC。當(dāng)前的世界坐標(biāo)*上一幀的VP再除以上一幀的齊次坐標(biāo)的w,得到上一幀數(shù)的lastNDC,再lastNDC-ndc=>speed,沿speed方向進(jìn)行多次采樣。作為顏色,
六.深度模糊(景深DOF)。獲取深度圖,深度大于一定的閥值取周圍點(diǎn)進(jìn)行模糊。
8. Bloom的做法?
在C#中OnRenderImage中獲取當(dāng)前屏幕圖片,然后用Luminance(光亮度,即RGB*一定系數(shù))的方法找出曝光區(qū)域,曝光區(qū)域進(jìn)行模糊處理,最后和原圖疊加。
9. Glow的做法?
一.在C#中利用Shader的RenderType 用RenderWithShader 替換要發(fā)亮的Shader 然后再在C#中進(jìn)混合。
二.利用CommandBuffer提前把人物渲染進(jìn)行混合。
三.如果人物的Alpha通道沒有用則可以利用Alpha通道進(jìn)行發(fā)光處理。
10. FXAA的做法?
先用Depth和Normal進(jìn)行識(shí)別邊緣,在判斷哪個(gè)邊緣的方向需要補(bǔ)齊,再取周圍的點(diǎn)進(jìn)行混合。
11. Fog的做法?
一.利用深度圖,像素點(diǎn)和Fog的深度進(jìn)行比較,然后乘一定的灰度值。
二.利用Unity_Fog 的方法,Unity_CALC_FOG_FACTOR_RAW(CameraWorldPos-ObjectWorldPos)來實(shí)現(xiàn)Fog.
12. 實(shí)現(xiàn)降低亮度的感覺?
顏色輸入,通過卷積核進(jìn)行顏色校正,實(shí)現(xiàn)暗的感覺。
13. HDR?
通過色調(diào)映射,將原來的顏色進(jìn)行映射處理得到新的顏色。
14. ShadowMap的實(shí)現(xiàn)?
一.在燈的位置用相機(jī)渲染一個(gè)LightMode 為ShadowCaster Pass通道來得到可投射陰影的光源的陰影映射紋理以及攝像機(jī)的深度紋理,利用這兩個(gè)紋理來得到屏幕空間的陰影圖,如果攝像機(jī)的深度圖中記錄的表面深度大于轉(zhuǎn)換到陰影映射紋理中的深度值,則說明該表面是可見的但是卻處于陰影當(dāng)中。
二.接受陰影直接用Unity 的Shadow_Coords、Transfer_Shadow和 Shadow_Attenuation。光照衰減用Unity_Light_Attenuation
15. BRDF的參數(shù)?
BRDF(Albedo(基礎(chǔ)顏色),Spec(反射顏色),OneMinusRefl,Smoothness(光滑度),WorldNormal,WorldViewDir,UnityLight(光顏,光方向,物體法線和光的點(diǎn)積(NDOTL)),
UnityIndirect(漫反射,鏡面反射)。
16. BRDF 漫反射公式?
Disney BRDF F->菲尼爾 D->法線 G->陰影遮擋
17. 延遲渲染GBUFFER參數(shù)。
GBufer.0.rgb=albedo
GBufer.0.a=occlusion
GBuffer.1.rgb=spec Color
GBuffer.1.a=smooth
GBuffer.2=normal
GBuffer.3=emission color
18. UI的原理?
Mesh組成,即面片。然后將UI圖片渲染在上面。
19. 九宮格UI的原理?
Mesh 的頂點(diǎn)拉伸。
20. UI的描邊?
即復(fù)制UI的頂點(diǎn)外移。
21. RectMas2D和 Mask 的區(qū)別?
RectMask2D不會(huì)合批,如果只有一個(gè)MASK 優(yōu)先使用。Mask 多個(gè)內(nèi)部會(huì)合批,但是不會(huì)和外部的合批,2個(gè)以上建議用。
22. ETC壓縮的原理的和比例?
ETC1將圖片分為4x4的塊來壓縮,由4x4x24=384bit壓縮為64bit,壓縮倍率為6。對(duì)像素塊的顏色進(jìn)行編碼,修改像素塊的亮度得到最終紋理。
23. 延遲渲染和正向渲染的區(qū)別?
正向渲染先著色計(jì)算,再深度測(cè)試。光數(shù)量為n物體數(shù)量為m,復(fù)雜度n*m。
延遲渲染先深度測(cè)試,在著色計(jì)算。光數(shù)量為n物體數(shù)量為m,復(fù)雜度n+m。
延遲渲染渲染的優(yōu)勢(shì):就是把光源數(shù)目和場(chǎng)景數(shù)目分開了所以復(fù)雜度低,
只渲染可見的像素節(jié)省計(jì)算量,用更少的Shader,對(duì)后處理支持良好,在大量光源的場(chǎng)景尤為明顯。
延遲渲染缺點(diǎn):內(nèi)存開銷大,GBuffer讀寫的性能瓶頸,透明物體存在問題渲染需要結(jié)合正向渲染,對(duì)MSAA抗鋸齒支持不好。
24. 如何降低GC?
一.頻繁使用的臨時(shí)變量提升為成員變量
二.共享的成員提升為靜態(tài)變量(單例化)
三.GC大的函數(shù)盡量繞過去(切換場(chǎng)景執(zhí)行GC.Collect)
四.使用合理的數(shù)據(jù)結(jié)構(gòu)(Struct Class out ref)
五.使用合理的復(fù)用策略,減少new Object(ObjectPool,StringBuilder)
六.減少設(shè)計(jì)的耦合防止循環(huán)引用(橋接模式)
25. UI渲染的優(yōu)化?
一.UI減少DC用圖集(2的冪整數(shù)),也可以動(dòng)態(tài)生成圖集
二.圖片盡量別重疊。
三.Z值為0可以減少DC。
四.動(dòng)靜分離(細(xì)分Canvas拆分UIPlanes)。
五.不可見的設(shè)置Size為0或者設(shè)置Layer不可見,別SetActive。
六.關(guān)閉UI的Mipmap,減少內(nèi)存開銷
七.不透明UI,頂點(diǎn)數(shù)量換像素減少Over Draw開銷
八.視野外的不一定會(huì)剔除(會(huì)有DC),建議手動(dòng)不可見
九.減少特效字體(顏色、漸變、內(nèi)容頻繁更改(會(huì)導(dǎo)致頻繁渲染)),Rich Text
十.不要用空紋理Image來增加觸碰范圍,會(huì)增加DC,OverDraw,用Empty4Raycast 代替
26. 場(chǎng)景的優(yōu)化?
一.少動(dòng)態(tài)光和物體頂點(diǎn),一些曲面棱角用法線圖代替。
二.不透明物體減少DC,減少材質(zhì)數(shù)量,減少面片(開銷DC>材質(zhì)數(shù)量>面片)
三.Combine 一些小的Mesh。
四.Static Batching、Dynamic Batching 、GPU Instance 渲染合批
五.設(shè)置視野距離、ShadowDistance、ShadowMap質(zhì)量(開銷高>中約等于低) 。
六.LOD,甚至遠(yuǎn)處直接用面片。
七.使用剔除組
八.開啟多線程渲染,但是會(huì)增加不透明和UI的渲染開銷
九.現(xiàn)在的手機(jī)分辨率高,可以降低分辨率來提高Frag Shader,同時(shí)降低我們開的RT的分辨率來提高效率
十.地形和多貼圖的PBR材質(zhì)用Texture2DArray(降低glbindTexture)
27. 粒子和動(dòng)畫優(yōu)化?
一.減少粒子系數(shù)數(shù)量和粒子數(shù)量(開銷粒子系統(tǒng)數(shù)量>粒子數(shù)量)
二.粒子使用讓粒子處于調(diào)用Play去播放 而不是 setactive
三.使用粒子池
四.多粒子系統(tǒng)可用一套圖集
五.調(diào)節(jié)動(dòng)畫誤差值、浮點(diǎn)精度可以適當(dāng)調(diào)節(jié)大來減少包占用
六.視野外的Visible不播放動(dòng)畫
七.通過貼圖來完成頂點(diǎn)動(dòng)畫
28.HSR?
隱藏表面消除(Hidden-surface removal):Early-Z技術(shù)。是指消除實(shí)體物體被其他物體所遮擋的那部分(隱藏直線消除與此類似,有用線性模型);實(shí)現(xiàn)隱藏表面消除的最簡(jiǎn)單方法是使用深度緩沖區(qū)(又稱z緩沖區(qū))。深度緩沖區(qū)原理是把一個(gè)距離觀察平面(通常是近側(cè)裁剪平面)的深度值或者距離與窗口中的每個(gè)元素相關(guān)聯(lián)。
29.FPK?
FPK 是 Forward pixel kill(FPK) 即arm mali gpu中的一種隱藏面消除方法。
對(duì)于不透明的物體,當(dāng)按照從后往的次序渲染的時(shí),可以改善性能。
與Earyly zs test 的區(qū)別是 , Early-ZS 從前往后的次序渲染可以kill 掉 overdraw 。
但是實(shí)際情況不一定都是前往后,所以設(shè)計(jì)了FPK與Early-ZS提高GPU的性能
一句話總結(jié):FPK 是 作用在安卓ARM GPU下的,針對(duì)于不透明物體,在從后往前渲染下的一種隱藏面消除方法,用于改善性能。Early ZS Test 是從前往后渲染的kill overdraw來提高性能的方法。FPK 與 Early ZS 互補(bǔ)提高GPU性能。
觸發(fā)FPK的條件:必須通過Early ZS Test 并做了Early ZS Buffer 更新的fragment才可以Kill 其他的fragment.每個(gè)fragment有兩個(gè)狀態(tài)To Kill(Kill 別的Fragment) To Be Kill(被別的Fragment Kill)只有當(dāng)前被標(biāo)記成To KIll ,然后后進(jìn)入FIFO隊(duì)列,這樣就能Kill 前面的To be Kill Fragment。
作用方法:標(biāo)記成To Kill 的fragment 后進(jìn)入FIFO 隊(duì)列 殺死前面的To be Kill Fragment。
30.GPU的IMR和TBR?
IMR(immediate mode rendering):用于桌面(PC)的GPU的渲染模式。對(duì)于每一個(gè)draw call,vertex shading做完拼成圖元后直接做fragment shading,pipeline不會(huì)中斷執(zhí)行。
IMR優(yōu)點(diǎn):架構(gòu)簡(jiǎn)單,頂點(diǎn)輸出結(jié)構(gòu)經(jīng)過裁剪等直接進(jìn)入片元。這樣不用額外的內(nèi)存來儲(chǔ)存中間結(jié)果,并且節(jié)省寫出、讀入的內(nèi)存帶寬。
IMR缺點(diǎn):如果先渲染遠(yuǎn)的,再渲染近的,被近的遮擋會(huì)產(chǎn)生無效渲染。
TBR(tile based rendering):TBR是指對(duì)于一個(gè)FBO(幀緩沖), 將其拆成許多小的tile,先執(zhí)行所有draw call的vertex shading,拼裝成相應(yīng)的圖元后,接著對(duì)于每一個(gè)tile,各用一張鏈表(polygon list)來記錄位于該tile中的圖元;然后對(duì)于每一個(gè)tile中的每一個(gè)圖元進(jìn)行光柵化和fragment shading。
TBR優(yōu)點(diǎn):一、節(jié)省帶寬,將FBO拆分成小Tile,這樣內(nèi)存中儲(chǔ)存的就是很多個(gè)小Tile來保存渲染結(jié)果,可以用片內(nèi)Memory來儲(chǔ)存,片內(nèi)Memory的優(yōu)勢(shì)是訪問速度快。二、FBO的vertex shading完了之后,可以知道每個(gè)drawcall物體的相對(duì)位置,可以用Early ZS Test 和 FPK 來Kill 掉不必要的Fragment,減少不必要的運(yùn)算。
TBR缺點(diǎn):一、Vertex shading的計(jì)算結(jié)果以及每個(gè)tile和triangle list需要存到物理內(nèi)存。Fragment Shading又要從物理內(nèi)存里面讀回。所以需要額外的儲(chǔ)存空間和執(zhí)行效率。隨著模型復(fù)雜度的增加,缺點(diǎn)逐漸增強(qiáng)。二、一幀數(shù)里面有>=2的渲染,且后面渲染需要前面渲染的結(jié)果. TBR需要所有的圖元執(zhí)行完畢之后再執(zhí)行frag,因?yàn)?gt;=2的渲染,這時(shí)候后面的draw命令需要前面的渲染生成結(jié)果,那么不得不要求GPU把緩存的draw都執(zhí)行完畢,然后放棄當(dāng)前的緩存內(nèi)容.極端的時(shí)候,每次draw都需要前面的渲染結(jié)果,TBR直接退化成IMR