Skip to content

Add a scene depth mode to the CameraFrame debug rendering - #9182

Merged
mvaligursky merged 1 commit into
mainfrom
mv-camera-frame-debug-depth
Aug 17, 2026
Merged

Add a scene depth mode to the CameraFrame debug rendering#9182
mvaligursky merged 1 commit into
mainfrom
mv-camera-frame-debug-depth

Conversation

@mvaligursky

Copy link
Copy Markdown
Contributor

CameraFrame.debug could display the scene colour, the bloom, the SSAO, the vignette and both halves of the depth of field - but not the scene depth those effects are driven by. So inspecting anything depth related meant writing a material that samples uSceneDepthMap by hand, on a layer rendered after the scene pass, which is what the gaussian splatting work ended up doing twice.

Adds 'depth', displaying the linear scene depth as a ramp over the camera's clip range.

A debug mode never changes what is rendered

The mode does not request the depth. A frame with no depth consumer renders black instead of quietly enabling a producer, so switching the debug view can never alter the thing being debugged. That is what the internal depthmissing mode is for: the requested mode resolves to it when nothing has published a depth, and a debug build explains the black screen once:

CameraFrame.debug is set to 'depth', but nothing this camera renders produces the scene depth, so the debug view is black. Enable an effect which consumes the depth (the depth of field, the volumetric fog, TAA, or SSAO in combine mode), or request it with CameraFrame.rendering.sceneDepthMap.

Changes

  • compose.js (GLSL and WGSL): a DEBUG_COMPOSE == depth branch, plus the depthmissing branch which writes black. screenDepthPS is included inside the depth branch - declaring the sampler in a frame with no depth bound to it is an error, which is also why the missing case needs a mode of its own rather than an #ifdef around the sampling.
  • RenderPassCompose: had no camera at all until now, so it takes the camera component for ShaderUtils.addScreenDepthChunkDefines (the depth encoding varies with the producer) and for the clip range. camera_params is set in execute only in this mode, so the rest of the composition leaves camera state alone. The resolved mode and the depth encoding key both feed the shader name.
  • FramePassCameraFrame: reports depth availability (sceneTextureDepth || prepassEnabled) to the compose pass each frame, and warns in a debug build when the mode has nothing to show.
  • DebugType.DEPTH in scripts/esm/camera-frame.mjs, so the editor-facing script exposes it too.

Notes

  • The ramp is linear over near..far. It reads better than the raw numbers suggest, because the debug branch sits before gammaCorrectOutput - a subject at 12..25 of a 70 unit far clip lands around 0.45..0.63 on screen. A log remap would give the near field more contrast at the cost of no longer being proportional to distance; not done here.
  • Verified on both backends with an unreleased gsplat example: correct ramp on WebGPU and WebGL 2, black plus the warning when fog and DOF are both off, and the pre-existing modes still work through the same setting.
  • No new API surface beyond the one enum value; unused modes cost nothing, as DEBUG_COMPOSE was already part of the compose shader key.

🤖 Generated with Claude Code

The debug rendering could display the scene colour, the bloom, the SSAO,
the vignette and both halves of the depth of field, but not the depth
those effects are driven by - so anything depth related had to be
inspected with a hand written material sampling uSceneDepthMap, which is
what the gaussian splatting examples ended up doing.

Adds 'depth', displaying the linear scene depth as a ramp over the
camera's clip range. Like every other mode it only displays what the
frame already produces: it does not request the depth, so a frame with no
depth consumer renders black rather than quietly turning a producer on.
That is what the internal depthmissing mode is - the requested mode
resolves to it when nothing has published a depth, and a debug build
explains the black screen once.

The compose pass had no camera until now, so it takes the camera
component for the depth encoding defines and the clip range, and sets
camera_params only for this mode, leaving the rest of the composition
untouched. The screenDepthPS include is inside the depth branch, as
declaring the sampler in a frame with no depth bound to it is an error.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown

Public API report

This PR changes the public API surface (+1 / −1), per the docs' rules (@ignore / @Private / undocumented are excluded).

Show API diff
-CameraFrame.debug: "scene" | "ssao" | "bloom" | "vignette" | "dofcoc" | "dofblur" | null
+CameraFrame.debug: "depth" | "scene" | "ssao" | "bloom" | "vignette" | "dofcoc" | "dofblur" | null

Informational only — this never fails the build.

@github-actions

Copy link
Copy Markdown

Build size report

This PR changes the size of the minified bundles.

Bundle Minified Gzip Brotli
playcanvas.min.js 2366.5 KB (+1.4 KB, +0.06%) 607.7 KB (+0.3 KB, +0.04%) 472.0 KB (+0.5 KB, +0.11%)
playcanvas.min.mjs 2363.9 KB (+1.4 KB, +0.06%) 606.7 KB (+0.3 KB, +0.04%) 471.3 KB (+0.3 KB, +0.06%)

@mvaligursky mvaligursky added the area: graphics Graphics related issue label Aug 17, 2026
@mvaligursky
mvaligursky merged commit c60ed91 into main Aug 17, 2026
10 checks passed
@mvaligursky
mvaligursky deleted the mv-camera-frame-debug-depth branch August 17, 2026 10:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: graphics Graphics related issue

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant