BabylonJS/Babylon.js · error · Error

FrameGraphSelectionOutlineLayerTask "${this.name}": depthTex

Error message

FrameGraphSelectionOutlineLayerTask "${this.name}": depthTexture is required

What it means

FrameGraphSelectionOutlineLayerTask throws this when depth occlusion is enabled (layer.useDepthOcclusion && layer.occlusionStrength > 0) but no depthTexture handle was assigned to the task. Depth occlusion needs the scene depth to hide outlines behind occluders, so the texture is mandatory in that configuration.

Source

Thrown at packages/dev/core/src/FrameGraph/Tasks/Layers/selectionOutlineTask.ts:46

     */
    constructor(name: string, frameGraph: FrameGraph, scene: Scene, options?: IThinSelectionOutlineLayerOptions) {
        super(name, frameGraph, scene, new ThinSelectionOutlineLayer(name, scene, options, true), 0, FrameGraphBaseLayerBlurType.None, false, false, false);

        this._objectRendererForLayerTask.objectList = {
            meshes: this.layer._selection || [],
            particleSystems: [],
        };
    }

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

    public override record() {
        const useDepthOcclusion = this.layer.useDepthOcclusion && this.layer.occlusionStrength > 0;

        if (useDepthOcclusion && this.depthTexture === undefined) {
            throw new Error(`FrameGraphSelectionOutlineLayerTask "${this.name}": depthTexture is required`);
        }

        super.record(false, (context: FrameGraphRenderContext, effect: Effect) => {
            context.bindTextureHandle(effect, "maskSampler", this._objectRendererForLayerTask.outputTexture);
            if (useDepthOcclusion) {
                context.bindTextureHandle(effect, "depthSampler", this.depthTexture!);
            }
        });

        this.layer.textureWidth = this._layerTextureDimensions.width;
        this.layer.textureHeight = this._layerTextureDimensions.height;
    }
}

View on GitHub (pinned to 0592b347b8)

Solutions

  1. Assign a valid depth texture handle to selectionOutlineTask.depthTexture before calling record().
  2. If occlusion is not needed, set layer.useDepthOcclusion = false (and/or occlusionStrength = 0) so the depth input becomes optional.
  3. Ensure the depth texture comes from a preceding task output (e.g. an object renderer or main depth task) rather than being left undefined.

Example fix

// before
const task = new FrameGraphSelectionOutlineLayerTask("outline", context, layer);
layer.useDepthOcclusion = true;
// after
const task = new FrameGraphSelectionOutlineLayerTask("outline", context, layer);
task.depthTexture = mainObjectRendererTask.depthTexture;
layer.useDepthOcclusion = true;
Defensive patterns

Strategy: validation

Validate before calling

if (selectionOutlineTask.layer.useDepthOcclusion && selectionOutlineTask.layer.occlusionStrength > 0 && selectionOutlineTask.depthTexture === undefined) {
  throw new Error("SelectionOutline needs depthTexture when useDepthOcclusion is on");
}

Type guard

function isDepthOcclusionReady(task: FrameGraphSelectionOutlineLayerTask): boolean {
  return !task.layer.useDepthOcclusion || task.layer.occlusionStrength <= 0 || task.depthTexture !== undefined;
}

Try / catch

try {
  selectionOutlineTask.record();
} catch (e) {
  if (String(e).includes("depthTexture is required")) {
    selectionOutlineTask.layer.useDepthOcclusion = false;
    selectionOutlineTask.record();
  } else throw e;
}

Prevention

When it happens

Trigger: selectionOutlineTask.record() with layer.useDepthOcclusion = true (or occlusionStrength > 0) while task.depthTexture is undefined.

Common situations: Enabling useDepthOcclusion on the layer after building the task without wiring a depth input; forgetting the depthTexture assignment when converting from the legacy SelectionOutlineLayer; copying setup code that disabled occlusion.

Related errors


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