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.