Skip to content

Performance Model

Debug views should be cheap enough to leave mounted while you work. The native runtime keeps that true by separating material-channel views from pass-backed views — the optional R3F adapter uses the same pass model.

See Native Runtime for compositor vs viewport paths.

The scene pass can pack several material diagnostics into one low-precision RGBA target:

ChannelSourceFallback when unsupported
Rroughness1
Gmetallic / metalness0
Bao1
Aopacity / transparency1

These defaults are shader-side defaults. The runtime does not walk the scene to patch materials, and it does not fabricate temporary aoMap, roughness, metalness, or emissive properties.

That matters because a debug view should not mutate the thing it is measuring. If a material has an AO map, the AO view reads it. If it does not, the view shows white, meaning no material AO contribution.

In single compose mode, switching between compatible built-in views reuses one runtime pipeline group instead of rebuilding a pass graph for every click.

The reusable scene group includes:

  • beauty
  • normal
  • depth
  • albedo / baseColor
  • emissive
  • roughness
  • ao
  • metallic / metalness
  • opacity / transparency

The material-detail group includes:

  • materialNormal / normalMap

This avoids first-click stalls for common debug toggles while keeping the selected view narrow from the UI’s point of view.

The reusable scene pass keeps diagnostic outputs low precision. emissive gets its own low-precision scene target, while roughness, metallic, ao, and opacity stay packed in one material target. That avoids exceeding common WebGPU color-attachment byte limits when all compatible views are preconfigured together.

Some views are intentionally not folded into the cheap material-channel path:

SourceWhy it has its own pass
wireframeNeeds a wireframe override material.
lightingOnlyNeeds a neutral lighting override material.
reflectionOnlyNeeds a reflective override material.
overdrawMeasured overlap: depth prepass + blend counter subgraph.
overdrawVisualOptional additive overlap visualization (approx).
lightComplexityLight overlap (v1 analytic counter via NodeMaterial override pass).
shaderCostNeeds bucketed override materials based on material complexity signals.

These views render only when selected or visible in the active layout/viewport plan.

Custom TSL views participate in runtime keys by node identity. If React replaces a custom node instance, the compose pipeline rebuilds so the view does not keep rendering stale shader code.

When equivalent custom views are recreated often, use createCustomDebugView() with a stable id so viewport render-graph deduping can treat them as the same logical view.

Three’s PassNode.compileAsync() can prewarm pass-backed views, but it should be applied carefully. Prewarming must happen after MRT setup and before rendering, without leaking override material or fallback state into the view being inspected.

The current runtime avoids the bigger stall first: it keeps cheap material-channel switching on reusable pipelines and keeps pass-backed views isolated.