It seems the Panda distribution does not contain a standard example program on how to use the volumetric lighting postprocess filter. Considering that this particular filter is much more involved to set up correctly than the other CommonFilters, I thought it would be nice to document this more fully.
Therefore, I have pieced together the following sample program from the information I could find. It differs from the posted code examples I could find:
- The occlusion is rendered in a separate pre-pass, using another camera.
- The occlusion camera is set up to only render objects that have a depth coordinate between the light and the viewer. (This is dynamically updated each frame.) This effectively switches off volumetric lighting for those objects that are behind the light. (If this is not done, those objects cast light rays instead of shadow rays, which looks wrong. It may be a limitation of the algorithm - at least to me the shader implementation looks correct.)
- This version demonstrates how to use volumetric lighting in scenes with cartoon inking, or with any other postprocess filter. Bloom is also enabled on the main render, so that bright pixels will glow when the light is not behind the object.
- The strength of the rays is modulated using the directional cosine between the camera’s axis vector and the position vector of the light in the camera’s coordinate system. This makes the effect fade out as the light approaches the perpendicular, eliminating the artifact mentioned in section 13.6 in the original article (the samples can become very sparse if the caster’s y = 0 and x and/or z tend to infinity in camera coordinates).
- The final additive blending combining the scene and the volumetric lighting is done in a very minimal custom shader.
- This is a minimal standalone program independent of demomaster.
First of all, to get an idea about how the filter is supposed to work, it helped to read the original article where the algorithm is explained (including pictures):
On the practical side, especially helpful were the original threads where aurilliance and rdb discussed this in 2009, and another thread where one of the users asked how to set it up:
Also, while the function CommonFilters.setVolumetricLighting() contains no docstring (as of 1.8.1), the parameters are explained in the manual:
Regarding the interaction with cartoon shading, it was also useful to know that in 1.8.1, the autoshader only writes into the normals aux texture if at least one built-in light is enabled (reportedly, this is a bug in 1.8.1 that is fixed in the current development tree):
The code of the example, and required flare texture (the latter from ninth’s lens flare example), are attached as a zip file.
When 1.9.0 comes out, I can update this example if needed - I think I read somewhere on the forums that rdb mentioned that rendering to a buffer will become easier in the new version.
Note that the screenshots in this post were taken using the new antialiasing cartoon shader from the “cartoon shader improvements” patch; the code of the example can run either with that or with original 1.8.1. Default is original 1.8.1 so that the example works out of the box. Search for “cartoon shader improvements” to see which lines must be changed to enable the antialiased cartoon shading if the patch is installed.
Tut-Volumetric-Lighting.zip (87.8 KB)