边缘光 (Rim Light)
增强物体轮廓的光照效果
📚 原理
边缘光本质上是菲涅尔效应的应用,但通常会加入光源方向的考量,使效果更自然。
无边缘光
简单边缘光
方向性边缘光
💻 代码实现
简单边缘光(基于菲涅尔)
// Properties
_RimColor("Rim Color", Color) = (1, 1, 1, 1)
_RimPower("Rim Power", Range(0.5, 8)) = 3
half4 frag(Varyings input) : SV_Target
{
float3 N = normalize(input.normalWS);
float3 V = normalize(_WorldSpaceCameraPos - input.positionWS);
// 边缘光 = 1 - N·V
float rim = 1.0 - saturate(dot(N, V));
rim = pow(rim, _RimPower);
half4 baseColor = SAMPLE_TEXTURE2D(_BaseMap, sampler_BaseMap, input.uv);
half3 finalColor = baseColor.rgb + _RimColor.rgb * rim;
return half4(finalColor, baseColor.a);
}
方向性边缘光(考虑光源)
half4 frag(Varyings input) : SV_Target
{
float3 N = normalize(input.normalWS);
float3 V = normalize(_WorldSpaceCameraPos - input.positionWS);
float3 L = normalize(_MainLightPosition.xyz);
// 基础菲涅尔
float rim = 1.0 - saturate(dot(N, V));
rim = pow(rim, _RimPower);
// 只在背光面显示边缘光
float NdotL = dot(N, L);
float rimMask = smoothstep(-0.1, 0.3, -NdotL); // 背光遮罩
rim *= rimMask;
half4 baseColor = SAMPLE_TEXTURE2D(_BaseMap, sampler_BaseMap, input.uv);
half3 finalColor = baseColor.rgb + _RimColor.rgb * rim * _MainLightColor.rgb;
return half4(finalColor, baseColor.a);
}
脉冲边缘光(动画效果)
// 使用时间做脉冲 float pulse = sin(_Time.y * _PulseSpeed) * 0.5 + 0.5; float rim = 1.0 - saturate(dot(N, V)); rim = pow(rim, _RimPower) * pulse; half3 finalColor = baseColor.rgb + _RimColor.rgb * rim;
🎮 应用场景
👤 角色高亮
选中、悬停、被击中时的高亮
🌙 月光轮廓
黑夜场景的物体轮廓
🔮 魔法效果
能力激活、施法状态
🎨 卡通渲染
增强卡通风格的深度感
🆚 边缘光 vs 描边
| 特性 | 边缘光 (Rim Light) | 描边 (Outline) |
|---|---|---|
| 实现方式 | 片段着色器内计算 | 额外 Pass 或后处理 |
| 性能 | ✅ 轻量 | 需要额外渲染 |
| 效果 | 柔和发光 | 锐利线条 |
| 应用 | 光照效果 | 卡通/选中高亮 |