US3S5L4——点光源衰减计算

知识回顾

在Shader中进行光照衰减处理时,我们是通过从纹理中取出衰减数据
不使用灯光遮罩时,从 _LightTexture0​ 纹理中获取,使用时,从 _LightTextureB0​ 纹理中获取
在纹理采样之前,我们需要将顶点坐标从世界空间中转换到光源空间中,变换矩阵为:

  • 老版本:_LightMatrix0
  • 新版本:unity_WorldToLight

点光源衰减计算

注意:一般点光源我们不会为其添加 cookie 光照遮罩,一般想要使用光照遮罩都会在聚光灯中使用,因此我们不用考虑 cookie 纹理的问题

  1. 将顶点从世界空间转换到光源空间

    1
    float3 lightCoord = mul(unity_WorldToLight, float4(worldPos, 1)).xyz;

    lightCoord​ 是光源坐标系下顶点根据光源的范围 range​ 规范化后的坐标,相当于是一个模长为 0~1 之间的向量
    也就是说,无论点光源的范围多大,在光源坐标系下规范化后,范围都是 -1~1 ,而光源坐标系内的顶点坐标就在其中,因此模长就在 0~1 之间

    image

  2. 利用该光源空间下的坐标来计算离光源的距离,并利用距离参数,从光源纹理中采样

    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)​ 是为了通过点乘得到结果 x2+y2+z2=distance2(离光源距离)x^2 + y^2 + z^2 = distance^2(离光源距离),也就是离光源的平方距离

    • xx​ 是一种特殊写法,目的是构建一个 float2​ 代表 uv 坐标

      这里的 uv 坐标 相当于是 (distance2,distance2)(distance^2, distance^2)

    distance2distance^2 做 uv 坐标,而不是 distancedistance

    1. 为了避免开平方带来性能消耗

    2. 采用这种平方衰减更符合现实世界中光照的特性

      因为人眼对亮部不敏感,而对暗部敏感,这样我们就可以将 衰减值的精度 集中在比较远的地方
      distancedistance 是 0.5 时,distance2distance^2 是 0.25,这样 LUT 查找表中大部分值都会留给比较远的部分,或者说,将暗部的范围拉长