BabylonJS/Babylon.js · error · Error

FrameGraphMotionBlurTask "${this.name}": sourceTexture is re

Error message

FrameGraphMotionBlurTask "${this.name}": sourceTexture is required

What it means

FrameGraphMotionBlurTask.record() aborts immediately if sourceTexture is undefined, since no motion blur pass can run without an input color texture. This is the first of three guards in the task's record() method; the other two (velocity/depth) fire later inside the pass bindings.

Source

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

    public override readonly postProcess: ThinMotionBlurPostProcess;

    /**
     * Constructs a new motion blur task.
     * @param name The name of the task.
     * @param frameGraph The frame graph this task belongs to.
     * @param thinPostProcess The thin post process to use for the task. If not provided, a new one will be created.
     */
    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);

View on GitHub (pinned to 0592b347b8)

Solutions

  1. Assign task.sourceTexture a valid texture handle before build().
  2. Add the source-producing task to the graph before the motion blur task.
  3. Check that you are not accidentally clearing/reassigning sourceTexture after initial setup.

Example fix

// before
const mb = new FrameGraphMotionBlurTask(frameGraph, "motionBlur");
frameGraph.addTask(mb);

// after
const mb = new FrameGraphMotionBlurTask(frameGraph, "motionBlur");
mb.sourceTexture = objectRendererTask.outputTexture;
frameGraph.addTask(mb);
Defensive patterns

Strategy: validation

Validate before calling

if (mbTask.sourceTexture === undefined) {
  throw new Error("Motion blur task missing sourceTexture before build");
}

Type guard

function hasMotionBlurSource(t: { sourceTexture?: unknown }): boolean {
  return t.sourceTexture !== undefined;
}

Try / catch

try {
  frameGraph.build();
} catch (e) {
  if (String(e?.message).includes("sourceTexture is required")) {
    console.error("Motion blur source not wired:", e.message);
  } else { throw e; }
}

Prevention

When it happens

Trigger: Calling frameGraph.addTask(motionBlurTask) and building/rendering the graph without ever assigning motionBlurTask.sourceTexture.

Common situations: Adding the motion blur task before the source render task in the graph; forgetting the assignment when copying a sample; conditional setups where the source task is skipped but the blur task is not.

Related errors


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