Skip to main content

Persistence

Accumulate the current frame into a fading history texture to create luminous motion trails and long-exposure visualizations. persistenceEffect keeps history ownership explicit so applications can control reset behavior and ping-pong resources.

GitHub

At a Glance

PropertyValue
ExportpersistenceEffect
Shader uniform namespacepersistence
BackendsWebGPU and WebGL2
Render passesOne fullscreen color-filter pass per frame
Required bindingApplication-owned persistenceTexture

Usage

import type {Texture} from '@luma.gl/core';
import {ShaderPassRenderer} from '@luma.gl/engine';
import {persistenceEffect} from '@luma.gl/effects';

const accumulationRenderers = [
new ShaderPassRenderer(device, {shaderPasses: [persistenceEffect]}),
new ShaderPassRenderer(device, {shaderPasses: [persistenceEffect]})
];

let previousAccumulationTexture = clearedHistoryTexture;

function accumulateFrame(frameIndex: number, currentSceneTexture: Texture): Texture {
const renderer = accumulationRenderers[frameIndex % accumulationRenderers.length];
previousAccumulationTexture = renderer.renderToTexture({
sourceTexture: currentSceneTexture,
bindings: {persistenceTexture: previousAccumulationTexture}
});
return previousAccumulationTexture;
}

Alternating renderers prevents one pass from sampling and writing the same internal output texture. Clear or replace the history whenever canvas dimensions or scene ownership change.

Parameters

The current implementation has no public scalar uniforms. Its visual response is defined by the following fixed shader behavior:

BehaviorValuePurpose
Current-frame color boost4Keeps sparse bright samples visible in the accumulated image.
Previous-color contribution0.9Produces gradually decaying trails.
Previous-alpha decay0.9Preserves coverage while reducing stale history over time.
Output RGB rangeClamped to 1Prevents repeated accumulation from exceeding display range.

Composition and Cost

The shader adds one fullscreen pass and samples the caller-supplied previous accumulation. Unlike named-history ShaderPassPipeline effects, the standalone pass does not allocate, clear, or rotate history automatically. Use a cleared initial texture and explicitly avoid read/write aliasing.

  • Motion Blur follows current per-pixel velocity instead of accumulating previous images.
  • Temporal Antialiasing validates history with scene depth and motion vectors.
  • Bloom can add stabilized photographic glow to bright accumulated trails.