One of our projects currently under development is a 3D puzzle game where player will manipulate a number of cubic blocks. Those blocks can be moved above the board so to look realistic they need to cast shadows onto the board. Despite shadows are used in many 3D games and OpenGL ES does have all necessary things to implement them there is no support for shadows in API itself so the implementation is not straightforward at all. The task requires some smart coding. Let’s see how it can be done.
There are several ways to implement shadows efficiently and in our case we took our specific task into account. The matter is we have a flat board which also serves as scene background and is the main object for shadows to be cast on. Once a block is placed above the board we can project its polygons onto the board plane and fill those with darkened semi-transparent color. A very good description of the algorithm and formulae can be found here as well as sample code.
In the most common case however a scene has many 3D objects and a random camera view that may depend on user actions. That means shadows of every object must be cast onto every object. Projection method does not perform well in this case because it will require N*N projections (each object onto each object). This number will grow very quickly as the number of objects grows. There is another method that will work quite well though and it is based on Stencil buffer usage. It is a trick that will darken a particular area of the scene which if properly used together with Depth buffer will simulate a 3D shadow. See detailed description of the method here.
Additional examples and algorithm explanation is also available here.
In the end the feature seemed so reusable for many projects that we decided to add it to our internal 3D library JellyTouch. We think that such feature makes difference from numerous OpenGL wrappers and will add some good value to it.