Shader-less Shadows

Here is a shadow demo that uses no shaders (except the built in screen blur), renders very fast, and gives soft shadows.

It works like this:

The scene is rendered without any lighting and textures and materials turned off by a camera placed at the lights position and pointed at the center of the screen onto a “Shadow” buffer. The buffer has a black background, and objects are rendered solid white. The ground is not rendered. The buffer is blurred using CommonFilters, then its texture is captured and projected back onto the scene from the cameras position and rotation.

This projected texture is applied using the blend mode, which makes anything white look dark on the ground, and black pixels are see through.

But that will not create shadows. That will just illuminate how far the first pixel is from the light source. You cant blurry without shaders.

But you can do shadows without shaders using stencil shadows, but they are quite slow and require special closed hull models from your art team. And the math to get them to work is insane! Doom3 uses this shadow type.

It’s that blurring step that’s going to kill you. If you’re not using a shader, that means you have to blur the texture on the CPU, which means you have to copy the texture RAM from graphics memory to main memory and back again, and that double-copy is death to your frame rate. Plus the CPU isn’t as good at that kind of processing as the GPU is, so you get a double hit.

It would probably be better to use an on-card approach to soft shadows, rendering multiple different (slightly offset) views from the light onto the same texture, blending them sensibly. But this means multiple rendering passes over the scene, which can again be a killer if your scene is complex.


You can certainly use this technique to create shadows without using a shader, if you’re content with hard-edged (and slightly pixelly) shadows. The code in direct/src/showbase/ demonstrates precisely this.


I am doing the blurring with CommonFilters, which though uses shaders, it does not need any custom code.

How can I set the the shadow camera to render all the models as white?

this wont work with the shader generator.
Good idea though, might use it in the future.

Set an initial state on the shadow camera with a white colour attribute and a high priority value.

How do I set priority?

Its looking really good so far.

See the aforementioned, which as I said, does exactly this.


Okay, I have finished a working demo. Its attached to the first post.

(And the is really old, and some things don’t work in it.)[/img]

That works really good. I’ve got ~30fps on my really, really bad machine, and with a bit of tweaking I got it to run at ~60fps (so at top speed). I’ve set the buffer size 256x256 and setBlurSharpen(0.0). The shadows are more blurry (softer) and it runs faster.

I have no idea why people in this thread were so sceptic. It works perfectly. Besides the usual error messages on the console it looks perfect, just with low FPS (9-10). Playing with the buffer size or blurSharpen doesnt improve things.

Mac OS X.6.6.

The original topic was edited after we had posted our suggestions. Our skepticism was directed at the original suggestion to blur the texture without using shaders. The final implementation does use shaders, which is a fine solution.


Well yeah, very low fps is the issue. Other than that I have no problem with it.

I understand. I thought he didn’t? I mean is the blur thing a shader? Because I don’t see a .sha file in the demo.

It uses common filters, which run on shaders.

On a different note, I actually get amazingly good performance with this code. It tops 700 frames here, and the shadow looks very good. The only problem is that when I uncomment setShaderAuto(), the framerate drops to ~70-80 frames. Can’t say I understand where such difference comes from.

I get really good performance as well.

I think there is a bug in Panda that is killing the frame rate when a projected texture is used along with the shader generator.

There is one bug in this code; if you have an model under the ground it will still show up as a shadow. I suggest using a clip plane on the shadow camera to make everything under the ground invisible. This should not be a common problem though, as I see no reason to place a model under the floor.

A building with multiple floors, a dungeon, a cave, an underground train station, sewers… :wink:

Still, a clip plane or camera masks should solve that, yeah.

Last time I encountered this when I wanted to project water caustics on the ocean floor.
And when I wanted to project flashlight.

Too bad because thats some pretty sweet looking shadows.

One way to work around this bug is to save out the generated shader into a file, and then load it explicitly and apply it to your model instead of enabling the auto-shader. You do have to do this separately for each part of your model that has different states, though.