跳到主要内容

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

效果

X-Ray 轮廓渲染效果

这篇笔记演示了一个简单的 X-Ray / 轮廓渲染效果:只根据当前物体的法线方向和相机视线方向,就能把靠近轮廓的区域高亮出来。


原理

核心思路:

  • 顶点着色器里,把相机位置转换到与模型同一空间,得到视线方向 viewDir
  • 片元着色器里,使用顶点的法线方向 normalviewDir 做点乘。
  • 法线越朝向相机,点乘越接近 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