I’m trying to write a custom shader that has shadows. I’ve tried everything and I can’t seem to get it to work.
Here is the code that I have. I just want the simplest possible non-surface shader that accepts shadows. I know I can just use a surface shader but I need to do some more advanced operations after I get shadows working.
The light is in the top right area of the room, even though the light is on the left. The lighting stays the same even if I move the light around. This is probably a separate issue from the shadows though.
Well, by default Unity will give you one shadow in forward rendering mode.
This gets given to the fwd_base pass and is the shadow cast from the most prominent directional light affecting that object.
If you’re not using directional lights, you won’t get shadows. Also the attenuation for a directional light will always be 1 if that light has no shadows (directional lights never attenuate).
Try setting the FallBack to “VertexLit” (technically Diffuse should do that anyway, but it’s worth cutting out the middle man). VertexLit contains passes that give the shadow caster/reciever information to the lighting system, so it has to be in the fallback for shadows to be calculated at all. You could make your own fallback with just those in… but vertexlit’s an easy and known-to-work alternative.
Vertex lit REQUIRES that you have a property of _Color in your properties (just copy/paste it from the other Unity shaders if you like). Otherwise you don’t get no shadows at all
If you’re using cutout/transparent vertex lit it will also require _MainTex in there so that it can derive the alpha from that with which to cast shadows.
Oh oops. I’m using deferred rendering; I guess I should have mentioned that.
I put in “#pragma multi_compile_fwdadd” because without it, it would comment out my shader and complain about it being in Unity 2.x style and needing to change it to a surface shader. Is there a deferred version of that pragma command that would let me use shadows?
Hmmm… well, maybe I could render my shader with the advanced stuff without shadows, and then render another pass with just shadows, and blend them together?
Do you think that’s a viable option? If so, I’m having trouble combining them: how do I get a surface shader into a Pass? I need my second Pass to blend with my first one, but I can’t seem to get shadows working in anything other than a surface shader.
Dang. Basically, I’m just trying to add shadows to my scene over my own shader.
Here’s what I have now - it’s a shader that lights each tile equally. (By the way, what’s the term for a non-surface shader? Do I just call them fragment shaders? (That’s what this is))
I’d like to apply some simple shadows on top of that. If I replace that shader with just a super-simple surface shader (just setting albedo to 1), I get this:
(note that this doesn’t actually exist in game, I just blended the images together in Photoshop to make this one)
That’s the end result I’m trying to achieve (well, except for the little dark bump edges on the tiles, I just want to blend the shadows. But I guess that’s a different issue). Is there a way to achieve this blending in Unity?
It says to just put the surface shader after the pass - however, they don’t seem to be blending. If I put “Blend One Zero” before the second pass, it just gives me a gray color, whereas I would expect it to be the appearance of the first pass.
I’m still on this issue. I have a fragment shader that I need to get some hard shadows from point lights in. It sounds like a simple task but I’ve spent weeks unsuccessfully trying to get it to work. Is it possible at all to get a fragment shader with shadows? Or at least fake it, through multiple passes and blending?
The trick is to use #pragma multi_compile_fwdadd_fullshadows (thanks aras!). This gives you all combinations of spot/point-keywords with shadows as well as without. The functional code then becomes (tested unity4.0):
Shader "Custom/Test Shadowed" {
Properties {
_Color ("Main Color", Color) = (1,1,1,1) //note: required but not used
}
SubShader {
Tags { "RenderType"="Opaque" "Queue"="Geometry" }
Pass {
Tags { "LightMode" = "ForwardAdd" }
Blend One One
Fog { Color(0,0,0,0) }
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile_fwdadd_fullshadows
#include "UnityCG.cginc"
#include "AutoLight.cginc"
struct v2f {
float4 pos : SV_POSITION;
LIGHTING_COORDS(0,1)
};
v2f vert (appdata_full v) {
v2f o;
o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
TRANSFER_VERTEX_TO_FRAGMENT(o);
return o;
}
float4 frag (v2f i) : COLOR {
return LIGHT_ATTENUATION(i);
}
ENDCG
} //Pass
} //SubShader
FallBack "Diffuse" //note: for passes: ForwardBase, ShadowCaster, ShadowCollector
}
Damn! holy smokes! The above code doesn’t work at all! I just transcribed all my shader into it and guess what- if you comment out the “Fallback diffuse” line, it doesn’t display anything at all. fortunately it is also amusing, as this was unexpected.
Trying to do this in Unity 5 with no luck.
Using forward rendering, 1 directional light casting hard shadows and this test code
I tried the above code directly unmodified but then the object completely vanishes.
I saw on another thread that SHADOW_COORDS and TRANSFER_SHADOW is now the way to go so I knocked up the example below, but no joy.
Yeah that seems to match what I have already. I noticed when I just put this shader into it’s own file it does in fact work as expected so there’s something else going on. The technique appears to be correct.
For anyone else who comes upon this thread at a later date, I figured it out.
@monark almost had it right. That will cause it to receive shadows but not to cast them. To also cast shadows, after the first pass, add the following line:
UsePass “Legacy Shaders/VertexLit/SHADOWCASTER”
That will allow it to both cast and receive shadows.