Spot light shadows in custom vert/frag shader on mobile

I’ve spent the last few days trying just about everything; all google results, looking through Unity 5 shader source, looking at compiled shader source and tweaking every possible combination of glimmers of info I’ve gained from the above.

Literally the only way I’ve got spotlight shadows working in a custom shader on mobile (outside of the standard shader - which has truly abysmal performance on iPad 3) is with a surface shader and the fullforwardshadows pragma. Needless to say, since I’m working with custom vert/frag shaders this doesn’t help in anyway (other than rubbing salt in the wound since it clearly is possible somehow).

Here are some of the things I’ve tried:

  • Checked shadows are enabled
  • Checked all materials involved have cast/receive shadows enabled as appropriate
  • Use fallback diffuse/vertexlit to inherit the caster/collector passes (based on using those shaders in the materials themselves, I’m assuming this does nothing on mobile anyway)
  • Implemented my own caster/collector passes in the shader
  • Use the various shadow/lighting macros in autolight.cginc et el
  • Pulled shadow related code from the standard shader into my custom shader

In the time I’ve spent on this I could have written my own shadow mapper from scratch and I’m almost at the point of saying ‘sod it’ and doing just that - but when Unity is clearly doing this behind the scenes, that seems silly.

What is the secret here? :slight_smile:

As mikkel.gjoel mentioned in the thread How do I sample a shadowmap in a custom shader? - Questions & Answers - Unity Discussions, just add this to your forwardadd pass of the shader:

#pragma multi_compile_fwdadd_fullshadows

then the LIGHTING_COORDS, TRANSFER_VERTEX_TO_FRAGMENT and LIGHT_ATTENUATION will do their job in the pass with point/spot lights (if there are proper caster/collector passes presented in the shader or a proper fallback is there)

If it works with surface shaders then you can click on the “Show generated code” button and see what exactly the surface shader does. You can copy/paste relevant parts to your shader or take the generated code and remove the parts that you don’t care about.
For example, I took a working surface shader and added geometry shader support to it with this method.

Thanks, I revisited this (I ended up just using a surface shader to get shadows) and thanks to this #pragma my custom vert/frag version now renders shadows correctly!

Thanks, this is def. a good way of seeing what’s going on under the hood. My only issue with it is that it’s obviously showing the final compiled output - for completeness I’d rather use Unity’s various macros etc. which will be expanded to their code in the compiled output.