时间:2025-09-20 04:48
人气:
作者:admin
【从UnityURP开始探索游戏渲染】专栏-直达
在物理正确的光照模型中,衰减需要遵循两个基本定律:
$漫反射 = 表面颜色 * 表面反照率 * max(0, N·L)$
URP通过额外计算衰减因子来弥补兰伯特的不足:
hlsl
// URP光源获取函数 (Lighting.hlsl)
Light GetMainLight()
{
Light light;
light.direction = _MainLightPosition.xyz;
// 距离衰减计算
float distance = length(_WorldSpaceCameraPos - positionWS);
light.distanceAttenuation = 1.0 / max(distance * distance, 0.01);
light.color = _MainLightColor.rgb;
return light;
}
// 主光源 漫反射计算
lightingData.mainLightColor += CalculateBlinnPhong(mainLight, inputData, surfaceData);
half3 CalculateBlinnPhong(Light light, InputData inputData, SurfaceData surfaceData)
{
// 这里通过颜色计算了光线衰减
half3 attenuatedLightColor = light.color * (light.distanceAttenuation * light.shadowAttenuation);
half3 lightDiffuseColor = LightingLambert(attenuatedLightColor, light.direction, inputData.normalWS);
half3 lightSpecularColor = half3(0,0,0);
#if defined(_SPECGLOSSMAP) || defined(_SPECULAR_COLOR)
half smoothness = exp2(10 * surfaceData.smoothness + 1);
lightSpecularColor += LightingSpecular(attenuatedLightColor, light.direction, inputData.normalWS, inputData.viewDirectionWS, half4(surfaceData.specular, 1), smoothness);
#endif
#if _ALPHAPREMULTIPLY_ON
return lightDiffuseColor * surfaceData.albedo * surfaceData.alpha + lightSpecularColor;
#else
return lightDiffuseColor * surfaceData.albedo + lightSpecularColor;
#endif
}
物理混合方案:
hlsl
half3 ApplyAttenuation(Light light, float3 positionWS)
{
// 基础平方反比衰减
float dist = distance(light.position, positionWS);
float atten = 1.0 / (dist * dist);
// 范围平滑过渡
float fade = saturate(1.0 - (dist / light.range));
atten *= fade * fade;
// 聚光灯角度衰减
if(light.type == SPOT)
{
float3 toLight = normalize(light.position - positionWS);
float spotFactor = dot(toLight, light.direction);
atten *= smoothstep(light.outerAngle, light.innerAngle, spotFactor);
}
return saturate(atten * light.intensity);
}
移动端优化版:
hlsl
half3 SimpleAttenuation(Light light, float3 positionWS)
{
// 使用预计算的衰减纹理
float dist = distance(light.position, positionWS);
float t = saturate(dist / light.range);
half atten = SAMPLE_TEXTURE2D(_LightAttenuationTex, sampler_LinearClamp, float2(t, 0.5)).r;
return atten * light.intensity;
}
csharp
// 光源组件属性设置
Light light = gameObject.AddComponent<Light>();
light.type = LightType.Point;
light.range = 10.0f;// 控制衰减范围
light.intensity = 1.0f;// 控制最大强度
light.color = Color.white;
性能敏感场景:
hls
// 使用简化距离衰减
float atten = saturate(1.0 - distance/range);
高品质渲染:
hlsl
// 物理精确衰减
float atten = 1.0 / (distance * distance + 1e-5);
风格化渲染:
hlsl
// 自定义衰减曲线
float atten = exp(-_Falloff * distance);
在URP中,虽然经典兰伯特模型本身不具备完整的物理衰减特性,但通过引擎层的光照系统补偿,开发者可以轻松实现物理正确的衰减效果,同时保留艺术控制自由度。这种分层设计正是现代渲染管线的实用智慧体现。
【从UnityURP开始探索游戏渲染】专栏-直达
(欢迎点赞留言探讨,更多人加入进来能更加完善这个探索的过程,????)