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.
推荐阅读: