Unity高性能的多光源實現
遊戲中往往需要多個光源來提升場景的真實感
- 火把
- 技能
- 室內燈光
- 燈塔
Unity中自帶的點光源存在一些問題
- 最多只能支持4個像素光
- 烘培的物件必須通過addpass才能接收點光源,性能太低,多一個點光,範圍稍大cpu和gpu的開銷就瘋狂上升
- 動態物件走的是頂點光照,不能使用normalmap,效果一般
- unity移動端上一般不使用延遲渲染,forward+什麼的也暫不考慮,所以我們就打算自己實現一套點光源和聚光燈
首先我們要使用新的光源系統,就需要把舊的光源系統屏蔽,把sh部分的代碼都刪了,把addpass的代碼都刪了,前提是必須用vf寫shader,不能用surf
我們需要一個點光源的計算公式,參數如下
- 頂點normal
- 頂點worldPos
- 光源pos
- 光源range
- 光源idensity
- 光源color
聚光燈額外有
- 光源angle
- 光源direction
點光源核心衰減公式
fixed atten = pow(((pow(PointLightRange, 2) - pow(fDistance, 2)) / pow(PointLightRange, 2)), 2) * pow(PointLightIntensity/2,3);
PointLightRange是光源範圍
fDistance是worldPos到光源的距離
pointLightIndensity是光源強度
聚光燈其實只是在點光源的基礎上約束了一下範圍(注意, 這裡僅是模擬, 很難做到完全和原生的一樣, 原生的聚光燈是基於LUT的)
float3 vecLP = normalize(worldPos - PointLightPos);
float dotLP = dot(normalize(SpotLightForward), vecLP);
float radiusOffset = SpotLightAngle * 3.1415926 / 180 - acos(dotLP);
if (radiusOffset < 0)
{
atten = 0 ;
}
else
{
atten *= radiusOffset;
}
然後在shader裡面封裝一個pointlight和spotlight介面,傳入normal和worldpos就可以了,這樣在各個shader中都可以用了,能做到通用, 直接把代碼調用加在平行光的計算shader中就OK了
c#層主要做一個給shader傳參數的管理器就ok了
由於是項目功能, 具體的完整的代碼就不給出了, 效果就是文章開頭的效果
說到底技術上並沒有什麼突破, 只是在移動端的一種提升性能的trick.
推薦閱讀: