{"record":{"id":"e28c4b88a4a0ab6d","repo":"BabylonJS/Babylon.js","slug":"depth-texture-is-required-for-aerial-perspective-c","errorCode":null,"errorMessage":"Depth texture is required for aerial perspective compositor.","messagePattern":"Depth texture is required for aerial perspective compositor\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/dev/addons/src/atmosphere/atmosphere.ts","lineNumber":1122,"sourceCode":"        if (\r\n            !effectWrapper.isReady() ||\r\n            !(skyViewLut?.isReady() ?? true) ||\r\n            !multiScatteringLut.isReady() ||\r\n            !transmittanceLut.isReady() ||\r\n            !(aerialPerspectiveLut?.isReady() ?? true) ||\r\n            !this.depthTexture.isReady()\r\n        ) {\r\n            return;\r\n        }\r\n\r\n        DrawEffect(\r\n            engine,\r\n            this._effectRenderer!,\r\n            effectWrapper,\r\n            null, // No render target, it will render to the current buffer.\r\n            (effectRenderer, _, effect) => {\r\n                if (this.depthTexture === null) {\r\n                    throw new Error(\"Depth texture is required for aerial perspective compositor.\");\r\n                }\r\n                this.bindUniformBufferToEffect(effect);\r\n                effectRenderer.bindBuffers(effect);\r\n                effect.setTexture(\"transmittanceLut\", transmittanceLut);\r\n                effect.setTexture(\"multiScatteringLut\", multiScatteringLut);\r\n                if (this._isSkyViewLutEnabled) {\r\n                    effect.setTexture(\"skyViewLut\", skyViewLut);\r\n                }\r\n                if (this._isAerialPerspectiveLutEnabled) {\r\n                    effect.setTexture(\"aerialPerspectiveLut\", aerialPerspectiveLut);\r\n                }\r\n                effect.setTexture(\"depthTexture\", this.depthTexture);\r\n                effectRenderer.draw();\r\n            },\r\n            1, // depth to use in the compositor.\r\n            this.applyApproximateTransmittance ? Constants.ALPHA_PREMULTIPLIED_PORTERDUFF : Constants.ALPHA_ONEONE,\r\n            true, // depthTest\r\n            false, // depthWrite\r","sourceCodeStart":1104,"sourceCodeEnd":1140,"githubUrl":"https://github.com/BabylonJS/Babylon.js/blob/0592b347b8a4ee0236089ea86a749cacfdb266d8/packages/dev/addons/src/atmosphere/atmosphere.ts#L1104-L1140","documentation":"The aerial perspective compositor blends atmosphere into already-rendered geometry based on per-pixel depth. It requires a scene depth texture bound via `atmosphere.depthTexture`. Inside the render callback the code re-checks `this.depthTexture === null` and throws because sampling depth is impossible without it.","triggerScenarios":"Enabling aerial perspective (compositor mode) on an Atmosphere instance without setting `atmosphere.depthTexture = ...` (and not passing `options.depthTexture`) before/at render time.","commonSituations":"Using Atmosphere purely as a skybox (no depth needed) and then enabling the aerial-perspective/post-process path; forgetting to rebind depthTexture after recreating the render target or on scene resize; constructing with options that omit depthTexture.","solutions":["Set a depth texture before rendering: `atmosphere.depthTexture = scene.enableDepthRenderer().getDepthMap().getDepthTexture()` (or pass `options.depthTexture`).","If aerial perspective is not wanted, disable the compositor path so depth is never required (use Atmosphere as sky only).","Re-assign depthTexture whenever the prepass/depth renderer is recreated (resize, render target rebuild) so it is never null at draw time."],"exampleFix":"// before\nconst atmosphere = new Atmosphere(scene, [sun]); // depthTexture defaults to null\natmosphere.enableAerialPerspective?.(); // throws\n// after\nconst depthRenderer = scene.enableDepthRenderer();\nconst atmosphere = new Atmosphere(scene, [sun], { depthTexture: depthRenderer.getDepthMap().getDepthTexture() });","handlingStrategy":"validation","validationCode":"const depthTex = atmosphere.depthTexture ?? scene.enableDepthRenderer().getDepthMap().getDepthTexture();\nif (!depthTex) throw new Error(\"depth texture unavailable\");\natmosphere.depthTexture = depthTex;","typeGuard":"const hasDepth = (a: Atmosphere): a is Atmosphere & { depthTexture: WebGLTexture | GPUTexture } => a.depthTexture !== null;","tryCatchPattern":"try {\n  scene.render();\n} catch (e) {\n  if (String(e).includes(\"Depth texture is required\")) {\n    atmosphere.depthTexture = scene.enableDepthRenderer().getDepthMap().getDepthTexture();\n  } else throw e;\n}","preventionTips":["Always pass options.depthTexture when using aerial perspective.","Rebind depthTexture after recreating render targets / resizing.","Keep the depth renderer enabled for the whole lifetime of the compositor."],"tags":["atmosphere","depth-texture","aerial-perspective","missing-resource"],"backgroundTag":"missing-required-resource","analyzedSha":"0592b347b8a4ee0236089ea86a749cacfdb266d8","analyzedAt":"2026-08-30T15:11:20.442Z","schemaVersion":2},"datasetVersion":"2026-08-30T18:17:15.746Z"}