X-Ray 基于法线的轮廓渲染
效果

这篇笔记演示了一个简单的 X-Ray / 轮廓渲染效果:只根据当前物体的法线方向和相机视线方向,就能把靠近轮廓的区域高亮出来。
原理
核心思路:
- 顶点着色器里,把相机位置转换到与模型同一空间,得到视线方向
viewDir。 - 片元着色器里,使用顶点的法线方向
normal与viewDir做点乘。 - 法线越朝向相机,点乘越接近 1,说明在“物体正面”;
- 法线越背离相机,点乘越接近 -1,说明更靠近“边缘”。
- 用
1 - saturate(dot(viewDir, normal))得到一个 Rim 值,在边缘处更亮,在中心处更暗。 - 再用
_RimColor和_RimPower控制最终颜色和过渡形状,就得到了轮廓高亮。
Shader 关键代码
顶点着色器:计算视线方向与法线
v2f vert (appdata_full v)
{
v2f o;
// 常规的 MVP 变换
o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
// 相机世界坐标转换到对象空间,并归一化,作为视线方向
o.viewDir = normalize(TransformWorldToObject(GetCameraPositionWS()));
// 顶点法线直接传给片元
o.normal = v.normal;
return o;
}
片元着色器:根据 Rim 值输出轮廓颜色
float4 frag (v2f i) : COLOR
{
// 法线与视线夹角:靠近中心时 dot≈1,靠近边缘时 dot≈0
float rim = 1 - saturate(dot(i.viewDir, i.normal));
// Rim 轮廓颜色,_RimPower 控制边缘宽度/过渡
float4 color = _RimColor * pow(rim, _RimPower);
return color;
}
可以在材质中暴露这些参数:
_RimColor:轮廓颜色。_RimPower:控制边缘区域的宽窄、过渡曲线形状。
小结与扩展方向
在这个基础版上,你可以继续扩展:
- 把 Rim 效果和原本的 Albedo / 光照混合,做“半 X-Ray 半正常渲染”的效果;
- 利用深度或遮挡关系,只对被遮挡部分做 X-Ray 轮廓;
- 在 URP/HDRP 里改成基于屏幕空间的 Outline Pass,叠加到后处理栈中。
版权声明:本文最初发布于 CSDN「uniGame」,遵循 CC 4.0 BY-SA 协议,转载请附上原文链接及本声明。
原文链接:https://blog.csdn.net/alla_Candy/article/details/122918655