Super Soft, Super Easy DropShadows in threejs
I’m currently working with a leading danish furniture manufacturer, to replace their Flash configurator with a WebGL solution.
They have over a thousand product types/variations, so we need to be economic with the models, in both kilobytes, and the time used on each one.
We were asked the question, can we have more realistic 3D? A question you may have to deal with from time to time when working in the Web 3D space. The answer is of course, not simple. Yes, yes you can have close to photorealistic 3D… just as long as your scenes are fixed and we can use many hours to create them. Being an online configurator, where a user can plan an entire room in their browser, pre-rendered lighting is not an option. And the time factor? For every 10 minutes extra work on each model, over 160 hours are added to production.

With no shadow, the bed looks separated from the floor, making the scene unrealistic. (click to open)
Still, eager to please a very longstanding customer (I was the 3D guy on the Flash version, and on the VRML version before that, 2009!), I did try to think about improving the existing models programmatically.
One easy way to improve just about any 3d presentation is to add some shadows. Three has this built-in although there are some limitations regarding the fidelity and size ratio, not to mention performance in complicated scenes. You will find lots of tutorials out there, for example: http://learningthreejs.com/blog/2012/01/20/casting-shadows/
Another approach is pre-rendered shadows. These can be created in most 3D packages using RenderToTexture and Ambient Occlusion.

An Ambient Occlusion map rendered via Raytracing in 3D Studio MAX.
The Ambient Occlusion map is created by bouncing thousands of sample rays of light around the scene from a skylight. The practical upshot of this expensive calculation is a map that is almost invariably a “blurred silhoette” of the original object. So perhaps you can already see where I’m going with this…?
I hope you’d agree, it’s an improvement, but again, there’s a 1000 models to consider. At 10 minutes a model, that’s a months work.
So is there an alternative? Well, yes. When working in Away3D I’d faced the exact same problem and wrote a class to create lush shadows without a performance hit.
http://www.videometry.net/matcap-materials-and-smooth-soft-shadows-for-away3d/
Steps:
- color the object in the required shadow color.
- take a snapshot with an orthographic camera from above the object.
- Use the resulting image to fill a 2D canvas.
- Add as much blur as required to the 2D canvas.
- Use the canvas image as a texture in threejs.
- Use the texture in a material on a plane beneath the target object.
- Result?
The fake shadow looks at least as good as the rendered one and has many advantages.
- No extra hours in 3D studio.
- Change the color and internsity of ALL shadows in the scene at once
- No bitmap download
If you open the example (by clicking on the image above or below), you will see that I have made the extra elements used in HTML visible (just change the visibility of ‘shadowDiv’ to hide, it works just the same).
Download the class, together with example usage on github.
https://github.com/themightyatom/DropShadow3d/tree/master
Obviously this is not a magic bullet that will work in all circumstances, but especially for single objects, it can add a pinch of realism. I hope it can be a start point for someone else.
The class takes just 3 parameters, the object to receive the shadow, and the X and Z dimension of the object. Blur, and color of shadow are written into the class and can be easily edited.
The class itself uses a queue system, for when you might open a scene with many objects. This is due to the slight delay when setting up the shadow, which without some management resulted in the shadows being applied to the wrong objects!
I’d be very happy to hear your experiences and issues, and most of all your improvements 🙂