Execution failure of second pass in Unity’s custom shader

The issue was resolved by removing a bracket. This solution worked for me. It is unfortunate that there is no auto complete for shaders, making it easy to overlook errors like this. However, your code resulted in the following errors in the editor: an extra bracket on line three and a syntax error. Removing that bracket resolved the problem. Unfortunately, the build tools do not provide any specific information about which script or line number is causing the issue.


Question:

I possess a shader that is designed to perform two passes, rendering the back first and then the front. Please refer to the shader code provided below.

Shader "Custom/Geometry/Wireframe"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
        [PowerSlider(3.0)]
        _WireframeVal ("Wireframe width", Range(0., 0.34)) = 0.05
        _FrontColor ("Front color", color) = (1., 1., 1., 1.)
        _BackColor ("Back color", color) = (1., 1., 1., 1.)
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        Pass
        {
            Cull Back
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #pragma geometry geom
            #include "UnityCG.cginc"
            struct v2g {
                float4 pos : SV_POSITION;
            };
            struct g2f {
                float4 pos : SV_POSITION;
                float3 bary : TEXCOORD0;
            };
            v2g vert(appdata_base v) {
                v2g o;
                o.pos = UnityObjectToClipPos(v.vertex);
                return o;
            }
            [maxvertexcount(3)]
            void geom(triangle v2g IN[3], inout TriangleStream triStream) {
                g2f o;
                o.pos = IN[0].pos;
                o.bary = float3(1., 0., 0.);
                triStream.Append(o);
                o.pos = IN[1].pos;
                o.bary = float3(0., 0., 1.);
                triStream.Append(o);
                o.pos = IN[2].pos;
                o.bary = float3(0., 1., 0.);
                triStream.Append(o);
            }
            float _WireframeVal;
            fixed4 _FrontColor;
            fixed4 frag(g2f i) : SV_Target {
            if(!any(bool3(i.bary.x < _WireframeVal, i.bary.y < _WireframeVal, i.bary.z < _WireframeVal)))
                 discard;
                return _FrontColor;
            }
            ENDCG
        }
        Pass
        {
            Cull Front
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #pragma geometry geom
            #include "UnityCG.cginc"
            struct v2g {
                float4 pos : SV_POSITION;
            };
            struct g2f {
                float4 pos : SV_POSITION;
                float3 bary : TEXCOORD0;
            };
            v2g vert(appdata_base v) {
                v2g o;
                o.pos = UnityObjectToClipPos(v.vertex);
                return o;
            }
            [maxvertexcount(3)]
            void geom(triangle v2g IN[3], inout TriangleStream triStream) {
                g2f o;
                o.pos = IN[0].pos;
                o.bary = float3(1., 0., 0.);
                triStream.Append(o);
                o.pos = IN[1].pos;
                o.bary = float3(0., 0., 1.);
                triStream.Append(o);
                o.pos = IN[2].pos;
                o.bary = float3(0., 1., 0.);
                triStream.Append(o);
            }
            float _WireframeVal;
            fixed4 _BackColor;
            fixed4 frag(g2f i) : SV_Target {
            if(!any(bool3(i.bary.x < _WireframeVal, i.bary.y < _WireframeVal, i.bary.z < _WireframeVal)))
                 discard;
                return _BackColor;
            }
            ENDCG
        }
    }
}

The issue I’m encountering is that the second pass in the code does not execute. This is because the color set for the back pass does not appear on the mesh where the shader (material) is used.

If I reverse the order of the passes, with the back-pass preceding the front-pass, the opposite issue arises.

Below is a photo of the mesh with the material applied, showing the front and back perspectives:
Front:
FRONT
Back:
BACK

As a beginner in shader creation, any assistance or guidance would be greatly appreciated for my first attempt.


Solution:

Please remove the bracket in the images labeled as

and

.

Shader "Custom/Geometry/Wireframe"
{<<<<<<<<<<<<
    Properties
    {

this made it work for me

Regrettably, shaders do not have an auto-complete feature, making it easy to overlook errors like this. However, your code resulted in the following errors in the editor.

There is an additional bracket on line three in

Parse error: syntax error unexpected '{' 3

.

The error in the code (

shader is not supported on this gpu

) is due to a syntax issue.

The problem is resolved by eliminating the bracket.

Shader "Custom/NewSurfaceShader" 
{
        Properties
        {
            _MainTex("Texture", 2D) = "white" {}
            [PowerSlider(3.0)]
            _WireframeVal("Wireframe width", Range(0., 0.34)) = 0.05
            _FrontColor("Front color", color) = (1., 1., 1., 1.)
            _BackColor("Back color", color) = (1., 1., 1., 1.)
        }
            SubShader
            {
                Tags { "RenderType" = "Opaque" }
                Pass
                {
                    Cull Back
                    CGPROGRAM
                    #pragma vertex vert
                    #pragma fragment frag
                    #pragma geometry geom
                    #include "UnityCG.cginc"
                    struct v2g {
                        float4 pos : SV_POSITION;
                    };
                    struct g2f {
                        float4 pos : SV_POSITION;
                        float3 bary : TEXCOORD0;
                    };
                    v2g vert(appdata_base v) {
                        v2g o;
                        o.pos = UnityObjectToClipPos(v.vertex);
                        return o;
                    }
                    [maxvertexcount(3)]
                    void geom(triangle v2g IN[3], inout TriangleStream triStream) {
                        g2f o;
                        o.pos = IN[0].pos;
                        o.bary = float3(1., 0., 0.);
                        triStream.Append(o);
                        o.pos = IN[1].pos;
                        o.bary = float3(0., 0., 1.);
                        triStream.Append(o);
                        o.pos = IN[2].pos;
                        o.bary = float3(0., 1., 0.);
                        triStream.Append(o);
                    }
                    float _WireframeVal;
                    fixed4 _FrontColor;
                    fixed4 frag(g2f i) : SV_Target {
                    if (!any(bool3(i.bary.x < _WireframeVal, i.bary.y < _WireframeVal, i.bary.z < _WireframeVal)))
                         discard;
                        return _FrontColor;
                    }
                    ENDCG
                }
                Pass
                {
                    Cull Front
                    CGPROGRAM
                    #pragma vertex vert
                    #pragma fragment frag
                    #pragma geometry geom
                    #include "UnityCG.cginc"
                    struct v2g {
                        float4 pos : SV_POSITION;
                    };
                    struct g2f {
                        float4 pos : SV_POSITION;
                        float3 bary : TEXCOORD0;
                    };
                    v2g vert(appdata_base v) {
                        v2g o;
                        o.pos = UnityObjectToClipPos(v.vertex);
                        return o;
                    }
                    [maxvertexcount(3)]
                    void geom(triangle v2g IN[3], inout TriangleStream triStream) {
                        g2f o;
                        o.pos = IN[0].pos;
                        o.bary = float3(1., 0., 0.);
                        triStream.Append(o);
                        o.pos = IN[1].pos;
                        o.bary = float3(0., 0., 1.);
                        triStream.Append(o);
                        o.pos = IN[2].pos;
                        o.bary = float3(0., 1., 0.);
                        triStream.Append(o);
                    }
                    float _WireframeVal;
                    fixed4 _BackColor;
                    fixed4 frag(g2f i) : SV_Target {
                    if (!any(bool3(i.bary.x < _WireframeVal, i.bary.y < _WireframeVal, i.bary.z < _WireframeVal)))
                         discard;
                        return _BackColor;
                    }
                    ENDCG
                }
            }
    }

Frequently Asked Questions