Render the scene depth from the scene pass, replacing the depth prepass where possible - #9174
Conversation
…ss where possible
Public API reportThis PR changes the public API surface (+2 / −0), per the docs' rules (@ignore / @Private / undocumented are excluded). Show API diff+CameraFrame.static isSplatSceneDepthSupported(device: GraphicsDevice): boolean
+GSplatParams.sceneDepthWrite: booleanInformational only — this never fails the build. |
Build size reportThis PR changes the size of the minified bundles.
|
There was a problem hiding this comment.
Pull request overview
Moves post-process depth generation into the scene pass where supported, avoiding redundant geometry prepasses.
Changes:
- Adds scene-depth attachments and publication.
- Adds optional Gaussian splat depth contribution.
- Reorders combined SSAO and adjusts the DOF example’s MSAA/TAA settings.
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
src/scene/renderer/render-pass-forward.js |
Publishes generated scene textures. |
src/scene/gsplat-unified/gsplat-params.js |
Adds the splat depth-write option. |
src/scene/constants.js |
Maps scene textures to uniforms. |
src/extras/render-passes/frame-pass-camera-frame.js |
Selects and configures depth producers. |
src/extras/render-passes/camera-frame.js |
Exposes device support detection. |
examples/src/examples/graphics/depth-of-field.example.mjs |
Avoids combining TAA with MSAA. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 6 out of 6 changed files in this pull request and generated no new comments.
Suppressed comments (1)
src/extras/render-passes/frame-pass-camera-frame.js:299
- This warning also fires when TAA or combine-mode SSAO is the only depth consumer, but it specifically says volumetric fog and depth of field are affected even when both are disabled. Please describe the active consumers dynamically, or use a generic message such as “effects using scene depth cannot account for the splats,” so the remediation is not misleading.
Debug.warnOnce(`CameraFrame: the gaussian splats this camera renders do not contribute to the scene depth, and so the effects using it (the volumetric fog and the depth of field) are not bound by them: ${reason}.`);
CameraFrame can now render the scene depth as an additional attachment of the scene render target, alongside the scene color, instead of by a depth prepass. This is both cheaper and more capable.
Cheaper, because the depth prepass is a second geometry pass over every opaque mesh the camera renders, and for the common configurations it disappears entirely - volumetric fog, depth of field, TAA and SSAO all consume the depth only after the scene has been rendered, so the scene pass can produce it as a by-product for the cost of one attachment write. On the examples this removes the prepass from volumetric fog, TAA, the shadow catcher and SSAO in combine mode.
More capable, because the blended geometry contributes to it. Gaussian splats accumulate a transmittance weighted depth as they render, which a prepass cannot produce at all, so the effects using the depth become bounded by the splats instead of drawing through them. That is opt-in per scene, as it costs the attachment for the whole scene pass.
Changes:
CameraFramederives which producer to use rather than exposing a setting. The depth is rendered by the scene pass when only the post-processing passes consume it. When something needs it earlier - the materials, viarendering.sceneDepthMap, or SSAO applied during shading - the prepass is kept, and the scene pass additionally renders it only when the splats are set to contribute.GSplatParams.sceneDepthWriteturns the splat contribution on, defaulting to false.CameraFrame.isSplatSceneDepthSupportedreports whether a device can do it, so an application can disable those effects on the ones which cannot.after, mirroring how the depth prepass publishes its own, so the passes consuming it sample whichever producer ran later in the frame. Only the last pass rendering to the scene render target publishes, as exposing an attachment which the remaining passes still render into would let the materials they render sample it.R32F, or asR16Fwhere 32 bit float blending is unavailable. Half float is only used when the splats are contributing, since otherwise the prepass stores the depth more precisely - asR32F, or losslessly packed into RGBA8 - and the effects consuming it are sensitive to that.examples/graphics/depth-of-fielddisables multi-sampling when TAA is enabled, matching the ambient occlusion example. It was paying for both.API Changes:
GSplatParams#sceneDepthWrite- new, whether the gaussian splats contribute to the scene depth. Defaults to false.CameraFrame.isSplatSceneDepthSupported(device)- new static, whether a device can render the scene depth the splats contribute to.Nothing changes for a camera whose configuration consumes no depth. Verified on both backends across the examples using CameraFrame, including the two-scene-pass case with a color grab pass, partial viewport cameras, and a device emulated as having no float blending to exercise the half float path and the packed prepass coexistence.