This include file contains a small lite-C script for generating PSSM (Parallel Split Shadow Maps) in outdoor levels. In this algorithm, several shadow maps are used for rendering shadows in different resolution, depending on the distance to the camera. The script uses five view stages and two shaders from the code folder, vp_depth.fx and vp_shadow.fx. The shaders are simple enough to understand them with some previous shader knowledge, for instance through the Shader Workshops. If you want to modify the script or the shaders, please edit a copy in your work folder, and not the original files in the include and code folders.
|| PSSM shadow
PSSM shadows have some advantages and some disadvantages in comparison to the standard stencil shadow algorithm:
- PSSM shadows have soft edges.
For stencil shadows, you need postprocessing (stencil_blur function) for soft edges.
- Although the PSSM script is optimized for maximum speed, PSSM shadows have still a large frame rate impact due to their 5 rendering stages.
They render faster than stencil shadows on large levels with many shadow casting objects, but slower on small levels with few shadow casting objects.
- PSSM shadows don't have the restrictions of stencil shadows, such as the closed mesh requirement or shadows on the back side of objects. They also consider texture transparency, which is important f.i. for rendering leafs and vegetation.
- On the other hand, PSSM shadows require careful adjustment of the shadow bias (pssm_fbias, see below) and the camera clip_far value to the level size and type. Wrong values can cause artefacts such as "surface acne" or displaced shadows.
- The light source is the sun, as set up in the level map or in the script (sun_angle).
- Only objects that cast PSSM shadows can receive PSSM shadows. For this reason, the SHADOW flag should be set for level geometry and terrain.
- Dynamic shadows cast by level geometry can look strange in combination with static shadow mapping, especially when the sun moves over the sky and gets different angles than in the map. In such a case it might make sense to disable static sun shadows altogether, or render them for an almost vertical sun.
- Due to aliasing, PSSM shadows tend to flicker on moving objects, such as cars. This can be prevented by setting the CAST flag for disabling shadows on those objects.
- Shader model 3.0 is required for PSSM shadows.
- The basic algorithm of shadow maps is described in the Shader Workshop 7. This lite-C script uses the PSSM algorithm proposed by Zhang, Sun, and Nyman in GPU Gems 3, with some improvements for faster and smaller code.
|Shadow depth bias. Too small values cause "surface acne", too large values cause "peter panning" (displaced shadows). Use the [Tab] console to adjust this variable to the optimal value for your level.
|Split scheme, 0..1. A smaller value favors a linear split scheme, a higher value favors a logarithmic split scheme. You can find details about split schemes in GPU Gems 3, chapter 10. Use the [Tab] console to adjust this variable to the optimal value for your level.
|Shadow map resolution, either 512, 1024, or 2048. Set this before calling pssm_run.
|Shadow darkness factor, 0..1.
Activate or deactivate PSSM shadows.
numsplits - number of shadow maps, 0..4. Every shadow map requires a rendering pass. Good values are 3 for small levels, and 4 for large levels. Use 0 for deactivating PSSM shadows.
- PSSM shadows must be deactivated before changing the video resolution or video mode, or when loading a level or changing the level size. Activate them again
- They should be deactivated when the player enters an indoor area (otherwise, everything indoor would be in shadow).
- Before activating PSSM shadows, set shadow_stencil at 8, and set camera.clip_near as high and camera.clip_far as low as possible. Make sure that level_ent.max_x and level_ent.min_x reflects the final level size.
PSSM shadows also work with GPU bones rendering (such as in the crowd.c sample). For this, please comment in the #define BONES line at the beginning of the vp_depth.fx and vp_shadow.fx shader code. Note that this reduces the frame rate by about 3%..5%, so it's commented out by default.
video_mode = 8;
shadow_stencil = 8; // activate external shadows
shadow_lod = 2; // works also for PSSM
// set up a level
// all objects get the SHADOW flag
for(you = ent_next(NULL); you; you = ent_next(you))
// adjust camera and bias, activate PSSM
camera.clip_far = 3000;
camera.clip_near = 30;
pssm_fbias = 0.0005;
stencil shadows, SHADOW