多个SubShader,只有一个正在渲染

时间:2018-08-09 20:22:20

标签: unity3d hlsl cg

我正在尝试将多个子着色器添加到一个着色器。一个SubShader只是标准的Unity表面着色器,第二个SubShader是一个透明的轮廓,可以从网上找到的地方进行修改。这是到目前为止的代码:

Shader "Custom/MetallicOutline" {

Properties {
    _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


        // Added this : Ben Hoffman
        [Space(10)][Header(xxxxxxxxxxxxxxxx)][Header((Outline))]_OutlineWidth("Width", Float) = 0.5
        _OutlineWidthControl("Width Control", 2D) = "white" {}

        [Space(8)][Toggle(ENABLE_OPO)] _EOPO("Enable Outline Offset", Float) = 0
        _OutlineOffset("Outline Offset", Vector) = (0,0,0)

        [Space(8)]_OutlineColor("Color", Color) = (0,0,0,1)

        [Space(8)]_OutlineNoiseIntensity("Noise Intensity", Range(0, 1)) = 0
        [MaterialToggle] _DynamicNoiseOutline("Dynamic Noise Outline", Float) = 0

        _OutlineOpacity("Outline Opacity", Range(0, 1)) = 1
}


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

    CGPROGRAM
    // Physically based Standard lighting model, and enable shadows on all light types
    #pragma surface surf Lambert

    // Use shader model 3.0 target, to get nicer looking lighting
    #pragma target 3.0

    sampler2D _MainTex;

    struct Input {
        float2 uv_MainTex;
    };

    half _Glossiness;
    half _Metallic;
    fixed4 _Color;

    // Add instancing support for this shader. You need to check 'Enable Instancing' on materials that use the shader.
    // See https://docs.unity3d.com/Manual/GPUInstancing.html for more information about instancing.
    // #pragma instancing_options assumeuniformscaling
    UNITY_INSTANCING_BUFFER_START(Props)
        // put more per-instance properties here
    UNITY_INSTANCING_BUFFER_END(Props)

    void surf (Input IN, inout SurfaceOutputStandard o) {
        // Albedo comes from a texture tinted by color
        fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
        o.Albedo = c.rgb;
        // Metallic and smoothness come from slider variables
        o.Metallic = _Metallic;
        o.Smoothness = _Glossiness;
        o.Alpha = c.a;
    }
    ENDCG
}


SubShader {

    Tags {
        "RenderType" = "Opaque"
    }

    Pass {
        Name "Outline"
        Tags {
            "Queue" = "Transparent"
        }

        //ZWrite Off
        Blend SrcAlpha OneMinusSrcAlpha

        Cull Front

        Stencil {
            Ref[_RefVal]
            Comp[_Compa]
            Pass[_Oper]
            Fail[_Oper]
        }

CGPROGRAM
    #pragma vertex vert
    #pragma fragment frag
    #include "UnityCG.cginc"
    #pragma fragmentoption ARB_precision_hint_fastest
    #pragma multi_compile_shadowcaster
    #pragma multi_compile_fog
    #pragma multi_compile_instancing
    #pragma only_renderers d3d9 d3d11 glcore gles3 metal d3d11_9x xboxone ps4 switch
    #pragma target 3.0
    #pragma shader_feature ENABLE_OPO
        uniform sampler2D _Texture; uniform float4 _Texture_ST;
    uniform float4 _OutlineColor;

    uniform fixed _Transparent;

    uniform float _OutlineNoiseIntensity;
    uniform fixed _DynamicNoiseOutline;
    uniform fixed _TexturePatternStyle;
    uniform sampler2D _OutlineWidthControl; uniform float4 _OutlineWidthControl_ST;
    uniform float _OutlineWidth;
    uniform float3 _OutlineOffset;

    // Transparency options
    uniform float _OutlineOpacity;


    struct VertexInput {
        float4 vertex : POSITION;
        float3 normal : NORMAL;
        float2 texcoord0 : TEXCOORD0;
        UNITY_VERTEX_INPUT_INSTANCE_ID
    };
    struct VertexOutput {
        float4 pos : SV_POSITION;
        float2 uv0 : TEXCOORD0;
        float4 projPos : TEXCOORD1;
        UNITY_FOG_COORDS(2)
    };
    VertexOutput vert(VertexInput v) {
        VertexOutput o = (VertexOutput)0;
        o.uv0 = v.texcoord0;
        UNITY_SETUP_INSTANCE_ID(v);
        float3 viDir = normalize(_WorldSpaceCameraPos.xyz - o.pos.xyz);
        float4 viDirVP = mul(UNITY_MATRIX_VP, float4(viDir.xyz, 1));
        float4 node_9780 = _Time;
        float node_5371_ang = node_9780.g;
        float node_5371_spd = 0.002;
        float node_5371_cos = cos(node_5371_spd*node_5371_ang);
        float node_5371_sin = sin(node_5371_spd*node_5371_ang);
        float2 node_5371_piv = float2(0.5,0.5);
        float2 node_5371 = (mul(o.uv0 - node_5371_piv,float2x2(node_5371_cos, -node_5371_sin, node_5371_sin, node_5371_cos)) + node_5371_piv);
        float2 _DynamicNoiseOutline_var = lerp(o.uv0, node_5371, _DynamicNoiseOutline);
        float2 node_7493_skew = _DynamicNoiseOutline_var + 0.2127 + _DynamicNoiseOutline_var.x*0.3713*_DynamicNoiseOutline_var.y;
        float2 node_7493_rnd = 4.789*sin(489.123*(node_7493_skew));
        float node_7493 = frac(node_7493_rnd.x*node_7493_rnd.y*(1 + node_7493_skew.x));
        float4 _OutlineWidthControl_var = tex2Dlod(_OutlineWidthControl,float4(TRANSFORM_TEX(o.uv0, _OutlineWidthControl),0.0,0));
        o.pos = UnityObjectToClipPos(float4(v.vertex.xyz + v.normal*(lerp(1.0,node_7493,_OutlineNoiseIntensity)*(clamp(_OutlineWidth,0.0,1000.0)*0.01)*_OutlineWidthControl_var.rgb),1));

 #ifdef ENABLE_OPO
        o.pos.xyz = o.pos.xyz - _OutlineOffset.xyz*viDirVP.xyz*0.1;
 #endif

        UNITY_TRANSFER_FOG(o,o.pos);
        o.projPos = ComputeScreenPos(o.pos);
        COMPUTE_EYEDEPTH(o.projPos.z);
        return o;
    }

    fixed4 frag(VertexOutput i) : COLOR{

        float2 sceneUVs = (i.projPos.xy / i.projPos.w);
        float2 _TexturePatternStyle_var = lerp(i.uv0, float2((sceneUVs.x * 2 - 1)*(_ScreenParams.r / _ScreenParams.g), sceneUVs.y * 2 - 1).rg, _TexturePatternStyle);
        float4 _Texture_var = tex2D(_Texture,TRANSFORM_TEX(_TexturePatternStyle_var, _Texture));
        clip(lerp(1.0, _Texture_var.a, _Transparent) - 0.0);

        // Set the opacity of the outline
        fixed4 col = fixed4(_OutlineColor.rgb, 0);
        col.a = _OutlineOpacity;

        return col;

    } // End frag

        ENDCG
        }   // End outline pass

    }

    FallBack "Diffuse"
}

我知道大纲的逻辑在一定程度上适用。 SubShader中位于代码之上的任何东西都将被渲染,而另一个则不被渲染。

有人知道为什么会这样吗?

1 个答案:

答案 0 :(得分:1)

我有完全相同的问题。我通过将第二个子着色器中的通道移动到第一个子着色器(位于第一个通道的正下方)并删除我的第二个子着色器来对其进行修复。

我对Unity很陌生,但是我认为这是因为Unity仅加载一个子着色器。可能设计了不同的子着色器,使您可以灵活地处理不同的情况或平台,但一次只能激活一个。尝试将两个通道放置在同一子着色器中,看看是否能解决您的问题。