Второй проход пользовательского шейдера Unity не выполняется

У меня есть шейдер, который должен делать два прохода, которые один раз отрисовывают задний план. См. код шейдера ниже:

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<g2f> 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<g2f> 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
        }
    }
}

Но проблема, с которой я сталкиваюсь, заключается в том, что второй проход в коде никогда не выполняется. Потому что, когда я устанавливаю цвет для обратного прохода, этот цвет никогда не становится видимым в сетке, к которой применяется шейдер (материал).

Кроме того, если я поменяю местами проходы так, что задний проход будет перед передним, возникнет противоположная проблема.

РЕДАКТИРОВАТЬ
См. здесь изображение передней части сетки с нанесенным материалом и изображение обратной стороны той же сетки с материалом:
Спереди:
FRONT
Назад:
НАЗАД

Это мой первый раз, когда я пытаюсь сделать такой шейдер, поэтому я очень благодарен за любую помощь!


person FutureCake    schedule 06.11.2018    source источник
comment
То есть одна сторона сетки правильно окрашена лицевой стороной, а другая сторона невидима? А если поменять местами порядок проходов, то одна сторона меша по-прежнему окрашена лицевой стороной, а другая сторона все равно невидима?   -  person Ruzihm    schedule 06.11.2018
comment
да, если я правильно понимаю, что вы правильно меняете порядок, убедитесь, что первый проход окрашен, а второй - нет. Таким образом, если _backColor pas выполняется первым, этот цвет становится видимым, а _FrontColor — нет. То же самое происходит, когда вы меняете порядок. В этом случае _FrontColor будет виден, а _BackColor — нет. Надеюсь, это прояснит это!   -  person FutureCake    schedule 06.11.2018
comment
Пожалуйста, отредактируйте свой вопрос и включите изображение визуализированной сетки, если смотреть спереди и сзади, когда шейдер закодирован, как в вопросе.   -  person Ruzihm    schedule 06.11.2018
comment
@Ruzihm Я добавил две фотографии, одну спереди и одну сзади. Извините за поздний ответ, но что-то произошло между ними.   -  person FutureCake    schedule 10.11.2018


Ответы (1)


введите здесь описание изображениявведите здесь описание изображенияуберите эту скобку

Shader "Custom/Geometry/Wireframe"

{<<<<<<<<<<<<
    Properties
    {

это заставило меня работать

к сожалению, для шейдеров нет автоматического завершения, поэтому такие ошибки легко пропустить, но ваш код дал мне следующие ошибки в редакторе:

Parse error: syntax error unexpected '{' 3 (дополнительная скобка в третьей строке)

shader is not supported on this gpu (вызвано синтаксической ошибкой)

удаление этого кронштейна устраняет проблему!

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<g2f> 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<g2f> 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
                }
            }
    }
person Technivorous    schedule 10.11.2018
comment
между прочим, это хороший простой каркасный шейдер. хорошая работа. - person Technivorous; 10.11.2018
comment
Я обновил код, потому что, возможно, я ошибся при копировании. Но кронштейн для меня не проблема. Если я уберу его, шейдер сломается. До сих пор не вижу цвет спины, к сожалению. Спасибо, но я должен сказать, что изменил шейдер из примера в Интернете: P - person FutureCake; 11.11.2018
comment
отлично работает для меня, братан. Я поместил сюда весь шейдер и несколько фотографий, чтобы показать вам, что он выглядит красиво - person Technivorous; 11.11.2018
comment
приятно видеть, что это работает! может быть, это связано с рендерпиплином, что вы используете базовый 3D-шаблон или LWRP или HDRP? сейчас я работаю в LWRP - person FutureCake; 11.11.2018
comment
О, угу. Lwrp допускает только один проход. Вот почему у вас есть проблемы вы. Он выполнит только первый проход и не выдаст никаких ошибок. Похоже, вы только что ответили на свой вопрос. ???? - person Technivorous; 11.11.2018
comment
Просто напомню, что HDRP, похоже, также работает только с одним проходом. - person Axle; 12.11.2018