Unity DrawCall及優(yōu)化
Draw Call就是CPU調(diào)用圖形編程接口,是CPU向GPU發(fā)送的命令 1.CPU和GPU并行工作的原理 CPU和GPU工作有一個(gè)命令緩沖區(qū)(Command Buffer) 命令緩沖區(qū)包含了一個(gè)命令隊(duì)列,由CPU向其中添加命令,而由GPU從中讀取命令。當(dāng)CPU需要渲染一些對(duì)象時(shí),它可以向命令緩沖區(qū)添加命令,而GPU完成了上一次的渲染任務(wù)后,它就可以從命令隊(duì)列里取出一個(gè)命令并執(zhí)行它。 命令緩沖區(qū)中的命令有很多種類,而Draw Call是其中的一種,其它命令還有改變渲染狀態(tài)等命令(改變使用的Shader,使用不同的紋理等)。
2.為什么 Draw Call多了會(huì)影響幀率? 在每次調(diào)用Draw Call之前,CPU需要向GPU發(fā)送很多內(nèi)容,包括數(shù)據(jù),狀態(tài),命令等。CPU完成了這些準(zhǔn)備工作,GPU就可以開(kāi)始本次的渲染。如果Draw Call的數(shù)量太多,CPU就會(huì)把大量時(shí)間花費(fèi)在提交Draw Call命令上,造成CPU的過(guò)載。 3.如何減少DrawCall? DrawCall是CPU調(diào)用底層圖形接口。比如有上千個(gè)物體,每一個(gè)的渲染都需要去調(diào)用一次底層接口,而每一次的調(diào)用CPU都需要做很多工作,那么CPU必然不堪重負(fù)。但是對(duì)于GPU來(lái)說(shuō),圖形處理的工作量是一樣的。所以對(duì)DrawCall的優(yōu)化,主要就是為了盡量解放CPU在調(diào)用圖形接口上的開(kāi)銷。所以針對(duì)drawcall我們主要的思路就是每個(gè)物體盡量減少渲染次數(shù),多個(gè)物體最好一起渲染。所以,按照這個(gè)思路就有了以下幾個(gè)方案:
使用Draw Call Batching,也就是描繪調(diào)用批處理。Unity在運(yùn)行時(shí)可以將一些物體進(jìn)行合并,從而用一個(gè)描繪調(diào)用來(lái)渲染他們。具體下面會(huì)介紹。
通過(guò)把紋理打包成圖集來(lái)盡量減少材質(zhì)的使用。
盡量少的使用反光啦,陰影啦之類的,因?yàn)槟菚?huì)使物體多次渲染。
mesh合并,減少Cpu需要提交的模型信息次數(shù)。
使用Gpu Instance一次繪制多個(gè)相同的物體。
優(yōu)化shader 減少pass通道
注意OverDraw
4.Draw Call Batching
首先我們要先理解為何2個(gè)沒(méi)有使用相同材質(zhì)的物體即使使用批處理,也無(wú)法實(shí)現(xiàn)Draw Call數(shù)量的下降和性能上的提升。
因?yàn)楸弧芭幚怼钡?個(gè)物體的網(wǎng)格模型需要使用相同材質(zhì)的目的,在于其紋理是相同的,這樣才可以實(shí)現(xiàn)同時(shí)渲染的目的。因而保證材質(zhì)相同,是為了保證被渲染的紋理相同。
因此,為了將2個(gè)紋理不同的材質(zhì)合二為一,我們就需要進(jìn)行上面列出的第二步,將紋理打包成圖集。具體到合二為一這種情況,就是將2個(gè)紋理合成一個(gè)紋理。這樣我們就可以只用一個(gè)材質(zhì)來(lái)代替之前的2個(gè)材質(zhì)了。
而Draw Call Batching本身,也還會(huì)細(xì)分為2種。
Static Batching 靜態(tài)批處理
只要物體不移動(dòng),并且擁有相同的材質(zhì),靜態(tài)批處理就允許引擎對(duì)任意大小的幾何物體進(jìn)行批處理操作來(lái)降低描繪調(diào)用。
那要如何使用靜態(tài)批來(lái)減少Draw Call呢?你只需要明確指出哪些物體是靜止的,并且在游戲中永遠(yuǎn)不會(huì)移動(dòng)、旋轉(zhuǎn)和縮放。想完成這一步,你只需要在檢測(cè)器(Inspector)中將Static復(fù)選框打勾即可,如下圖所示:

編輯
Dynamic Bathing 動(dòng)態(tài)批處理

編輯
動(dòng)態(tài)批處理需要在Project Setting → Player → Other Setting 中將Dynamic Bathing 勾選上,Unity會(huì)自動(dòng)將使用相同材質(zhì)的物體合并處理。但動(dòng)態(tài)批處理需要滿足以下條件:
頂點(diǎn)屬性最大限制900的可移動(dòng)物體,
使用lightmap的物體不行進(jìn)行批處理
使用多通道的shader也不會(huì)進(jìn)行批處理
縮放比不同的物體不會(huì)批處理
Enable GPU Instancing
在使用大量重復(fù)的物體時(shí),需要將該物體的材質(zhì)的 Enable GPU Instancing 勾選上,這樣Unity會(huì)將Mesh相同的物體合并處理,常用于樹木,植被,粒子等。使用GPU Instancing 對(duì)shader有要求,需要在shader中添加支持GPU Instancing 批處理的命令 ?#pragma multi_compile_instancing

編輯切換為居中
實(shí)際測(cè)試,如果shader中有多pass也會(huì)影響Enable GPU Instancing的合批操作。
減少實(shí)時(shí)光照和陰影效果
光照產(chǎn)生陰影同樣會(huì)產(chǎn)生大量的DrawCall,類似模型的渲染,在不需要陰影的情況下關(guān)閉燈光的陰影效果,降低陰影質(zhì)量。對(duì)需要陰影和不需要陰影的物體拆分shader,分別使用會(huì)產(chǎn)生陰影和不會(huì)產(chǎn)生的材質(zhì)shader。

編輯

編輯
同樣可以在物體的meshrender 組件中選擇是否產(chǎn)生和接受陰影

編輯
減少Shader的pass通道
一個(gè)pass通道會(huì)多產(chǎn)生一個(gè)繪制信息,并且對(duì)動(dòng)態(tài)合批和gpu instance產(chǎn)生影響,盡可能的在一個(gè)pass通道中處理好模型的表現(xiàn)效果。
注意渲染順序和透明材質(zhì)使用
unity的繪制順序是先繪制不透明物體,再繪制透明物體,如果有透明物體則會(huì)導(dǎo)致一些像素點(diǎn)被重新繪制增加調(diào)用次數(shù)并可能打斷一部分合批操作,如果多個(gè)透明物體重疊則更加復(fù)雜。OverDraw就是上面所表達(dá)的意思。常常是游戲的性能問(wèn)題所在。注意透明材質(zhì)的使用,合理的設(shè)置渲染順序,尤其是特效這部分常常是開(kāi)發(fā)者所忽略的,特效包含大量的半透明效果。
特效方面的優(yōu)化可以看我這篇文章:https://www.bilibili.com/read/cv25215347
UGUI方面的優(yōu)化可以看我這篇文章:https://www.bilibili.com/read/cv23858056