Ошибка компиляции вершинного шейдера от DX9 до DX11 (Unity 5.6-2017.4)


У меня есть постэффект Unity image с использованием пользовательского шейдера, который выдает ошибку при переходе с Unity 5.6 на Unity 2017.4

Утверждение не удалось: не удалось создать объявление вершины DX11; что-то не так с входными данными вершинного шейдера? (hr=80070057)

Похоже, что это ошибка в этом сценарии.

Shader "SG/Stretch Shadows" {
Properties {
    _MainTex ("Light texture", 2D) = "white" {}
}
SubShader {
    LOD 100
    Blend One Zero
    Cull Off
    ZWrite Off
    Lighting Off

    Pass {    // 0 Blacken source
        CGPROGRAM
            #pragma target 3.0

            #include "UnityCG.cginc"
            #pragma vertex processVerts
            #pragma fragment drawFrag

            #pragma glsl_no_auto_normalization

            struct vertdata {
                float2 uv : TEXCOORD0;
                float2 uvScaled : TEXCOORD1;
                float4 vertex : POSITION;
            };

            struct frag_v2f {
                float4 vertex : SV_POSITION;
                half2 uv : TEXCOORD0;
            };

            uniform sampler2D _MainTex;

            frag_v2f processVerts (vertdata v){
                frag_v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                 o.uv = v.uv;
                return o;
            }

            half4 drawFrag (frag_v2f i) : SV_Target {
                fixed4 shadow = tex2D(_MainTex, i.uv);
                half intensity = max(shadow.r, max(shadow.g, shadow.b));
                intensity = step(intensity,0.1);
                return 1-intensity;
            }

        ENDCG
    }

    Pass {    // 1 Stretch
        CGPROGRAM
            #pragma target 3.0

            #include "UnityCG.cginc"
            #pragma vertex processVerts
            #pragma fragment drawFrag

            #pragma glsl_no_auto_normalization

            struct vertdata {
                float2 uv : TEXCOORD0;
                float2 uvScaled : TEXCOORD1;
                float4 vertex : SV_POSITION;
            };

            struct frag_v2f {
                float4 vertex : SV_POSITION;
                half2 basePos : TEXCOORD0;
                half2 zoomPos : TEXCOORD1;
            };

            uniform sampler2D _ObstacleTex;
            uniform sampler2D _MainTex;
            half4 _SunPos;
            #ifdef UNITY_HALF_TEXEL_OFFSET
            #endif

            frag_v2f processVerts (vertdata v){
                frag_v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                 o.basePos = v.uv;
                o.zoomPos = v.uv * _SunPos.zw + (_SunPos.xy -_SunPos.zw*0.5);
                return o;
            }

            half4 drawFrag (frag_v2f i) : SV_Target {
                half2 basePos = i.basePos;
                half2 zoomPos = i.zoomPos;
                half4 tex = tex2D(_MainTex, i.basePos);

                half sub = 1.0/60;
                half len = length((basePos - zoomPos));

                half4 col = tex*tex.a;
                col = half4(0,0,0,0);
                half pos = 1;
                half power = 0.5;

                for(int i = 0; i < 60; i++){
                    pos -= sub;
                    half4 obstacle = tex2D(_MainTex, lerp(zoomPos, basePos, pos));
                    obstacle *= pow(pos, power);
                    col = max(col, obstacle);
                }

                return 1-col;//half4(half3((basePos - zoomPos).x*20), 1);//tex2D(_ObstacleTex, basePos);
            }

        ENDCG
    }

    Pass {    // 2 Blacken alpha
        CGPROGRAM
            #pragma target 3.0

            #include "UnityCG.cginc"
            #pragma vertex processVerts
            #pragma fragment drawFrag

            #pragma glsl_no_auto_normalization

            struct vertdata {
                float2 uv : TEXCOORD0;
                float2 uvScaled : TEXCOORD1;
                float4 vertex : SV_POSITION;
            };

            struct frag_v2f {
                float4 vertex : SV_POSITION;
                half2 uv : TEXCOORD0;
            };

            uniform sampler2D _MainTex;

            frag_v2f processVerts (vertdata v){
                frag_v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                 o.uv = v.uv;
                return o;
            }

            half4 drawFrag (frag_v2f i) : SV_Target {
                fixed4 shadow = tex2D(_MainTex, i.uv);
                half4 intensity = half4(0,0.2,0.2,shadow.a);
                intensity = lerp(shadow, intensity, shadow.a);

                return intensity;
            }

        ENDCG
    }

    Pass {    // 3 Draw fully zoomed shadow and half zoomed shadow
        // Each pass duplicates previous pass, doubling drawn shadows
        CGPROGRAM
            #pragma target 3.0

            #include "UnityCG.cginc"
            #pragma vertex processVerts
            #pragma fragment drawFrag

            #pragma glsl_no_auto_normalization

            struct vertdata {
                float2 uv : TEXCOORD0;
                float2 uvScaled : TEXCOORD1;
                float4 vertex : SV_POSITION;
            };

            struct frag_v2f {
                float4 vertex : SV_POSITION;
                half2 basePos : TEXCOORD0;
                half2 zoomPos : TEXCOORD1;
            };

            uniform sampler2D _ObstacleTex;
            uniform sampler2D _MainTex;
            half4 _SunPos;
            half _Offset;                                            // frational lerp value. Decrease by powers of two each pass
            #ifdef UNITY_HALF_TEXEL_OFFSET
            #endif

            frag_v2f processVerts (vertdata v){
                frag_v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                 o.basePos = v.uv;
                o.zoomPos = v.uv * _SunPos.zw + (_SunPos.xy -_SunPos.zw*0.5);
                return o;
            }

            half4 drawFrag (frag_v2f i) : SV_Target {
                half2 basePos = i.basePos;
                half2 zoomPos = i.zoomPos;
                half firstPass = tex2D(_MainTex, basePos).a;
                half secondPass = tex2D(_MainTex, zoomPos).a-0.85;
                half4 output = half4(0,0,0,max(firstPass, secondPass));
                secondPass = tex2D(_MainTex, lerp(zoomPos, basePos, 0.65)).a-0.3;
                output.a = max(output.a, secondPass);
                secondPass = tex2D(_MainTex, lerp(zoomPos, basePos, 0.4)).a-0.45;
                output.a = max(output.a, secondPass);
                secondPass = tex2D(_MainTex, lerp(zoomPos, basePos, 0.25)).a-0.6;
                output.a = max(output.a, secondPass);
                secondPass = tex2D(_MainTex, lerp(zoomPos, basePos, 0.1)).a-0.7;
                output.a = max(output.a, secondPass);

                return output;//half4(half3((basePos - zoomPos).x*20), 1);//tex2D(_ObstacleTex, basePos);
            }

        ENDCG
    }

Pass {    // 4 Single pass. Ping-pong
        // Each pass duplicates previous pass, doubling drawn shadows
        CGPROGRAM
            #pragma target 3.0

            #include "UnityCG.cginc"
            #pragma vertex processVerts
            #pragma fragment drawFrag

            #pragma glsl_no_auto_normalization

            struct vertdata {
                float2 uv : TEXCOORD0;
                float2 uvScaled : TEXCOORD1;
                float4 vertex : SV_POSITION;
            };

            struct frag_v2f {
                float4 vertex : SV_POSITION;
                half2 basePos : TEXCOORD0;
                half2 zoomPos : TEXCOORD1;
            };

            uniform sampler2D _ObstacleTex;
            uniform sampler2D _MainTex;
            half4 _SunPos;
            half _Offset;                                            // frational lerp value. Decrease by powers of two each pass
            #ifdef UNITY_HALF_TEXEL_OFFSET
            #endif

            frag_v2f processVerts (vertdata v){
                frag_v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                 o.basePos = v.uv;
                o.zoomPos = v.uv * _SunPos.zw + (_SunPos.xy -_SunPos.zw*0.5);
                return o;
            }

            half4 drawFrag (frag_v2f i) : SV_Target {
                half firstPass = tex2D(_MainTex, i.basePos).a;
                half secondPass = tex2D(_MainTex, lerp(i.zoomPos, i.basePos, _Offset)).a;
                half4 output = half4(0,0,0,max(firstPass, secondPass));
                return output;
            }

        ENDCG
    }
}

Инструменты сборки не предоставляют никаких подробностей о том, какой сценарий или номер строки является неисправным. Документация по Unity post effects ничего не покрывает о специфике. Google не находит никого с такой же проблемой. Единственное, что я нашел, - кто-то предложил заменить SV_POSITION на POSITION, что я безуспешно пробовал всевозможные комбинации.

Я также создал новый шейдер эффекта изображения в Unity для сравнения, и код выглядит так же.

Какова правильная форма для создания подходящего вершинного шейдера для постэффекта? Или это вообще проблема с моим кодом?

1 2

1 ответ:

Ты уже близко! Семантика SV_POSITION предназначена для позиции вершины, передаваемой шейдеру фрагментов.

Удалите все префиксы SV_ из SV_POSITION в ваших структурах vertdata. Например:
struct vertdata
{
    float2 uv : TEXCOORD0;
    float2 uvScaled : TEXCOORD1;
    float4 vertex : POSITION;    // <- Remove here
};

struct frag_v2f
{
    float4 vertex : SV_POSITION; // <- Keep here
    half2 uv : TEXCOORD0;
};