Dynamic shadows
Keywords:
tutorial,
X3D,
world,
rendering,
shadows
Author(s): Tobias Alexander Franke, Johannes Behr, Yvonne Jung
Date: 2007-03-05
Summary: This tutorial shows how to enable dynamic shadows.
Shadow types
The current X3D ISO-spec does not include any kind of shadow for dynamic scenes. There are some proposals for shadow extensions, but most are limited in the types of lights or methods supported. Our method has two major advantages. First of all it works with almost every type of scene and is very intuitive. It works with Directional-, Spot- and PointLights and can work well with application defined shaders. We do not introduce new special shadow nodes but extend the existing light nodes with additional fields. Therefore the light-node regulates illumination and shadows simultaneously, just like in the real world. Second, our parameter and abstraction level allows the support and implementation of different methods, e.g. shadow-map or shadow-volumes, to fulfill different requirements.
For the most basic applications, the shadowIntensity field per light controls the shadow-casts for this light-node. The shadowIntensity (in [0, 1]) defines the intensity of the shadows. If the field value is equal to 0, the shadow is off, otherwise it defines the shadow opacity.
Code: Setting individual shadow intensities.
SpotLight { shadowIntensity 0.3 direction 0 -1 0 location -2 14 -2 }
The shadows are then automatically applied to all corresponding scene objects. The user does not need to specify specific occluders and occludees. But since we are in a virtual world, we can exclude objects from throwing shadows. This is quite useful for performance optimizations and can be achieved via the shadowExcludeObjects field of the Environment node. The Environment node is a Bindable which holds rendering states and settings like global shadow parameters. The most important shadow parameters are "globalShadowIntensity" and "shadowMode". The globalShadowIntensity allows forcing a global shadow-intensity and overwrites the per-light settings (if not 0). Again, the range is [0, 1], with higher values being more intense (i.e. darker). The shadowMode field allows the selection of different shadow calculation methods.
Code: An example environment using the uniformHardShadow method.
Environment { globalShadowIntensity 0.3 shadowMode "uniformHardShadow" excludeTransparentObjects FALSE }
All run-time environments should at least support the following values: "auto", "uniformHardShadow", "perspectiveHardShadow", "fastUniformSoftShadow, and "niceUniformSoftShadow". Whereas "auto" activates the default browser settings, all other modes are implementation dependent. We only assume that the given order reflects the increasing complexity of the method. "uniformHardShadow" should be the fastest and "niceUniformSoftShadow" should offer good quality shadows.
For example in our implementation we map the PCF-methods for "uniformSoftShadow"-modes and the modified PCSS to "perspectiveSoftShadow". Standard shadow maps correspond to the "uniformHardShadow"-mode and LISP shadows are mapped to the "perspectiveHardShadow"-mode. Different shadow modes are not only useful for speed-quality trade-offs but also for simulating different types of light sources: A single light bulb throws hard shadows, whereas an area light source such as a window throws very soft shows. The following shadow modes are available in the current implementation:
- perspectiveHardShadow :
- Light space perspective shadow maps (LISP).
- uniformHardShadow :
- Standard shadow maps.
- fastUniformSoftShadow :
- Dithered softshadows, comparable to the PCF shadows.
- niceUniformSoftShadow :
- Percentage closer filtering (PCF).
- perspectiveSoftShadow :
- Percentage closer soft shadows (PCSS).
- uniformSoftShadow :
- Variance shadow maps.
- none :
- Deactivates shadows completely.
HINT: Instant Player will allow you to apply shadows to a scene at runtime by pressing the key x and cycle through the modes by pressing the t key.
Some other fields are worth taking a closer look at: The field shadowExcludeTransparentObjects is a boolean responsible for - as one can guess by the name - the handling of transparent objects like glass etc. Shadow mapping is particularly tricky to get right when transparency comes into play and impacts on rendering speed. The shadowSmoothness is a mode-dependent scale factor, which determines the tradeoff between speed and quality: 1 equals best and 0 the fastest results for the given mode (by defining a filter kernel sampling range).
There are two more fields which are used for fine grained control of the shadow mapping implementation: The shadowOffset field defines the polygon offset for alleviating artifacts due to depth buffer precision problems. The shadowMapSize field defines, as the name implies, the size of the shadow map - again quite useful for controlling the speed-quality trade-off for shadow-map based implementations.
Files: