背景:
解决默认spotLight 的衰减模式下, 在距离灯光特别近的时候,灯光过爆的情况
解决方法:
修改SpotLight的衰减方式
下图是unity给出的几种衰减模式以及图示:
其中InverseSquare是当前2021.2 unity版本中urp(12.1.6)所使用的衰减方案
该衰减方案在图中可以看出 在距离最近的地方, 颜色有点过于爆。
为了方便项目在其他场景的时候, 添加了Legacy和Linear的衰减方案, 以供选择。
核心代码修改:RealtimeLights.hlsl中的DistanceAttenuation方法。
// 在原代码的基础上,添加了attenType , 用来标识当前灯光所使用的衰减方案
// 0 : InverseSquare , 1 : Linear , 2 :Legacy
// 在原代码的基础上,添加了attenType , 用来标识当前灯光所使用的衰减方案
// 0 : InverseSquare , 1 : Linear , 2 :Legacy
float DistanceAttenuation(float distanceSqr, half2 distanceAttenuation, half attenType = 0)
{
// We use a shared distance attenuation for additional directional and puctual lights
// for directional lights attenuation will be 1
float lightAtten = rcp(distanceSqr);
float2 distanceAttenuationFloat = float2(distanceAttenuation);
#if SHADER_HINT_NICE_QUALITY
// Use the smoothing factor also used in the Unity lightmapper.
half factor = half(distanceSqr * distanceAttenuationFloat.x);
half smoothFactor = saturate(half(1.0) - factor * factor);
smoothFactor = smoothFactor * smoothFactor;
#else
// We need to smoothly fade attenuation to light range. We start fading linearly at 80% of light range
// Therefore:
// fadeDistance = (0.8 * 0.8 * lightRangeSq)
// smoothFactor = (lightRangeSqr - distanceSqr) / (lightRangeSqr - fadeDistance)
// We can rewrite that to fit a MAD by doing
// distanceSqr * (1.0 / (fadeDistanceSqr - lightRangeSqr)) + (-lightRangeSqr / (fadeDistanceSqr - lightRangeSqr)
// distanceSqr * distanceAttenuation.y + distanceAttenuation.z
half smoothFactor = half(saturate(distanceSqr * distanceAttenuationFloat.x + distanceAttenuationFloat.y));
#endif
if(attenType == 2)
{
return smoothFactor * smoothFactor;
}
return lerp( lightAtten*smoothFactor, smoothFactor , attenType);
}
attenType 怎么来的?
urp工程中每个light组件下都会有一个UniversalAdditionLight的脚本, 我们可以在这个脚本中添加AttenType并且把数值传递到RealtimeLight中。
数值的传递在脚本ForwardLights中,详细的可以看代码进行扩展。
最终结果:
通过挂接脚本, 来修改当前灯光的AttenType,从而实现spotLight衰减方式的更换