BabylonJS/Babylon.js · error · Error

FrameGraphSSAO2Task "${this.name}": sourceTexture, depthText

Error message

FrameGraphSSAO2Task "${this.name}": sourceTexture, depthTexture, normalTexture and camera are required

What it means

FrameGraphSSAO2Task.record() validates that all required inputs were assigned before the frame graph is built. The SSAO2 post-process needs the source (color) texture, depth texture, normal texture and a camera to configure its rendering passes; if any is undefined the task cannot be recorded, so the library throws immediately instead of failing later with a confusing GPU/effect error. This is a fail-fast precondition check inside Babylon.js' frame graph system.

Source

Thrown at packages/dev/core/src/FrameGraph/Tasks/PostProcesses/ssao2Task.ts:30

    public normalTexture: FrameGraphTextureHandle;

    public camera: Camera;

    public override readonly postProcess: ThinSSAO2PostProcess;

    private _currentCameraMode = -1;

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

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

    public override record(skipCreationOfDisabledPasses = false): FrameGraphRenderPass {
        if (this.sourceTexture === undefined || this.depthTexture === undefined || this.normalTexture === undefined || this.camera === undefined) {
            throw new Error(`FrameGraphSSAO2Task "${this.name}": sourceTexture, depthTexture, normalTexture and camera are required`);
        }

        this._currentCameraMode = this.camera.mode;
        this.postProcess.updateEffect();

        const pass = super.record(
            skipCreationOfDisabledPasses,
            (context) => {
                this.postProcess.camera = this.camera;

                if (this._currentCameraMode !== this.camera.mode) {
                    this._currentCameraMode = this.camera.mode;
                    this.postProcess.updateEffect();
                }

                context.setTextureSamplingMode(this.depthTexture, Constants.TEXTURE_BILINEAR_SAMPLINGMODE);
                context.setTextureSamplingMode(this.normalTexture, Constants.TEXTURE_BILINEAR_SAMPLINGMODE);
            },

View on GitHub (pinned to 0592b347b8)

Solutions

  1. Assign sourceTexture, depthTexture and normalTexture from the frame graph texture manager / producing task outputs before building: task.sourceTexture = ...; task.depthTexture = ...; task.normalTexture = ...;
  2. Set task.camera to a valid Camera (e.g. frameGraph.scene.activeCamera) before record()/build()
  3. Ensure the tasks producing the depth/normal textures are added to the graph BEFORE the SSAO2 task and their outputs linked to these inputs
  4. Wrap the build call in try/catch and log which of the four inputs is undefined to pinpoint the missing one

Example fix

// before
const ssao2Task = new FrameGraphSSAO2Task("ssao2", frameGraph, { samples: 16 });
frameGraph.addTask(ssao2Task);
frameGraph.build(); // throws: inputs undefined

// after
const ssao2Task = new FrameGraphSSAO2Task("ssao2", frameGraph, { samples: 16 });
ssao2Task.sourceTexture = mainTextureTask.outputTexture;
ssao2Task.depthTexture = depthTextureTask.outputTexture;
ssao2Task.normalTexture = normalTextureTask.outputTexture;
ssao2Task.camera = frameGraph.scene.activeCamera;
frameGraph.addTask(ssao2Task);
frameGraph.build();
Defensive patterns

Strategy: validation

Validate before calling

// before frameGraph.build()
const required = { sourceTexture: ssao2Task.sourceTexture, depthTexture: ssao2Task.depthTexture, normalTexture: ssao2Task.normalTexture, camera: ssao2Task.camera };
const missing = Object.entries(required).filter(([, v]) => v === undefined).map(([k]) => k);
if (missing.length) throw new Error(`SSAO2 task missing inputs: ${missing.join(", ")}`);

Type guard

function hasSSAO2Inputs(t) { return t.sourceTexture !== undefined && t.depthTexture !== undefined && t.normalTexture !== undefined && t.camera !== undefined; }

Try / catch

try { frameGraph.build(); } catch (e) { if (String(e.message).includes("sourceTexture, depthTexture, normalTexture and camera are required")) { console.error("SSAO2 task inputs not wired:", { source: ssao2Task.sourceTexture, depth: ssao2Task.depthTexture, normal: ssao2Task.normalTexture, camera: ssao2Task.camera }); } else { throw e; } }

Prevention

When it happens

Trigger: Calling FrameGraphSSAO2Task.record() (directly or via FrameGraph.build()) when sourceTexture, depthTexture, normalTexture or camera was never set on the task instance, e.g. the task was added to the graph but its input properties were never assigned from texture manager handles or a camera.

Common situations: Building a frame graph where the SSAO2 task was wired before the source pipeline task produced its texture handles; forgetting to pass the camera when constructing the task; refactoring away from the legacy SSAO2RenderingPipeline where the pipeline grabbed scene textures automatically — frame graph tasks require explicit texture bindings; conditional code paths that skip texture assignment.

Related errors


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