描边四种做法:倒模 / 后处理 / 边缘检测 / 贴图

Unity 知识 · Shader 区域 · 常见效果 · 第 3 篇 更新于 2026-10-15

卡通描边、选中轮廓、赛璐璐风格——「给物体画一圈线」至少有四种正路,各有明确的适用边界。这篇按「目标 → 原理 → 关键代码 → 坑」过一遍,最后给选型表。

目标

沿物体轮廓画一圈可控宽度的线,摄像机移动时线钉在模型上(区别于菲涅尔 rim,见 /notes/unity/effects-2/)。

做法一:倒模(inverted hull)——最常用

原理:两个 Pass。第一个 Pass 把顶点沿法线外扩、Cull Front 只画背面——你看到的「线」其实是放大了一圈的模型内壁;第二个 Pass 正常画本体盖住中间。

Pass  // 描边 Pass
{
    Cull Front
    ZWrite On
    CGPROGRAM
    #pragma vertex vert
    #pragma fragment frag
    #include "UnityCG.cginc"

    float _OutlineWidth;
    fixed4 _OutlineColor;

    struct Attributes { float4 vertex : POSITION; float3 normal : NORMAL; };
    struct V2F { float4 pos : SV_POSITION; };

    V2F vert(Attributes v) {
        V2F o;
        // 观察空间外扩:宽度按「屏幕像素」恒定,不随距离变细
        float3 posVS = mul(UNITY_MATRIX_MV, v.vertex).xyz;
        float3 nVS   = normalize(mul((float3x3)UNITY_MATRIX_IT_MV, v.normal));
        posVS += nVS * _OutlineWidth;
        o.pos = mul(UNITY_MATRIX_P, float4(posVS, 1));
        return o;
    }
    fixed4 frag(V2F i) : SV_Target { return _OutlineColor; }
    ENDCG
}
// 其后接正常本体 Pass

坑:硬边模型(立方体)顶点法线平均后外扩方向错,角上开裂——解法是资产侧拆分顶点法线(每面独立法线)或按平滑组处理;蒙皮模型描边要带蒙皮(用 UNITY_SKINNING 或 URP 的 Skin 节点);宽度按世界空间时远处线会细于一个像素产生闪烁,观察空间写法解决。

做法二:后处理描边(全屏)

原理:把目标物体渲进一张 mask(Replace 材质或 Stencil 标记),全屏后处理对 mask 做邻域检测(采样偏移找边界)画线。

坑/边界:一次全屏 Pass 的固定带宽成本(移动端敏感,见 /notes/unity/performance-1/);描的是「屏幕合成后的轮廓」,两个相邻同类物体只出一圈外轮廓——要每个物体独立描边就得逐物体 mask,成本回升。

做法三:边缘检测(深度/法线)

原理:不针对特定物体——对 _CameraDepthTexture 和 _CameraNormalsTexture 做 Sobel 类梯度检测,深度/法线突变处画线。整个场景所有几何轮廓自动有线(卡通渲染管线常用)。

// 全屏 Pass 核心
float d = LinearEyeDepth(SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, sampler, uv).r);
float dN = LinearEyeDepth(SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, sampler, uv + _Texel).r);
float edge = saturate((dN - d) / (d * _Threshold)); // 相对深度差
col = lerp(col, _LineColor, edge);

坑:共面物体无线(深度无突变);同深度相邻物体只有法线线;宽度靠 texel 偏移,分辨率相关;需要引擎开启 depth texture(URP Renderer 勾选,见 /notes/unity/engineering-1/)。

做法四:贴图/美术描边

原理:线画进贴图(UV 边界留出血、画黑边),或模型侧做「轮廓壳」资产。零 shader 技巧,风格最可控(粗细变化、断点都是手绘的)。

坑:只对有 UV 且规划了边界的资产有效;轮廓随视角不变,转角度可能「线不在轮廓上」。

选型表

做法粒度移动端硬边模型典型场景
倒模每物体可用(×2 几何)需处理法线卡通角色主力
后处理 mask全屏/分组固定全屏成本无关选中高亮、分组描边
深度/法线检测全场景一次全屏 + 两张纹理无关全场景卡通风
贴图每资产最便宜无关风格化硬需求、道具

多 Pass 的 Draw Call 代价按遍数算,见 /notes/unity/performance-1/;Cull Front 的状态语义见 /notes/unity/structure-3/。

自检三问

  • 倒模描边在立方体角上开裂,根因是什么?
  • 深度边缘检测为什么对「贴地贴花」无线?
  • 选中一个敌人描边,哪种做法成本最可控?为什么不是全屏后处理?