Shadows are very important aspects in 3D space. Shadows enhance spatial awareness of objects in 3D space and give better user experience for players. However, shadow rendering is GPU intensive process. For low-end mobile devices, it will slow down your application. “Fast Shadow Receiver” will make shadow rendering much faster by minimizing the area where shadows are drawn.
“Fast Shadow Receiver” provides a useful mesh search tree called “Mesh Tree” which is used to search for polygons which are receiving shadows. Mesh Tree is useful not only for shadows but also for various purpose such as light projection, bullet marks, AI, and so on.
- Unity 2017 or higher is required.
- Unity Pro is not required.
- It works with Blob Shadow Projector or shadow-map.
- It can cast shadows on non-flat surface.
- Terrain object is also supported (Only Blob Shadow Projector is available)
- Really fast, even on low-end mobile devices!
- Accompanied with fast (but no falloff) projector shadow shader.
- It can handle multiple projectors or shadow casters.
- Optimized for multi-core processors
- Projector shadows can be correctly mixed with Lightmap shadows
How it works
Usually in a scene that has a large environment object like a terrain, shadow rendering will causes a performance problem. The large environment object will occupy most of pixels on the screen, rendering shadows on it will use a lot of GPU resource.
So, it is better for you to remove shadows from the large object, replace each shadow with a pair of “shadow receiver” and “blob shadow projector”. “Shadow receiver” will generate a minimum mesh to receive a shadow based on associated projector and large environment object (See the image below).
Fast Shadow Receiver is designed to work with Blob Shadow Projector.
Additionally, Fast Shadow Receiver can also work with shadow-map. However, lighting will not be applied, which makes the shadows not realistic. Shadow-map will be rendered by being multiplied or blended with the scene.
Fast Shadow Receiver is an asset for optimizing Projector performance. It is applicable not only to Blob Shadow Projector but also to Light Projector and Bullet Marks.
- Types of Shadow Receiver
- Getting Started
- Easy Setup Wizard for Projector Manager
- Steps to use Shadow Receiver with Projector
- Steps to use Shadow Receiver with Shadow-map
- Steps to use Shadow Receiver with Massive Projectors
- Create a Mesh Tree
- Setup Shadow Receiver
- Setup Projector Manager
- Use Projectors in LWRP projects
- Mixed Lighting Blob Shadow Projector
- MultiplyShadowMapShader for URP
- Projector Shaders
31 thoughts on “Fast Shadow Receiver”
First of all – great tool indeed! Thank you.
Now about a problem:
I am trying to apply a global shadow texture to my scene (houses, rocks etc) to get shadows on vehicles only. Vehicles cast shadows on the ground too. Thus I have vehicle object which casts its own shadows from local shadow caster and can receive shadows from global shadow caster. The problem is, that then I try to use global shadow map shadows under cars become of lowest resolution possible and become almost invisible.
I have no idea what to do….
I have tried same approach with default Unity BLOB projectors – works fine.
Is there a hint how to use receiver and caster on same object with your scripts?
Thank you in advance.
Thank you for the comment.
I am a little bit confused. You have a blob projector and a shadow receiver for each vehicle, and the vehicles also receive a global shadow map, right? It should be okay. There is nothing special you need to do. If the resolution of the shadow map changed, maybe some shadow receivers are receiving the global shadow map. Please check if the shadow receiver object has a check on “receive shadows” (in Mesh Renderer component) or not. And if it does, please remove the check.
hii i love your free asset and it works great
then i buyed your paid asset but as i used i didn’t know how to use it i searched for tutorial but i cant find one , i buyed your paid asset but now i am forced to use your free asset
plzz help me
how can i setup to project multiple shadow from my sun ( directional light )
and i covers all mesh in my scene
Hi, thank you for using our assets!
If your dynamic shadow projectors are working already, you can use Easy Setup Wizard.
Hi, I’m having problem displaying shadow on transparent object. After reading the instruction of Fast Shadow Receiver, I think your asset could display shadow on transparent object, is that correct?
That’s a good question. Several problems can happen when displaying shadow on transparent object.
1. Projector will ignore transparent objects.
2. Transparent objects will overwrite projector shadows.
3. MeshShadowReceiver does not include transparent polygons by default.
When you use Fast Shadow Receiver, 1st problem will not occur. Because shadow receiver objects can receive shadows on behalf of the transparent objects.
To avoid the 2nd problem, those transparent objects should be rendered before the projector shadows. Projector shadow material has 2999 render queue value, so the transparent object should have 2500 – 2998 render queue value.
To fix the 3rd problem, please remove “Transparent” from “Exclude Render Types”, when you build a Mesh Tree. (see Create a Mesh Tree).
This will enable ShadowProjector culling and Fast Shadow Projector will try to disable ShadowProjectors that are either off-screen or aren’t projecting onto receivers.
I use skyboxes a lot and also photos as a backdrop for composite work.
Would “Fast Shadow Receiver” allow for the casting of shadows on a simple Unity plane object set to transparent?
This would allow objects placed on that plane to cast their shadows on the skybox or backdrop photo with the plane object not seen.
Is this possible with your asset?
Yes, it is possible. You don’t need even a plane object. InfinitePlaneShadowReceiver can receive a shadow without any visible objects.
So, just be clear, it will cast a shadow on a skybox?
If it does, I*’ll buy it.
Thanks for your quick reply.
No, it just receives a shadow. Casting a shadow on a skybox doesn’t make sense.You need a shape (like a plane) which receives a shadow. In this case, InfinitePlaneShadowReceiver is the shape that receives a shadow.
It might not make sense to you but some skyboxes ,especially landscape and sea scape ones can be and are used for composition.
Placing an object on the skybox “ground” without the ability to have the object cast it’s shadow leaves the object “floating”.
Ground shadows allow for a more realistic look and “place” the object in a more natural way.
Maybe you should look at this?
One way would be to place a primitive plane in an appropriate place on the background. Make this plane transparent to show the background…and then have shadows fall on the plane.
Can your asset allow shadows to fall on a transparent plane?
The asset I use for this is rather limited….5
If you wish to see and check some of my stuff out and see what I’m getting at..
Yes, you can cast shadows on a transparent plane. InfinitePlaneShadowReceiver can receive only one shadow. You need to create InfinitePlaneShadowReceiver object for each shadow casting object.
For more details, please see this page.
In your case, you don’t have large environment objects. you can ignore step 1, 10, and 11.
If it is inconvenient for you to create lots of InfinitePlaneShadowReceivers, you can use a single InfinitePlaneShadowReceivers to receive all the shadows. If you do so, please set a large bounding box in step 4 so that it can cover all the shadow casting objects. This method is not good for the GPU performance though.
Many kind thanks for your replies and information.
I shall study your wise words and see what happens!!
Hi,How to use Shadowmap in URP projects?
I wrote a shader for URP here: https://nyahoon.com/products/fast-shadow-receiver/multiplyshadowmapshader-for-urp
Please try this.
Hi 🙂 Is it possible to receive shadows with LightProjector and InfinitePlaneShadowReceiver to receive shadows from not main light? I have 2 directional lights, main light is mixed and creating shadows for exterior movable objects, but in the interior part of the scene people have shadows casting by the second light. Bought the Fast Shadow Receiver and tried with LightProjector and InfinitePlaneShadowReceiver, the shadow receiver plane moves with the second light but the shadow comes from main light…. It is possible do that with your Fast Shadow Receiver?
Hi, that’s a good question… MultiplyShadowMap shader has “ForwardBase” LightMode tag which means the shader pass is used for main light.
If you replace this line with
then, the shader pass will be used for additional lights. If you have only two lights that have shadows, changing LightMode tag should work. If you have more, the projector will be rendered more than one time… Unfortunately, neither shader code nor scripts can chose a shadow texture, only Unity Engine can do.
Yes, I have only 2 directional lights. Used ForwardAdd and it works fine for a build-in pipeline.
But it doesn’t work in URP… It is any way to do this in URP?
I currently using dynamic shadow projector with projectors for lwrp/urp and they works good, but I have noticed decrease of fps with many animating characters….
Yes, it is possible to do the similar thing in URP, but we need to modify the shader code a lot. Also, it is a bit difficult and complicated to get the index of the additional light in URP (this is why the MultiplyShadowmapShader supports only main light, but if you have only two lights this won’t be a problem).
If you need, I will write a shader for the additional light shadows in URP. But have you tried Fast Shadow Receiver with Dynamic Shadow Projector? There are possibly two reasons for the fps drop. One is shadow texture rendering. If this is the main cause of the fps drop, you need to downsize the shadow texture, or give up to use Dynamic Shadow Receiver. However, usually the performance issue is caused by the other reason. That is projector rendering. This can be optimized by using Fast Shadow Receiver. So I recommend you to use Fast Shadow Receiver for the dynamic shadow projectors first if you haven’t tried.
I have tried dymamic shadow projector (ShadowTextureRenderer+DrawTargetObject+ProjectorForLWRP) configured shadow tex 32×32 and I have added InfinitePlaneShadowReceiver plane, the same fps drop, maybe I should do it different way? If you will write a shader for the additional light would be great, maybe this solution would be better for fps..
Did you properly set ignore layers so that the interior static objects do not receive shadows? Also you can try ‘Invisible’ material in DynamicShadowProjector/Shaders/Projector (available from version 1.2.0). If you use this material for a projector, you can disable only projector rendering. If fps is improved, that means Fast Shadow Receiver can improve the projector performance.
Yes, set ignore all layers except the ShadowReceiver layer and set only one rendering layer – player, still fps dropping from 140 to 40-50 with 25 characters… maybe that solution with additional directional light will be better…
25 characters are visible at the same time? That might be too many… For another solution, you can disable all the ShadowTextureRenders and enable a few of them in turn per frame.
Anyway, here is the shader for additional light shadow. If you have only 2 directional light, _AdditionalLightIndex should be 0 (default value).
This shader works for you? It doesn’t for me…. tried changing index and add more lights, but it receives no shadows…
I think the GetAdditionalPerObjectLight(0, i.worldPos.xyz) returns the first spot light near the shadow receiver, but the renderer becomes pink then…
Have you ever seen the shadows of the second directional light before using Fast Shadow Receiver? I checked the source code of URP version 12.0.0. It says,
I haven’t, read somewhere about it (post from ’19), but was wondering that they have changed something or Fast Shadows Receiver helps with this…
So, the only way to do this is to use dynamic shadow projector with fast shadow receiver ?
Rendering shadow textures by camera causes fps drop with more than 1-2 characters on the scene…
URP has some extendability. It might be possible to render a shadow texture for the secondary directional light and use it from LightProjector (you need another new shader, of course). But it will require lots of effort. I don’t know if it is worth for your project…
If you need performance, using blob shadows is a good option, I think.