BabylonJS/Babylon.js · error

FrameGraphIblShadowsRendererTask "${this.name}": depthTextur

Error message

FrameGraphIblShadowsRendererTask "${this.name}": depthTexture, normalTexture, positionTexture and velocityTexture are required

What it means

FrameGraphIblShadowsRendererTask.record() requires all four G-buffer inputs (depthTexture, normalTexture, positionTexture, velocityTexture) to be set, since the IBL shadows renderer samples the full geometry pass data. If any of them is undefined, record() throws instead of recording child passes with missing bindings.

Source

Thrown at packages/dev/core/src/FrameGraph/Tasks/Rendering/iblShadowsRendererTask.pure.ts:487

        // Don't poll for shadow dependencies here.  _tryEnableShadowsTasks() is called
        // in record() (where it imports a placeholder ICDF if the real one isn't ready yet,
        // preventing any "handle not found" errors) and by _beforeRenderDependencyObserver
        // on every frame.  Shadows enable automatically once the CDF, environment texture,
        // and blue-noise texture are all ready — no timeout involved.git pu
        return Promise.resolve();
    }

    public override isReady(): boolean {
        return this._voxelizationTask.isReady() && this._tracingTask.isReady() && this._spatialBlurTask.isReady() && this._accumulationTask.isReady();
    }

    /**
     * Records the parent task.
     * Child tasks record the actual passes.
     */
    public override record(): void {
        if (this.depthTexture === undefined || this.normalTexture === undefined || this.positionTexture === undefined || this.velocityTexture === undefined) {
            throw new Error(`FrameGraphIblShadowsRendererTask "${this.name}": depthTexture, normalTexture, positionTexture and velocityTexture are required`);
        }

        this._lastImportedIcdfTexture = null;
        this._lastImportedEnvironmentTexture = null;
        this._lastImportedBlueNoiseTexture = null;

        this._tryEnableShadowsTasks();

        // Set sub-task texture inputs (these are set here because handles may not be available at construction time)
        this._tracingTask.depthTexture = this.depthTexture;
        this._tracingTask.normalTexture = this.normalTexture;
        this._spatialBlurTask.depthTexture = this.depthTexture;
        this._spatialBlurTask.normalTexture = this.normalTexture;
        this._accumulationTask.positionTexture = this.positionTexture;
        this._accumulationTask.velocityTexture = this.velocityTexture;

        this._voxelizationTask.record();
        this._tracingTask.record();

View on GitHub (pinned to 0592b347b8)

Solutions

  1. Assign all four inputs: task.depthTexture, task.normalTexture, task.positionTexture, task.velocityTexture from the upstream geometry pass outputs before building the graph.
  2. Confirm the upstream geometry task is added to the frame graph and its output handles are not dangling.
  3. Order tasks so the geometry/GBUFFER task is registered before the IBL shadows renderer task.
  4. Add a pre-build validation asserting all four properties are defined.

Example fix

// before
iblShadowsRenderer.depthTexture = geometryTask.depth;
iblShadowsRenderer.normalTexture = geometryTask.normal;
// position and velocity missing

// after
iblShadowsRenderer.depthTexture = geometryTask.depth;
iblShadowsRenderer.normalTexture = geometryTask.normal;
iblShadowsRenderer.positionTexture = geometryTask.position;
iblShadowsRenderer.velocityTexture = geometryTask.velocity;
Defensive patterns

Strategy: validation

Validate before calling

const missing = (['depthTexture','normalTexture','positionTexture','velocityTexture'] as const)
    .filter(k => task[k] === undefined);
if (missing.length) throw new Error(`IblShadowsRendererTask missing inputs: ${missing.join(', ')}`);

Type guard

function isIblShadowsInputReady(t: FrameGraphIblShadowsRendererTask): boolean {
    return t.depthTexture !== undefined && t.normalTexture !== undefined && t.positionTexture !== undefined && t.velocityTexture !== undefined;
}

Try / catch

try {
    frameGraph.build();
} catch (e) {
    if (String(e).includes('depthTexture, normalTexture, positionTexture and velocityTexture are required')) {
        console.error('Wire all 4 gbuffer outputs to the IBL shadows renderer task');
    } else throw e;
}

Prevention

When it happens

Trigger: Calling record() (directly or via frameGraph.build()/render loop) on an IblShadowsRendererTask where one or more of depthTexture, normalTexture, positionTexture, velocityTexture was never assigned from an upstream geometry/GBUFFER task's outputs.

Common situations: Forgetting to connect a FrameGraphGeometryRenderer/ prepass task outputs to the IBL shadows renderer task; a refactor renamed or removed one of the four texture inputs; conditionally building the graph where the geometry task output handle was not yet resolved (dangling handle).

Related errors


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