Skip to content

Native Runtime

The root export threejs-debug-view is the canonical native runtime. The optional /r3f adapter is a thin layer on top of the same pipeline.

Use the native path when you:

  • own the WebGPU render loop and UI
  • want full control over layout, overlays, and viewport presentation
  • do not need React, R3F, or Leva

For install commands, see Quick Start — Native. For the optional adapter, see R3F.

import {
DEFAULT_DEBUG_VIEWS,
createDebugRenderPlan,
createDebugPipelineRuntime,
createDebugViewUniforms,
resolveDebugViewLayout,
updateDebugViewUniforms,
} from "threejs-debug-view"
import { WebGPURenderer } from "three/webgpu"
const views = DEFAULT_DEBUG_VIEWS
const activeView = 0
const layout = resolveDebugViewLayout("single")
const plan = createDebugRenderPlan(views, activeView, layout)
const uniforms = createDebugViewUniforms()
const runtime = createDebugPipelineRuntime(
scene,
camera,
plan,
layout,
renderer as WebGPURenderer,
uniforms,
)
function animate() {
updateDebugViewUniforms(
uniforms,
plan.activePipelineView,
layout,
plan.pipelineViews.length,
1,
)
runtime.pipeline.render()
requestAnimationFrame(animate)
}

Use createDebugPipelineRuntime for overlay, breakdown, grid, and other layouts where the TSL compositor blends multiple views in one fullscreen pass.

When a pane uses a custom camera or resolutionScale below 1, use the viewport planner and viewport renderer:

import {
DEFAULT_DEBUG_VIEWS,
createDebugViewportPlan,
createDebugViewportRenderGraphPlan,
createDebugViewportRenderer,
createDebugViewUniforms,
requiresViewportRuntime,
} from "threejs-debug-view"
const viewportPlan = createDebugViewportPlan({
views: DEFAULT_DEBUG_VIEWS,
viewportViews: [
{ view: "beauty" },
{ view: "normal", resolutionScale: 0.5 },
],
layout: "split-h",
})
if (requiresViewportRuntime(viewportPlan)) {
const viewportGraph = createDebugViewportRenderGraphPlan(viewportPlan)
const uniforms = createDebugViewUniforms()
const viewportRenderer = createDebugViewportRenderer({
gl: renderer,
scene,
defaultCamera: camera,
viewportPlan,
viewportGraph,
uniforms,
})
// Each frame:
viewportRenderer.render()
}

createDebugViewportRenderer clears the canvas, renders each pane into a scissor rect, adjusts per-pane camera aspect when needed, and restores the renderer’s previous viewport/scissor state.

Compositor (createDebugPipelineRuntime)Viewport (createDebugViewportRenderer)
One shader graph blends multiple viewsOne pass per pane, routed with GL scissor/viewport
overlayOpacity blends overlay layoutsoverlayOpacity defaults to 1 (opaque panes)
TSL divider lines between cellsNo divider lines — panes are separated physically
Layout uniforms updated each framePane rects computed once when the renderer is created

Recreate the viewport renderer when viewportPlan or viewportGraph changes. Optional overlayOpacity and dividerStyle are forwarded to updateDebugViewUniforms; single-view passes do not draw compositor dividers or overlay blends.

Call requiresViewportRuntime(viewportPlan) after planning to choose between the compositor and viewport paths.

These native exports are framework-agnostic — safe in tests, tools, or custom engines:

HelperPurpose
resolveDebugViewLayoutNormalize layout presets into rows, columns, and slots
createDebugRenderPlanSelect passes and pipeline views for a layout
createDebugViewportPlanMap pane assignments to viewport cells
createDebugViewportRenderGraphPlanGroup cells into render passes
requiresViewportRuntimetrue when any pane uses a custom camera or sub-full resolutionScale
createDebugPipelineRuntimeKeyStable cache key when rebuilding pipelines
readHeatmapCostFromCanvasSample shader-cost heatmap pixels from a canvas

threejs-debug-view/r3f adds useFrame / useThree wiring, DOM overlays for labels and legends, and optional Leva controls. It calls the same native runtime documented here — it does not duplicate the WebGPU pipeline.

See API Reference for R3F prop detail.