BabylonJS/Babylon.js · error · Error

FrameGraphMotionBlurTask "${this.name}": velocityTexture is

Error message

FrameGraphMotionBlurTask "${this.name}": velocityTexture is required for object-based motion blur

What it means

Thrown from the bindings callback of FrameGraphMotionBlurTask.record() when the post-process is configured for object-based motion blur (isObjectBased === true) but velocityTexture is undefined. Object-based motion blur samples per-object velocity from a velocity render target, so that texture is mandatory in this mode.

Source

Thrown at packages/dev/core/src/FrameGraph/Tasks/PostProcesses/motionBlurTask.ts:46

     */
    constructor(name: string, frameGraph: FrameGraph, thinPostProcess?: ThinMotionBlurPostProcess) {
        super(name, frameGraph, thinPostProcess || new ThinMotionBlurPostProcess(name, frameGraph.scene));
    }

    public override getClassName(): string {
        return "FrameGraphMotionBlurTask";
    }

    public override record(skipCreationOfDisabledPasses = false): FrameGraphRenderPass {
        if (this.sourceTexture === undefined) {
            throw new Error(`FrameGraphMotionBlurTask "${this.name}": sourceTexture is required`);
        }

        const pass = super.record(skipCreationOfDisabledPasses, undefined, (context) => {
            if (this.velocityTexture) {
                context.bindTextureHandle(this._postProcessDrawWrapper.effect!, "velocitySampler", this.velocityTexture);
            } else if (this.postProcess.isObjectBased) {
                throw new Error(`FrameGraphMotionBlurTask "${this.name}": velocityTexture is required for object-based motion blur`);
            }

            if (this.depthTexture) {
                context.bindTextureHandle(this._postProcessDrawWrapper.effect!, "depthSampler", this.depthTexture);
            } else if (!this.postProcess.isObjectBased) {
                throw new Error(`FrameGraphMotionBlurTask "${this.name}": depthTexture is required for screen-based motion blur`);
            }
        });

        pass.addDependencies(this.velocityTexture);
        pass.addDependencies(this.depthTexture);

        this.postProcess.textureWidth = this._sourceWidth;
        this.postProcess.textureHeight = this._sourceHeight;

        return pass;
    }
}

View on GitHub (pinned to 0592b347b8)

Solutions

  1. Assign task.velocityTexture to a velocity texture handle from a task that produces velocities.
  2. Alternatively, switch to screen-based motion blur (set the post-process mode so isObjectBased is false) if you intend to use depth-only blur.
  3. Verify the upstream velocity task is added to the graph and rendered before the motion blur task.
  4. Check that the velocity texture handle was not reset to undefined during reconfiguration.

Example fix

// before
const mb = new FrameGraphMotionBlurTask(frameGraph, "motionBlur"); // object-based
mb.sourceTexture = colorTask.outputTexture;
mb.depthTexture = depthTask.outputTexture;

// after
const mb = new FrameGraphMotionBlurTask(frameGraph, "motionBlur");
mb.sourceTexture = colorTask.outputTexture;
mb.velocityTexture = objectRendererTask.outputTexture; // velocity RT
mb.depthTexture = depthTask.outputTexture;
Defensive patterns

Strategy: validation

Validate before calling

if (mbTask.postProcess.isObjectBased && mbTask.velocityTexture === undefined) {
  throw new Error("Object-based motion blur requires velocityTexture before build");
}

Type guard

function velocityWiredForMode(t: { postProcess: { isObjectBased: boolean }; velocityTexture?: unknown; depthTexture?: unknown }): boolean {
  return !t.postProcess.isObjectBased || t.velocityTexture !== undefined;
}

Try / catch

try {
  frameGraph.build();
} catch (e) {
  if (String(e?.message).includes("velocityTexture is required for object-based motion blur")) {
    console.error("Wire a velocity texture or switch to screen-based mode:", e.message);
  } else { throw e; }
}

Prevention

When it happens

Trigger: Creating a motion blur task with object-based mode (default or explicitly) and building the graph without assigning task.velocityTexture to a velocity texture handle (e.g. from an ObjectRendererTask with velocity enabled).

Common situations: Leaving the task in its default object-based mode while only wiring a depth texture (screen-based setup); forgetting to enable velocity output on the object renderer; switching pipelines and not realizing the mode/texture pairing must match.

Related errors


AI-assisted analysis of BabylonJS/Babylon.js@0592b347b8 (2026-08-30). Data as JSON: /api/errors/fc6d0c3fc908f21e. Report an issue: GitHub.