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
- Assign all four inputs: task.depthTexture, task.normalTexture, task.positionTexture, task.velocityTexture from the upstream geometry pass outputs before building the graph.
- Confirm the upstream geometry task is added to the frame graph and its output handles are not dangling.
- Order tasks so the geometry/GBUFFER task is registered before the IBL shadows renderer task.
- 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
- Wire all four gbuffer outputs in one helper function so none can be forgotten.
- Add the geometry source task before the renderer task in the graph.
- Assert inputs in a unit test that builds the frame graph.
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
- FrameGraphSSAO2Task "${this.name}": sourceTexture, depthText
- FrameGraphSSRRenderingPipelineTask "${this.name}": sourceTex
- FrameGraphSSRTask "${this.name}": sourceTexture, normalTextu
- FrameGraphPostProcessTask "${this.name}": sourceTexture and
- FrameGraphVolumetricLightingBlendVolumeTask "${this.name}":
AI-assisted analysis of BabylonJS/Babylon.js@0592b347b8 (2026-08-30).
Data as JSON: /api/errors/dc44f5b1c0dcce42.
Report an issue: GitHub.