I have a Unity image post effect using a custom shader that throws an error when migrating from Unity 5.6 to Unity 2017.4
Assertion failed: Failed to create DX11 vertex declaration; something wrong with vertex shader input data? (hr=80070057)
It appears to be a fault in this script.
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
}
}
The build tools don't provide any details as to what script or line number is at fault. Documentation on Unity post effects doesn't cover anything about specifics. Google doesn't find anyone else with the same problem. The only thing I've found is someone suggest SV_POSITION should be replaced with POSITION, which I've tried all sorts of combinations of without success.
I also created a new image effect shader in Unity to compare and the code looks the same.
What's the correct form for creating a suitable vertex shader for a post effect? Or is that even the problem with my code?
You're close! The SV_POSITION
semantic is for the vertex position passed to the fragment shader.
Remove all SV_
prefixes from SV_POSITION
in your vertdata
structs. For example:
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;
};