US3S5L4——点光源衰减计算
US3S5L4——点光源衰减计算
知识回顾
在Shader中进行光照衰减处理时,我们是通过从纹理中取出衰减数据
不使用灯光遮罩时,从_LightTexture0
纹理中获取,使用时,从_LightTextureB0
纹理中获取
在纹理采样之前,我们需要将顶点坐标从世界空间中转换到光源空间中,变换矩阵为:
- 老版本:
_LightMatrix0
- 新版本:
unity_WorldToLight
点光源衰减计算
注意:一般点光源我们不会为其添加 cookie 光照遮罩,一般想要使用光照遮罩都会在聚光灯中使用,因此我们不用考虑 cookie 纹理的问题
-
将顶点从世界空间转换到光源空间
1
float3 lightCoord = mul(unity_WorldToLight, float4(worldPos, 1)).xyz;
lightCoord
是光源坐标系下顶点根据光源的范围range
规范化后的坐标,相当于是一个模长为 0~1 之间的向量
也就是说,无论点光源的范围多大,在光源坐标系下规范化后,范围都是 -1~1 ,而光源坐标系内的顶点坐标就在其中,因此模长就在 0~1 之间
-
利用该光源空间下的坐标来计算离光源的距离,并利用距离参数,从光源纹理中采样
1
fixed atten = tex2D(_LightTexture0, dot(lightCoord, lightCoord).xx).UNITY_ATTEN_CHANNEL;
这里的
UNITY_ATTEN_CHANNEL
是一个宏,由于不同平台上,纹理的光源衰减值分量不一定是r
分量,也有可能是g
,b
,a
使用这个宏可以让 Unity 在不同平台上做对应的替换,替换为正确的分量,避免出现错误在
dot(LightCoord, LightCoord).xx
中:-
dot(LightCoord, LightCoord)
是为了通过点乘得到结果 ,也就是离光源的平方距离 -
xx
是一种特殊写法,目的是构建一个float2
代表 uv 坐标这里的 uv 坐标 相当于是
用 做 uv 坐标,而不是
-
为了避免开平方带来性能消耗
-
采用这种平方衰减更符合现实世界中光照的特性
因为人眼对亮部不敏感,而对暗部敏感,这样我们就可以将 衰减值的精度 集中在比较远的地方
是 0.5 时, 是 0.25,这样 LUT 查找表中大部分值都会留给比较远的部分,或者说,将暗部的范围拉长
-