Skip to content

Post-processing

Materials output linear HDR color into a floating-point scene target, and a chain of passes turns that into the final image. Some of those passes are screen-space lighting (occlusion, reflections, volumetrics), some are camera and film effects (depth of field, bloom, grain), and a final resolve applies exposure, the tone-mapping operator, and the display encoding. Every one of them is off by default, and each is a settings object hanging off the Scene.

scene.ambientOcclusion darkens creases and contact points that the image-based environment would otherwise fill in.

scene.ambientOcclusion
..enabled = true
..method = AmbientOcclusionMethod.groundTruth
..radius = 0.5
..intensity = 1.0;

Two estimators are available. AmbientOcclusionMethod.obscurance (the default) averages angular obscurance over a sampling disk and is the cheaper of the two. AmbientOcclusionMethod.groundTruth integrates horizon visibility over hemisphere slices, which reads as more coherent contact shadowing at similar cost and composes correctly with image-based lighting.

bentNormals steers the diffuse environment lookup toward the unoccluded direction, specularMode extends the occlusion to indirect specular, and halfResolution (on by default) trades resolution for cost.

indirectLight turns the ground-truth occlusion march into a one-bounce color bleed, crediting radiance from the previous frame’s scene color to each newly visible sector, so lit surfaces tint their neighbors.

scene.ambientOcclusion
..enabled = true
..method = AmbientOcclusionMethod.groundTruth
..visibilityBitmask = true
..indirectLight = 1.0;

It requires groundTruth with visibilityBitmask, and while active the sun’s contact shadows are unavailable, since those channels carry radiance instead.

scene.screenSpaceReflections traces the rendered image to add reflections to glossy surfaces, on top of what the environment map already provides.

scene.screenSpaceReflections
..enabled = true
..intensity = 1.0
..maxDistance = 24.0
..resolutionScale = 0.5; // trace at half res

Reflections only contain what is on screen, so surfaces facing away from the camera fall back to the environment. blur widens the trace with roughness, and distanceFadeStart fades the effect out toward the trace limit.

scene.fog blends distant geometry toward a color, either as a distance falloff or as a height-based layer.

scene.fog
..enabled = true
..mode = FogMode.exponential
..color = vm.Vector3(0.6, 0.7, 0.8)
..density = 0.02;

FogMode.linear, exponential, and exponentialSquared pick the falloff curve (start/end drive the linear one). skyColorInfluence tints the fog from the sky instead of a fixed color, height and heightFalloff turn it into a ground layer, and sunInScatter brightens it toward the sun.

scene.godRays adds volumetric shafts through the directional light, ray-marched against the shadow map.

scene.godRays
..enabled = true
..intensity = 1.0
..density = 0.5;

stepCount and maxDistance set the march, and anisotropy controls how strongly the scattering points toward the light.

scene.depthOfField blurs by circle of confusion, with a physical lens model.

scene.depthOfField
..enabled = true
..focusDistance = 10.0 // world units
..fStop = 2.8
..quality = DepthOfFieldQuality.medium;

focalLength and sensorHeight complete the lens (a zero focalLength derives it from the camera’s field of view). bladeCount, bladeRotation, and bladeCurvature shape the bokeh into a polygonal aperture instead of a circle.

scene.postProcess groups the film effects that run over the resolved image.

scene.postProcess.bloom
..enabled = true
..threshold = 1.0
..intensity = 0.15;
scene.postProcess.vignette
..enabled = true
..intensity = 0.5
..radius = 0.75;
scene.postProcess.filmGrain..enabled = true;
scene.postProcess.chromaticAberration..enabled = true;

Bloom is what makes HDR emission read as glow, so a material with an emissiveFactor above 1.0 blooms once this is on.

colorGrading carries both the primary controls and a 3D lookup table.

scene.postProcess.colorGrading
..enabled = true
..contrast = 1.1
..saturation = 0.9
..temperature = 0.15;
// Or grade through a .cube LUT authored in a color tool.
scene.postProcess.colorGrading
..enabled = true
..lut = await ColorLut.fromCubeAsset('assets/look.cube')
..lutBlend = 0.8;

Exposure and tone mapping are the last stage of the chain and are covered in Lighting and environment, including scene.autoExposure for scenes whose brightness varies.

scene.antiAliasingMode picks between AntiAliasingMode.msaa (4x, highest quality for geometry edges, unsupported on some backends), fxaa (a post pass, supported everywhere), none, and auto, which is the default and takes MSAA where it is available. Read effectiveAntiAliasingMode for what actually runs.

scene.renderScale renders the scene at a fraction of the view’s resolution and upscales, the usual first knob for a GPU-bound scene. RenderView.renderScale overrides it per view.

PostEffect is the post-processing counterpart of ShaderMaterial. Author a fragment shader, compile it through the flutter_gpu_shaders build hook, and add it to the stack.

scene.postProcess.customEffects.add(
PostEffect(
fragmentShader: shader,
insertion: PostInsertion.afterTonemap,
),
);

The engine binds the current color to a sampler2D input_color sampled at the v_uv varying. PostInsertion.beforeTonemap runs on linear HDR (and must output linear HDR premultiplied by alpha, the same contract materials follow), while afterTonemap works on the display-referred image. Declare your own uniform blocks and textures and set them by name with setUniformBlock and setTexture.

AmbientOcclusionSettings, ScreenSpaceReflectionsSettings, Fog, GodRaysSettings, DepthOfField, PostProcessSettings, ColorLut, AntiAliasingMode, and PostEffect.