You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unity中能否将自定义裁剪Shader叠加在Standard Shader之上?

问题解答:将自定义裁剪Shader与Unity标准Shader结合,实现物体水平线裁剪

一、能否不修改标准Shader代码实现结合?

答案是可以,但没法直接“合并”两个Shader的源码——Unity标准Shader是预编译的内置资源,我们没法在不碰它代码的前提下直接插入裁剪逻辑。不过有两种实用的替代方案,完全满足“不修改标准Shader代码”的需求:

方案1:自定义Surface Shader复用标准Shader的光照模型

你可以自己写一个Surface Shader,直接调用Unity标准Shader内置的光照计算函数,同时加入水平线裁剪逻辑。这样既保留了标准Shader的所有材质属性(金属度、光滑度等),又实现了裁剪效果,完全不需要修改标准Shader的代码。

举个HLSL示例:

Shader "Custom/StandardWithHorizontalCrop" {
    Properties {
        // 复用标准Shader的核心属性
        _Color ("Color", Color) = (1,1,1,1)
        _MainTex ("Albedo (RGB)", 2D) = "white" {}
        _Glossiness ("Smoothness", Range(0,1)) = 0.5
        _Metallic ("Metallic", Range(0,1)) = 0.0

        // 自定义裁剪参数
        _LineY ("Line Y Position", Float) = 0.5
        _LineThickness ("Line Thickness", Float) = 0.01
    }

    SubShader {
        Tags { "RenderType"="Opaque" }
        LOD 200

        CGPROGRAM
        // 复用标准光照模型,和原生标准Shader一致
        #pragma surface surf Standard fullforwardshadows
        #pragma target 3.0

        // 声明变量映射属性
        sampler2D _MainTex;
        fixed4 _Color;
        half _Glossiness;
        half _Metallic;
        float _LineY;
        float _LineThickness;

        struct Input {
            float2 uv_MainTex;
            float3 worldPos; // 获取世界空间Y坐标用于计算
        };

        void surf (Input IN, inout SurfaceOutputStandard o) {
            // 先执行标准Shader的材质计算逻辑
            fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
            o.Albedo = c.rgb;
            o.Metallic = _Metallic;
            o.Smoothness = _Glossiness;
            o.Alpha = c.a;

            // 插入水平线裁剪逻辑
            float distanceToLine = abs(IN.worldPos.y - _LineY);
            if (distanceToLine > _LineThickness) {
                discard; // 丢弃超出线条厚度的像素
            }
        }
        ENDCG
    }
    FallBack "Standard" // 回退到标准Shader,保证兼容性
}

这个Shader完美继承了标准Shader的材质系统,只是在Surface函数末尾加入了你的裁剪逻辑,完全符合需求。

方案2:多Pass叠加渲染

如果不想重新编写Surface Shader,还可以给材质添加两个Pass:第一个Pass用标准Shader渲染整个物体,第二个Pass用你的裁剪Shader只渲染水平线部分(关闭深度写入,避免覆盖标准Shader的内容)。这种方式更适合需要给线条叠加特殊颜色的场景,若只想保留线条部分,方案1的效率会更高。

二、Gizmo Shader的适配优化建议

如果你要做一个用于Gizmo的Shader,需要针对Scene视图的特性做一些优化:

  • Scene视图兼容性:添加Tags { "Queue"="Overlay" "RenderType"="Transparent" "IgnoreProjector"="True" },关闭深度写入,避免被场景物体遮挡。
  • 简化计算:Gizmo不需要复杂光照,用Unlit Shader即可,减少性能开销。
  • 空间切换支持:加入开关参数,支持在本地空间/世界空间切换线条的Y坐标计算,适配不同的Gizmo使用场景。

举个简化的Gizmo版本示例:

Shader "Custom/GizmoHorizontalLine" {
    Properties {
        _LineColor ("Line Color", Color) = (1,0,0,1)
        _LineY ("Line Y Position", Float) = 0.0
        _LineThickness ("Line Thickness", Float) = 0.02
        _UseWorldSpace ("Use World Space", Float) = 1.0
    }

    SubShader {
        Tags { "Queue"="Overlay" "RenderType"="Transparent" "IgnoreProjector"="True" }
        LOD 100
        ZWrite Off
        Blend SrcAlpha OneMinusSrcAlpha

        Pass {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"

            struct appdata {
                float4 vertex : POSITION;
            };

            struct v2f {
                float4 pos : SV_POSITION;
                float3 worldPos : TEXCOORD0;
                float3 localPos : TEXCOORD1;
            };

            fixed4 _LineColor;
            float _LineY;
            float _LineThickness;
            float _UseWorldSpace;

            v2f vert (appdata v) {
                v2f o;
                o.pos = UnityObjectToClipPos(v.vertex);
                o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
                o.localPos = v.vertex.xyz;
                return o;
            }

            fixed4 frag (v2f i) : SV_Target {
                float currentY = lerp(i.localPos.y, i.worldPos.y, _UseWorldSpace);
                float distanceToLine = abs(currentY - _LineY);
                if (distanceToLine > _LineThickness) {
                    discard;
                }
                return _LineColor;
            }
            ENDCG
        }
    }
}

这个Shader可以直接挂在物体上,在Scene视图中显示红色水平线,支持切换空间坐标,非常适合调试或场景标注使用。


内容的提问来源于stack exchange,提问作者CarpoSep

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 07:41:01