Just updated my project to Unity 4 and have run into buckets of shader errors. I’m slowly getting through them, but this one is seriously stumping me:
(Obviously an extremely simplified version of the shader just to show the part with the issue.)
struct Input {
float4 color : COLOR; // vertex color
};
struct SurfOutput {
fixed3 VertexColor;
};
void surf (Input IN, inout SurfOutput o) {
o.VertexColor = IN.color.rgb; // The offending line
}
I understand what it’s saying but it doesn’t make any sense at all because the following things I’ve tried do not fix it:
//
o.VertexColor = fixed3(IN.color.rgb); // Still fails
o.VertexColor = fixed3(IN.color.r, IN.color.g, IN.color.b); // Still fails
// Even changing SurfOutput.VertexColor to a float3 doesn't change a thing.
fixed r = IN.color.r;
fixed g = IN.color.g;
fixed b = IN.color.b;
o.VertexColor = fixed3(r, g, b); // Still fails
// The only thing that works:
o.VertexColor = normalize(IN.color.rgb);
There’s no reason I can imagine that I should not be allowed to cast from float3 to fixed3, and certainly if I rebuild the fixed3 using the r, g, and b components individually. I do not like calling normalize on it just to get it to cast.
Is this some bug in Unity rewriting my code behind the scenes?
Edit:
Ironically, THIS works:
//
o.VertexColor = float3(1, 2, 3); // and notice its a float, not even a fixed
So it looks like there’s something wrong with IN.color.rgb… This is bringing back memories of struggling against Unity’s surface shaders in the past on version 3.x. I have a feeling there’s something else underlying this problem and Unity is just not giving the the right error… Possibly too many registers…
Thanks for the help! I just upgraded the project to Unity 4 so I wasn’t quite aware it automatically switched to DX11 mode, but I did see that mentioned that the truncation error is a common issue in DX11, so I should have mentioned it.
UNITY_INITIALIZE_OUTPUT didn’t help, it gave the same errors. I’m actually not worried about the 2nd error (“not completely initialized”) because this error is only a result of the 1st error causing it to not fill the VertexColor field. If I rem out the line with assigning the VertexColor, there are no errors.
Also, converting VertexColor to a float 4 just caused more errors unless I rem out the VertexColor assignment line and then I get zero errors.
EDIT: Here is the updated 1-file shader to test with
Shader "BakedVertexLighting/Bumped Specular Alpha Cutout" {
Properties {
_Color ("Main Color", Color) = (1,1,1,1) // Required for alpha shadows
_SpecColor ("Specular Color", Color) = (0.5, 0.5, 0.5, 1)
_Shininess ("Shininess", Range (0.01, 1)) = 0.078125
_MainTex ("Base (RGB) Trans (A)", 2D) = "white" {}
_BumpMap ("BumpMap (RGB)", 2D) = "bump" {}
_SpecMap ("Specular Map (RGB)", 2D) = "white" {}
_Cutoff ("Alpha cutoff", Range(0,1)) = 0.5
}
SubShader {
Tags {"Queue"="AlphaTest" "IgnoreProjector"="True" "RenderType"="TransparentCutout"}
LOD 400
// DEFERRED SURFACE SHADER
CGPROGRAM
#pragma target 3.0
#pragma surface surf BlinnPhong_AlphaTestGlowFix_BakedVertexLighting nolightmap nodirlightmap noambient alphatest:_Cutoff exclude_path:forward vertex:vert
fixed4 _Color;
sampler2D _MainTex;
sampler2D _BumpMap;
sampler2D _SpecMap;
half _Shininess;
struct SurfaceOutputVtxC {
fixed3 Albedo;
fixed3 Normal;
fixed3 Emission;
half Specular;
fixed Gloss;
fixed Alpha;
fixed3 VertexColor;
};
struct Input {
float2 uv_MainTex;
float2 uv_BumpMap;
float4 color : COLOR; // vertex color
};
inline fixed4 LightingBlinnPhong_AlphaTestGlowFix_BakedVertexLighting (SurfaceOutputVtxC s, fixed3 lightDir, half3 viewDir, fixed atten) {
// Forward lighting model
half3 h = normalize (lightDir + viewDir);
fixed diff = max (0, dot (s.Normal, lightDir));
float nh = max (0, dot (s.Normal, h));
float spec = pow (nh, s.Specular*128.0) * s.Gloss;
fixed4 c;
c.rgb = (s.Albedo * _LightColor0.rgb * diff + _LightColor0.rgb * _SpecColor.rgb * spec * 2.0f) * (atten * 2);
c.a = 0; // No specular glow
return c;
}
inline fixed4 LightingBlinnPhong_AlphaTestGlowFix_BakedVertexLighting_PrePass (SurfaceOutputVtxC s, half4 light) {
// Deferred lighting model
fixed spec = light.a * s.Gloss;
fixed4 c;
light.rgb += s.VertexColor;
c.rgb = s.Albedo * light.rgb + light.rgb * _SpecColor.rgb * spec * 2.0f;
c.a = 0; // No specular glow
return c;
}
void surf (Input IN, inout SurfaceOutputVtxC o) {
fixed4 tex = tex2D(_MainTex, IN.uv_MainTex);
fixed4 spec = tex2D(_SpecMap, IN.uv_MainTex);
o.Albedo = tex.rgb * _Color.rgb;
o.Gloss = spec.r * tex.a; // multiply red channel of specular map by alpha for final gloss
o.Alpha = tex.a;
o.Specular = _Shininess;
o.Normal = UnpackNormal(tex2D(_BumpMap, IN.uv_BumpMap));
o.VertexColor = IN.color.rgb; // Offending line
// Change to:
// o.VertexColor = IN.color.rgb * 1.0f; // Now it works!
}
// Alpha fog vertex function
void vert (inout appdata_full v, out Input o) {
// The fog components of this function were removed for simplicity. However, the vert function
// could not be removed for this example because without it, the error does not happen
o.uv_MainTex = v.texcoord;
o.uv_BumpMap = v.texcoord;
o.color = v.color;
}
ENDCG
// FORWARD SURFACE SHADER
CGPROGRAM
#pragma target 3.0
#pragma surface surf BlinnPhong_AlphaTestGlowFix_BakedVertexLighting nolightmap nodirlightmap noambient fullforwardshadows alphatest:_Cutoff exclude_path:prepass vertex:vert
fixed4 _Color;
sampler2D _MainTex;
sampler2D _BumpMap;
sampler2D _SpecMap;
half _Shininess;
struct SurfaceOutputVtxC {
fixed3 Albedo;
fixed3 Normal;
fixed3 Emission;
half Specular;
fixed Gloss;
fixed Alpha;
fixed3 VertexColor;
};
struct Input {
float2 uv_MainTex; // uv coords 1
float2 uv_BumpMap;
float4 color : COLOR; // vertex color
};
inline fixed4 LightingBlinnPhong_AlphaTestGlowFix_BakedVertexLighting (SurfaceOutputVtxC s, fixed3 lightDir, half3 viewDir, fixed atten) {
// Forward lighting model
half3 h = normalize (lightDir + viewDir);
fixed diff = max (0, dot (s.Normal, lightDir));
float nh = max (0, dot (s.Normal, h));
float spec = pow (nh, s.Specular*128.0) * s.Gloss;
fixed4 c;
c.rgb = (s.Albedo * _LightColor0.rgb * diff + _LightColor0.rgb * _SpecColor.rgb * spec * 2.0f) * (atten * 2);
c.a = 0; // No specular glow
return c;
}
inline fixed4 LightingBlinnPhong_AlphaTestGlowFix_BakedVertexLighting_PrePass (SurfaceOutputVtxC s, half4 light) {
// Deferred lighting model
fixed spec = light.a * s.Gloss;
fixed4 c;
light.rgb += s.VertexColor;
c.rgb = s.Albedo * light.rgb + light.rgb * _SpecColor.rgb * spec * 2.0f;
c.a = 0; // No specular glow
return c;
}
void surf (Input IN, inout SurfaceOutputVtxC o) {
fixed4 tex = tex2D(_MainTex, IN.uv_MainTex);
fixed4 spec = tex2D(_SpecMap, IN.uv_MainTex);
o.Albedo = tex.rgb * _Color.rgb;
o.Gloss = spec.r * tex.a; // multiply red channel of specular map by alpha for final gloss
o.Alpha = tex.a;
o.Specular = _Shininess;
o.Normal = UnpackNormal(tex2D(_BumpMap, IN.uv_BumpMap));
o.Emission = IN.color.rgb * tex.rgb;
}
// Alpha fog vertex function
void vert (inout appdata_full v, out Input o) {
// The fog components of this function were removed for simplicity. However, the vert function
// could not be removed for this example because without it, the error does not happen
o.uv_MainTex = v.texcoord;
o.uv_BumpMap = v.texcoord;
o.color = v.color;
}
ENDCG
}
Fallback "Transparent/Cutout/Bumped Specular"
}
Ahh, thanks for this! My shader was too bulky and would probably scare away some people who would otherwise help, so your version is perfect. I see you also got the error then. Good, then I’m not crazy afterall… well… @_@
I just checked and actually my editor/player is not in DX11 mode.
Actually, unfortunately, my shader doesn’t throw the ‘implicit truncation of vector type’ warning, but just the ‘output parameter ‘o’ not completely initialized’ warnings. They’re still mysterious, but unfortunately I didn’t quite replicate the problem exactly. Might have something to do with the lighting models, but I haven’t been able to find it yet.
Well, that complicates things. This is the first time I’ve seen that warning in regular mode. I don’t understand why it’s compiling for DX11, I thought that only happened in DX11 mode.
I suppose I will need to put #pragma exclude_renderers d3d11 in all of my shaders as I don’t imagine I’ll be using any DX11 shaders for this project. (Excluding d3d11 works to fix this bug also, btw.)
D’oh! No wonder it felt like a deja vu nightmare… I knew I had some issues like this, but this is basically the same dang thing. No, I never reported it because it was just too inconsistent. I’d have dozens of shaders with no problem then ONE would pop in and start doing that. Now it seems like all do.
I’m getting some other equally baffling and hair pulling problems with using tex2D.rgb in some shaders… Different error and not fixable by a * 1.0f hack.
It seems if you remove fullforwardshadows from the #pragma above or add target 3.0 it works. This worked just fine in 3.5.7. Either I’m doing things with just the right combination to break things or…
As a followup to the previous post, I’ve discovered there is a bug with fullforwardshadows on SM2. I’ve reported it. I am also reporting the COLOR bug as well.
SM2 fullforward shadows bug: Fullforwardshadows does not work with SM2.
Problem SM2 shader using full forward shadows always throws errors:
Shader "BUGS/Fullforwardshadows_SM2_Problem" {
Properties {
_MainTex ("Base (RGB) Trans (A)", 2D) = "white" {}
}
SubShader {
LOD 200
// fullforwardshadows = ON
// Errors:
// Program 'frag_surf", error X4539: sampler mismatch: sampler used inconsistently (compiling for d3d11_9x) at line 11
// Program 'frag_surf', implicit truncation of vector type (compiling for d3d11_9x) at line 77
CGPROGRAM
#pragma surface surf Lambert fullforwardshadows
sampler2D _MainTex;
struct Input {
float2 uv_MainTex;
};
void surf (Input IN, inout SurfaceOutput o) {
fixed4 tex = tex2D(_MainTex, IN.uv_MainTex);
o.Albedo = tex.rgb;
}
ENDCG
}
}
Shoot, I seemed to have missed this message yesterday. I noticed that today as I was about to file the bug report that it was not giving me the same errors… I found the reason for that one though:
Even though that’s not the right model for vertex coloring, just by calling s.VertexColor it eliminates the “not completely initialized” error and your shader compiles. It seems that non-standard fields in the struct must be called somewhere in the lighting model or it won’t initialize them properly.
So I will throw together the shader I have into one file and see if I can boil it down to basics while stll getting the error and post back.
Okay, I posted the shader in post #3 above. I stripped the shader down as much as I could but still getting that error. (I took out fog completely, but I kept in the skeleton of the vert program for fog because without it the error changes…)
So here the weird part… If I remove the vertex programs from both the forward and deferred shaders, the “implicit truncation” error is gone, but a “not completely initialized” error comes in and nothing I do in the surf or the lighting model will get rid of it. Additionally, if I switch to SM2.0 instead of 3.0, I get even more “not completely initialized” errors.