Почему мой шейдер не отображает подшейдер с цветом? - PullRequest
0 голосов
/ 05 февраля 2019

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

Оба шейдера прекрасно работают независимо, однако, когда я пытаюсь объединить ихцвет от второго шейдера не отображается.В чем может быть проблема?

Вот мой код:

Shader "Custom/TransparentSingleColorShader" {
    Properties{
      _Color("Color", Color) = (1.0, 1.0, 1.0, 1.0)
      [PowerSlider(3.0)]
        _WireframeVal("Wireframe width", Range(0., 0.5)) = 0.05
        _FrontColor("Front color", color) = (1., 1., 1., 1.)
        _BackColor("Back color", color) = (1., 1., 1., 1.)
        [Toggle] _RemoveDiag("Remove diagonals?", Float) = 0.
    }
        SubShader
        {
            Tags { "Queue" = "Geometry" "RenderType" = "Opaque" }

            Pass
            {
                Cull Front
                CGPROGRAM
                #pragma vertex vert
                #pragma fragment frag
                #pragma geometry geom

            // Change "shader_feature" with "pragma_compile" if you want set this keyword from c# code
            #pragma shader_feature __ _REMOVEDIAG_ON

            #include "UnityCG.cginc"

            struct v2g {
                float4 worldPos : SV_POSITION;
            };

            struct g2f {
                float4 pos : SV_POSITION;
                float3 bary : TEXCOORD0;
            };

            v2g vert(appdata_base v) {
                v2g o;
                o.worldPos = mul(unity_ObjectToWorld, v.vertex);
                return o;
            }

            [maxvertexcount(3)]
            void geom(triangle v2g IN[3], inout TriangleStream<g2f> triStream) {
                float3 param = float3(0., 0., 0.);

                #if _REMOVEDIAG_ON
                float EdgeA = length(IN[0].worldPos - IN[1].worldPos);
                float EdgeB = length(IN[1].worldPos - IN[2].worldPos);
                float EdgeC = length(IN[2].worldPos - IN[0].worldPos);

                if (EdgeA > EdgeB && EdgeA > EdgeC)
                    param.y = 1.;
                else if (EdgeB > EdgeC && EdgeB > EdgeA)
                    param.x = 1.;
                else
                    param.z = 1.;
                #endif

                g2f o;
                o.pos = mul(UNITY_MATRIX_VP, IN[0].worldPos);
                o.bary = float3(1., 0., 0.) + param;
                triStream.Append(o);
                o.pos = mul(UNITY_MATRIX_VP, IN[1].worldPos);
                o.bary = float3(0., 0., 1.) + param;
                triStream.Append(o);
                o.pos = mul(UNITY_MATRIX_VP, IN[2].worldPos);
                o.bary = float3(0., 1., 0.) + param;
                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
        }

        Pass
        {
            Cull Back
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #pragma geometry geom

                // Change "shader_feature" with "pragma_compile" if you want set this keyword from c# code
                #pragma shader_feature __ _REMOVEDIAG_ON

                #include "UnityCG.cginc"

                struct v2g {
                    float4 worldPos : SV_POSITION;
                };

                struct g2f {
                    float4 pos : SV_POSITION;
                    float3 bary : TEXCOORD0;
                };

                v2g vert(appdata_base v) {
                    v2g o;
                    o.worldPos = mul(unity_ObjectToWorld, v.vertex);
                    return o;
                }

                [maxvertexcount(3)]
                void geom(triangle v2g IN[3], inout TriangleStream<g2f> triStream) {
                    float3 param = float3(0., 0., 0.);

                    #if _REMOVEDIAG_ON
                    float EdgeA = length(IN[0].worldPos - IN[1].worldPos);
                    float EdgeB = length(IN[1].worldPos - IN[2].worldPos);
                    float EdgeC = length(IN[2].worldPos - IN[0].worldPos);

                    if (EdgeA > EdgeB && EdgeA > EdgeC)
                        param.y = 1.;
                    else if (EdgeB > EdgeC && EdgeB > EdgeA)
                        param.x = 1.;
                    else
                        param.z = 1.;
                    #endif

                    g2f o;
                    o.pos = mul(UNITY_MATRIX_VP, IN[0].worldPos);
                    o.bary = float3(1., 0., 0.) + param;
                    triStream.Append(o);
                    o.pos = mul(UNITY_MATRIX_VP, IN[1].worldPos);
                    o.bary = float3(0., 0., 1.) + param;
                    triStream.Append(o);
                    o.pos = mul(UNITY_MATRIX_VP, IN[2].worldPos);
                    o.bary = float3(0., 1., 0.) + param;
                    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
            }
        }
        SubShader{
          Tags { "RenderType" = "Transparent" "Queue" = "Transparent" }
          Blend SrcAlpha OneMinusSrcAlpha
          Cull Front
          LOD 200

          CGPROGRAM
          #pragma surface surf Lambert

          fixed4 _Color;

    // Note: pointless texture coordinate. I couldn't get Unity (or Cg)
    //       to accept an empty Input structure or omit the inputs.
    struct Input {
      float2 uv_MainTex;
    };

    void surf(Input IN, inout SurfaceOutput o) {
      o.Albedo = _Color.rgb;
      o.Emission = _Color.rgb; // * _Color.a;
      o.Alpha = _Color.a;
    }
    ENDCG
    }
        FallBack "Diffuse"
}

Это фотография: одна справа (как я хочу, чтобы она выглядела, но без диагонали) наосталось (как я хочу, но цвет отсутствует)

Current results

1 Ответ

0 голосов
/ 06 февраля 2019

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

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

...