Filament provides advanced shadow mapping with multiple techniques and extensive customization options. Shadows add depth and realism to 3D scenes by simulating how objects block light.
Shadow Types
Filament supports several shadow mapping techniques, each with different quality and performance characteristics.
PCF (Percentage Closer Filtering)
The default shadow technique providing good quality at reasonable performance.
view -> setShadowType ( ShadowType ::PCF);
Characteristics:
Fast and efficient
Soft shadow edges through filtering
Good for most use cases
Default shadow type
VSM (Variance Shadow Maps)
Pre-filtered shadow maps using variance to determine shadowing.
view -> setShadowType ( ShadowType ::VSM);
// Configure VSM options
VsmShadowOptions vsmOptions;
vsmOptions . anisotropy = 2 ; // 2^2 = 4 anisotropic samples
vsmOptions . mipmapping = true ; // Enable mipmaps
vsmOptions . msaaSamples = 4 ; // MSAA sample count
vsmOptions . highPrecision = false ; // Use 16-bit (32-bit if true)
vsmOptions . lightBleedReduction = 0.15 f ; // Reduce light bleeding
view -> setVsmShadowOptions (vsmOptions);
Characteristics:
Supports pre-filtering and blurring
Can produce soft shadows efficiently
May exhibit light bleeding artifacts
All shadow participants must be both casters and receivers
VSM-specific light options:
ShadowOptions shadowOpts;
shadowOpts . vsm . elvsm = true ; // Enable ELVSM to reduce light leaks
shadowOpts . vsm . blurWidth = 10.0 f ; // Blur width (0-125)
LightManager :: Builder ( LightManager :: Type ::SUN)
. shadowOptions (shadowOpts)
. build ( * engine, sun);
DPCF (Directional PCF)
PCF with contact hardening simulation for more realistic soft shadows.
view -> setShadowType ( ShadowType ::DPCF);
SoftShadowOptions softOptions;
softOptions . penumbraScale = 1.0 f ; // Global penumbra scale
softOptions . penumbraRatioScale = 1.0 f ; // Contact hardening strength
view -> setSoftShadowOptions (softOptions);
Characteristics:
Simulates contact hardening
Shadows softer farther from contact point
Higher quality than basic PCF
Moderate performance cost
PCSS (Percentage Closer Soft Shadows)
Physically-based soft shadows with contact hardening.
view -> setShadowType ( ShadowType ::PCSS);
SoftShadowOptions softOptions;
softOptions . penumbraScale = 1.0 f ;
softOptions . penumbraRatioScale = 1.5 f ; // Artistic control
view -> setSoftShadowOptions (softOptions);
Characteristics:
Most realistic soft shadows
Proper contact hardening
Highest performance cost
Recommended for high-quality rendering
Shadow Configuration
Basic Shadow Setup
Enable shadows on lights and configure shadow options:
ShadowOptions shadowOptions;
shadowOptions . mapSize = 2048 ; // Shadow map resolution
shadowOptions . shadowCascades = 4 ; // Number of cascades
shadowOptions . constantBias = 0.001 f ; // Bias in world units
shadowOptions . normalBias = 1.0 f ; // Normal offset scale
shadowOptions . shadowFar = 100.0 f ; // Shadow distance
shadowOptions . shadowNearHint = 1.0 f ; // Optimize from this distance
shadowOptions . shadowFarHint = 100.0 f ; // Optimize up to this distance
LightManager :: Builder ( LightManager :: Type ::SUN)
. castShadows ( true )
. shadowOptions (shadowOptions)
. build ( * engine, sun);
Cascaded Shadow Maps (CSM)
Directional lights support cascaded shadow maps to improve shadow quality across view distances:
shadowOptions . shadowCascades = 4 ; // 1-4 cascades
// Uniform split scheme
LightManager :: ShadowCascades :: computeUniformSplits (
shadowOptions . cascadeSplitPositions , 4 );
// Logarithmic split scheme
LightManager :: ShadowCascades :: computeLogSplits (
shadowOptions . cascadeSplitPositions , 4 , nearPlane, farPlane);
// Practical split scheme (blend of uniform and log)
LightManager :: ShadowCascades :: computePracticalSplits (
shadowOptions . cascadeSplitPositions , 4 , nearPlane, farPlane, 0.5 f );
Split positions:
For N cascades, need N-1 split positions
Values range from 0.0 (camera near) to 1.0 (camera far)
Default: for 4 cascades
Shadow Map Resolution
Higher resolution improves quality but uses more memory:
shadowOptions . mapSize = 1024 ; // Low quality / mobile
shadowOptions . mapSize = 2048 ; // Medium quality (default)
shadowOptions . mapSize = 4096 ; // High quality / desktop
Shadow map size must be a power of 2 and at least 8 pixels. Each cascade uses the same resolution.
Shadow Bias
Bias parameters prevent shadow acne and peter-panning artifacts:
// Constant bias - move shadow in world units
shadowOptions . constantBias = 0.001 f ; // 1mm (ignored for VSM)
// Normal bias - offset along surface normal
shadowOptions . normalBias = 1.0 f ; // Multiplier (ignored for VSM)
// Depth bias - prevent self-shadowing
shadowOptions . polygonOffsetConstant = 0.5 f ; // Depth units
shadowOptions . polygonOffsetSlope = 2.0 f ; // Slope-scaled units
VSM ignores constantBias, normalBias, and polygon offset parameters. Use VSM blur to reduce artifacts.
LiSPSM Optimization
Light-space Perspective Shadow Mapping improves resolution:
shadowOptions . lispsm = true ; // Enable (default)
shadowOptions . stable = false ; // Optimize for resolution vs stability
LiSPSM characteristics:
Greatly improves effective resolution
Similar quality to cascades without extra cost
Incompatible with large blur (VSM/PCSS)
Disable if blur artifacts occur
Enhance shadows with screen-space ray-marching:
shadowOptions . screenSpaceContactShadows = true ;
shadowOptions . stepCount = 8 ; // Ray-marching steps
shadowOptions . maxShadowDistance = 0.3 f ; // Max distance in world units
Characteristics:
Adds fine detail to shadow edges
Useful for large scenes
Works regardless of shadow casting settings
Moderate performance cost
Shadow Bulb Radius
Control soft shadow appearance:
shadowOptions . shadowBulbRadius = 0.02 f ; // 2cm (default)
Only affects DPCF and PCSS
Simulates light source size
Larger values = softer shadows
Physically represents light bulb radius
Artistic control over shadow direction:
// Rotate shadow direction by 30 degrees around Y-axis
float angle = 30.0 f * M_PI / 180.0 f ;
math ::quatf rotation = math :: quatf :: fromAxisAngle ({ 0 , 1 , 0 }, angle);
shadowOptions . transform = rotation; // Must be unit quaternion
Only applies to directional lights. Use with caution as it may produce unrealistic results.
Renderable Shadow Settings
Control which objects cast and receive shadows:
auto & rcm = engine -> getRenderableManager ();
auto instance = rcm . getInstance (entity);
// Enable shadow casting
rcm . setCastShadows (instance, true );
// Enable shadow receiving
rcm . setReceiveShadows (instance, true );
View-Level Shadow Control
Enable or disable all shadows in a view:
// Disable all shadows
view -> setShadowingEnabled ( false );
// Re-enable shadows
view -> setShadowingEnabled ( true );
Updating Shadow Options
Shadow options can be updated at runtime:
auto & lcm = engine -> getLightManager ();
auto instance = lcm . getInstance (sun);
// Get current options
ShadowOptions opts = lcm . getShadowOptions (instance);
// Modify
opts . mapSize = 4096 ;
opts . shadowCascades = 3 ;
// Update
lcm . setShadowOptions (instance, opts);
Optimize Shadow Map Size
Use smallest acceptable resolution
Mobile: 512-1024
Desktop: 2048-4096
Reduce for distant/less important lights
Cascade Configuration
More cascades = better quality but higher cost
Mobile: 1-2 cascades
Desktop: 2-4 cascades
Use practical split scheme for best quality
Shadow Distance
Set shadowFar to limit shadow rendering distance
Improves quality and performance
Match to visible scene distance
Shadow Hints
shadowNearHint: optimize quality from this distance
shadowFarHint: optimize quality up to this distance
Default: 1m to 100m
Light Configuration
Limit number of shadow-casting lights
Disable shadows for small/distant lights
Use castLight(false) for shadow-only lights
Example: High-Quality Shadows
ShadowOptions options;
options . mapSize = 4096 ;
options . shadowCascades = 4 ;
options . constantBias = 0.0005 f ;
options . normalBias = 1.0 f ;
options . shadowNearHint = 0.5 f ;
options . shadowFarHint = 150.0 f ;
options . lispsm = true ;
options . stable = false ;
options . screenSpaceContactShadows = true ;
options . stepCount = 16 ;
options . shadowBulbRadius = 0.03 f ;
LightManager :: ShadowCascades :: computePracticalSplits (
options . cascadeSplitPositions , 4 , 0.1 f , 100.0 f , 0.5 f );
view -> setShadowType ( ShadowType ::PCSS);
SoftShadowOptions softOpts;
softOpts . penumbraScale = 1.2 f ;
softOpts . penumbraRatioScale = 1.5 f ;
view -> setSoftShadowOptions (softOpts);
LightManager :: Builder ( LightManager :: Type ::SUN)
. castShadows ( true )
. shadowOptions (options)
. build ( * engine, sun);
Next Steps
Lighting Learn about light types and configuration
Post-Processing Add bloom, DOF, and other effects