ShadowCatcherMaterial class Materials

An invisible ground surface that receives shadows and ambient occlusion.

Assign it to a plane under a model and the plane itself never shows; it writes only the darkening that grounds the model, so a product scene composites over a transparent Flutter background (or any backdrop) with a believable contact to the ground. The output is (shadowColor * alpha, alpha) where alpha = saturate(shadowIntensity * (1 - shadow visibility) + aoStrength * (1 - occlusion)) * radial fade.

The shadow term samples the same aggregate the lit path shades with, the directional light's cascades, every shadow-casting spot's atlas tile, and the sun contact term marched by the occlusion chain, so the catcher's shadow always matches what lit geometry receives. The occlusion term samples the screen-space ambient-occlusion chain and therefore needs the scene's ambient occlusion enabled to contribute (the contact term needs DirectionalLight.contactShadows); with both off, only the mapped shadow term draws.

The catcher draws into the linear HDR scene color as ordinary translucent geometry, before the resolve pass applies exposure, tone mapping, and the display transform. That staging is load-bearing: the overlay rides the same exposure and tone curve as the geometry that casts onto it, so the shadow neither over-darkens nor washes out as the scene's exposure moves.

Unlike other translucent materials, the catcher also joins the camera depth prepass, so the screen-space chain evaluates occlusion, contact shadows, and depth effects at the plane's own depth rather than the backdrop behind it. The plane therefore acts like a ground surface for every screen-space effect (a model standing on it gains ambient occlusion from it, and depth of field focuses on it), which is the behavior a real ground plane would have.

mode selects how the atlas shadow term is evaluated. The default ShadowCatcherMode.live samples the atlas per frame and stays correct as lights and casters move. ShadowCatcherMode.baked renders the footprint shadow once into a low-resolution cache (blurred by softness) and samples that instead, cheaper and right for a static product scene, but stale until markBakedShadowsDirty is called after the lights or casters change. Baked mode assumes a ground-plane-like mesh lying in its local XZ plane (the cache is a top-down footprint).

shadowIntensity doubles as the enable switch. At exactly 0 the catcher registers no draws in any pass at all, a true early-out.

Construct only after Scene.initializeStaticResources() has completed (the Scene constructor starts it); the material draws with the engine's bundled catcher shader, which loads there.

Inheritance

Constructors

ShadowCatcherMaterial({Color shadowColor = const Color(0xFF000000), double shadowIntensity = 0.8, double aoStrength = 0.5, double softness = 0.0, double fadeStart = 0.0, double fadeEnd = 0.0, ShadowCatcherMode mode = ShadowCatcherMode.live})
Creates a shadow catcher. All parameters can be reassigned later.

Properties

aoStrength double
How strongly screen-space ambient occlusion darkens the surface, 0 to 1. Contributes only while the scene's ambient occlusion is enabled.
getter/setter pair
depthBias double
World-space offset toward the camera used for coplanar surface details. Positive values keep an overlay in front of its supporting surface without modifying its node transform. Zero and negative values leave the draw position unchanged. A fixed world offset provides fewer depth-buffer units as camera distance grows, so distant coplanar surfaces may need a larger value.
getter/setter pairinherited
depthPrepassParticipates bool
Whether this material's geometry joins the camera depth prepass that feeds the screen-space chain (ambient occlusion, contact shadows, reflections, depth of field).
no setter
doubleSided bool
Whether to render both faces of triangles drawn with this material (glTF's material.doubleSided). When true, bind disables back-face culling so the geometry is visible from both sides; otherwise back faces are culled. Defaults to false. The runtime importer sets it from the glTF material.
getter/setter pairinherited
drawsNothing bool
Whether this material currently draws nothing at all, keeping its render items out of every pass (color, depth prepass, shadows).
no setter
fadeEnd double
Radial distance from the mesh origin, in the mesh's local units, where the overlay reaches zero, so the plane has no hard visible edge.
getter/setter pair
fadeStart double
Radial distance from the mesh origin, in the mesh's local units, where the overlay starts fading out. See fadeEnd.
getter/setter pair
fragmentShader Shader
The fragment shader used when rendering geometry with this material.
no setteroverride
hashCode int
The hash code for this object.
no setterinherited
mode ShadowCatcherMode
How the shadow term is evaluated; see ShadowCatcherMode.
getter/setter pair
name String
The name of this material, used for identification.
getter/setter pairinherited
runtimeType Type
A representation of the runtime type of the object.
no setterinherited
sceneInputs Set<RenderInput>
Per-frame engine inputs this material samples, produced only when a visible material asks for them: RenderInput.depth binds the linear scene depth of the opaque geometry (forcing the depth prepass), and RenderInput.opaqueSceneColor binds the accumulated scene color behind the current draw, and RenderInput.filteredSceneColor adds its roughness-filtered atlas. Together they enable refraction, depth-fade absorption, shoreline foam, and soft-particle style effects on translucent surfaces. The base material requests nothing; a .fmat material declares these with engine_inputs:.
no setterinherited
shadowColor Color
The color the surface darkens toward where it is shadowed or occluded.
getter/setter pair
shadowIntensity double
How strongly aggregate shadow visibility darkens the surface, 0 to 1.
getter/setter pair
softness double
World-space penumbra radius for this catcher's shadow, decoupled from the scene's shadow settings.
getter/setter pair

Methods

bind(RenderPass pass, TransientWriter transientsBuffer, Lighting lighting) → void
Binds this material's render-pass state, uniforms, and textures.
override
bindVertexStage(RenderPass pass, Shader vertexShader, TransientWriter transientsBuffer) → void
Binds this material's vertex-stage uniforms to vertexShader, called by the encoder only when it used a material-supplied vertex shader (see materialVertexShader). The base implementation is a no-op; a material with vertex-stage parameters binds them here.
fragmentShaderForLighting(Lighting lighting) Shader
Selects this material's fragment shader for the frame lighting state.
isOpaque() bool
Whether geometry rendered with this material is fully opaque.
override
markBakedShadowsDirty() → void
Schedules a re-bake of the cached footprint shadow.
materialVertexShader(String variant) Shader?
The vertex shader this material supplies for a geometry's variant ('unskinned' / 'skinned' for the color pass, 'depth' for the position-only depth/shadow pass; see Geometry.materialVertexVariant), or null to use the engine's standard vertex shader for the geometry.
noSuchMethod(Invocation invocation) → dynamic
Invoked when a nonexistent method or property is accessed.
inherited
setFragmentShader(Shader shader) → void
Assigns the fragment shader used when this material is drawn.
inherited
setFragmentShaderName(String name, {String? cubeName, String? noShadowName, String? noShadowCubeName}) → void
Assigns the fragment shader by name from baseShaderLibrary.
inherited
setRadianceCubeFragmentShader(Shader? shader) → void
Assigns the already-loaded variant built with FLUTTER_SCENE_RADIANCE_CUBE, the counterpart of setFragmentShader for a material that samples the environment.
inherited
toString() String
A string representation of this object.
inherited

Operators

operator ==(Object other) bool
The equality operator.
inherited

Static Methods

composeAlpha({required double shadowVisibility, required double occlusion, required double shadowIntensity, required double aoStrength, double radialDistance = 0.0, double fadeStart = 0.0, double fadeEnd = 0.0}) double
The catcher's composed straight alpha, the same math the shader runs.