I have a surface shader with a custom lighting function that I want to behave differently depending on if the current pass is forward base or forward additive.
I also need the worldPos data
So, I have my input structure:
struct Input {
float2 uv_MainTex;
float3 worldPos;
};
I have my custom output struct and surface shader:
struct SurfaceOutputCustom {
fixed3 Albedo;
fixed3 Normal;
fixed3 Emission;
half Specular;
fixed Gloss;
fixed Alpha;
half3 WorldPos;
};
void surf (Input IN, inout SurfaceOutputCustom o) {
// Albedo comes from a texture tinted by color
fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
o.Albedo = c.rgb;
// Metallic and smoothness come from slider variables
o.Alpha = c.a;
o.Albedo = c.rgb;
o.WorldPos = IN.worldPos;
}
and inside my custom lighting function I have the following to test if the worldPos input data is correct (bear with me, see below the code block):
return float4(s.WorldPos.xyz, 0, 1);
#ifdef UNITY_PASS_FORWARDBASE
return float4(s.WorldPos.xyz, 0, 1);
#endif
#ifdef UNITY_PASS_FORWARDADD
return float4(s.WorldPos.xyz, 0, 1);
#endif
Here’s where it gets weird. If this executes as is, I get the correct shading on the object (world space coordinates rendered as colors twice, once for forwardbase, once for forwardadd). This implies that s.WorldSpace.xyz is correct.
However, If I comment out that first line, the s.WorldSpace.xyz coordinates are incorrect. They appear to be (1, 0, 0). After checking the generated code, it appears the presence of that line determines whether the line:
surfIN.worldPos = worldPos;
shows up in the final generated surface shader. (The frag_surf logic that contains the calls to surf() and my custom lighting method)
Why is that the case? Is something in the code generation logic thinking I don’t need the variable clipping it out? Is there a way to work-around it, fix it?