Skip to content

srinivas-86/webgl-developer-tool

Repository files navigation

WebGL Developer Tool

A modern, in-browser WebGL 1 & 2 inspector, debugger, and profiler.

Package name: webgl-developer-tool


About

WebGL Developer Tool is a modernized fork and major feature expansion of benvanik/WebGL-Inspector (BSD-3-Clause © 2014 Ben Vanik). The original tool was a landmark piece of WebGL tooling that let developers capture a frame, step through every GL call, inspect GPU resources, and replay the frame on a mirror canvas — all from inside the browser, with no extension required.

This project preserves that core idea and extends it into a fuller, modern debugger:

  • Ported from RequireJS/AMD to modern ESM + Vite. Zero runtime dependencies.
  • Targets both WebGL 1 (primary) and WebGL 2 (UBOs, VAOs, samplers, transform feedback, queries, multisampled renderbuffers, pixel-pack/unpack state).
  • Ships two ways: a standalone <script> embed and a Chrome Manifest V3 extension.
  • Adds many features the original never had (Console tab, Uniforms tab, shader hot-reload, frame export/import, dockable layouts, theme toggle, clickable source links, and more — see Features).
  • 132 unit tests across 10 suites — run with npm test.

💡 If you used the original WebGL-Inspector, the mental model is identical — hit Capture (F12), browse the trace, click resources to inspect — but almost every tab has been upgraded with richer detail.


Features

Frame capture & trace

  • One-click frame capture (F12 or the floating Capture button). Every gl.* call is recorded with its arguments, duration, error code, and full JS call stack.
  • 3-panel Trace view — frame thumbnails on the left, call list in the middle, live replay preview + call detail on the right (matches the original WebGL-Inspector layout).
  • Resource links[Buffer 3], [Program 2], [Texture 5] render as blue clickable links that jump to the resource's detail tab.
  • Enum resolution — numeric GL constants are rendered by name (TRIANGLES, TEXTURE_2D, FUNC_ADD), with bitmask decomposition (COLOR_BUFFER_BIT | DEPTH_BUFFER_BIT).
  • Step controls — restart, step back, step forward, skip to next draw, run to end (with hotkeys F6–F10).
  • Draw-call isolation — click the ⊚ button on any draw to re-render the frame with only that draw call visible, preserving FBO dependencies.

Redundant-call detection

  • Per-frame shadow-state analysis flags gl.* calls that set state to its current value (e.g., useProgram(X) when X is already bound).
  • Yellow row highlighting + live counter in the Trace toolbar (5/36 · 14%).
  • ×N repeat badges on the first occurrence of each redundant pattern so the worst offenders jump out.
  • Toggle off to dim redundant rows when you want to see only the meaningful state changes.

Error detection & Console

  • Red row highlighting on any call where gl.getError() returned non-zero.
  • Live Console tab logs every GL error as it happens (not only inside captures), with:
    • Level filters (Errors / Warnings / Info) with live counts
    • Free-text message search
    • Clickable source-location link on every error — parsed from the JS stack, skips inspector-internal frames, points directly at your code (e.g. …/app.js:293:6)
    • Repeat-collapse with ×N badges

Resource inspection

All resource tabs left-align a resource list and auto-select the first entry.

  • Textures — thumbnail, parameters (size, format, filters, wrap), full-resolution preview rebuilt via readPixels, History, Usage-in-frame, Download PNG / Zoom modal / Copy dataURL toolbar, and source-URL section for textures loaded from <img>/<video>/<canvas>/ImageBitmap.
  • Buffers — target/usage/size with A/E/U type badges at the right end (Array / Element / Uniform / etc.), "Structure (from last draw)" table showing the actual vertex-attribute layout (offset/size/type/stride/normalized) discovered by walking the trace, and stride-aware Contents view with one vertex per row and attribute-group separators.
  • Programs — full info block (LINK_STATUS, VALIDATE_STATUS, DELETE_STATUS, ACTIVE_UNIFORMS, ACTIVE_ATTRIBUTES queried live from the GPU), uniform table with live values, attribute table, sidebar shows VS: / FS: clickable shader refs.
  • Shaders — type, compile status + info log, syntax-highlighted GLSL source, editable (see below).
  • Uniforms — all uniform calls in the frame grouped by program, with the last value set for each uniform rendered as a proper matrix grid / vec / scalar, clickable call-ordinal links back to the Trace.
  • Framebuffers — attachment table (color/depth/stencil) with clickable resource refs, live checkFramebufferStatus().
  • Renderbuffers — size, internal format, samples.

Shader hot-reload

  • Edit any shader's source directly in the Shaders tab.
  • Apply & Recompile pushes the edit into the running app: re-calls shaderSource + compileShader, relinks every program that uses the shader, and transparently refreshes cached WebGLUniformLocation objects so apps that cache locations at init don't break.
  • Live-highlighted GLSL preview below the editor.
  • Revert to original source.
  • Compile errors show inline with the info log; the edit is automatically rolled back on failure.

State inspection

  • State tab with Initial / Current / End dropdown — see the GL state at three points in the frame:
    • Initial — captured at frame start
    • Current — snapshot at the currently-selected trace call (uses the replay GL context)
    • End — captured at frame end
  • Diff highlighting — in Current/End views, every changed row is highlighted green and labeled (was X) so you can instantly spot what the frame modified.
  • 12 canonical state categories (Alignment, Blend, Clear, Color, Coverage, Cull, Depth, Draw, Mipmap Hint, Polygon Offset, Scissor, Stencil) + Vertex Attributes + Texture Units.
  • Clickable resource valuesCURRENT_PROGRAM = [Program 11] jumps to the Programs tab.

Timeline

  • Stat cards: total calls / draw calls / redundant / CPU time / avg per call.
  • Call categories legend with color swatches + count + percentage + total duration per category (Draw, Redundant, Uniform, State changes, Resource binds, Data upload, Texture ops, Queries, Other).
  • Stacked category bar for at-a-glance frame breakdown.
  • Per-call duration chart colored by category, clickable bars jump to the Trace.
  • Top 15 functions by call count table with distribution bars — spot your dominant calls.

Export / Import

  • Export the current frame to a self-contained JSON file.
  • Includes: all calls + stack traces, every resource with parameters and pixel/buffer data (base64), shader sources, init + end state, 60+ GL parameters, frame screenshot as PNG.
  • Import any exported JSON — rebuilt frame appears in the frame selector, fully browsable across all tabs.
  • Imported textures reconstruct previews from the stored pixel bytes; buffers show stride-aware structure as before.
  • Share bug frames with teammates. Archive reference frames for A/B comparison across code changes.

UI / UX

  • Dockable — left / top / bottom / right, detached floating window, Maximize (fills viewport), and Open in new window (separate browser window). Dock choice persists via localStorage.
  • Resizable — drag any inner edge.
  • Dark / Light theme toggle — CSS-variable-driven; affects only the inspector, not the host page.
  • Font-size controlA− 12px A+, clamped 9–24 px, persists.
  • Tab visibility menu — toggle switches let you hide tabs you don't use; a master Show all toggle flips everything. Hidden tabs temporarily re-appear if you click a resource link that navigates there.
  • Single gear (⚙) menu — Chrome-style popover houses dock / theme / font / tabs / export-import in one place.
  • Close button (✕) — hide the inspector window; re-open via F11 or the host "Inspector" button.

Replay & debugging fundamentals (inherited from the original, fixed & improved)

  • Frame replay on a mirror GL context with per-call stepping (uniform-location invalidation and mirror disposal bugs from the original port have been fixed).
  • Real-time GL error capturegl.getError() is polled after every call, so errors show up in the Console tab as they happen, not only after a capture.
  • Always-on JS stack capture — no toggle to forget, clickable source links work out of the box.

Getting Started

Prerequisites

  • Node.js 20+
  • npm

Install & run the samples

git clone <this-repo>
cd webgl-inspector-next
npm install
npm run dev          # Vite dev server on port 5173

Then open:

  • http://localhost:5173/samples/webgl1-basic/ — textured rotating cube (WebGL 1)
  • http://localhost:5173/samples/webgl2-basic/ — WebGL 2 sample with UBOs, instancing, transform feedback

Using the standalone embed

npm run build:embed

This produces dist/embed/gli.js (+ gli.css). Include it on any page before your WebGL code:

<script type="module" src="path/to/gli.js"></script>
<script>
  // Your existing WebGL app — no changes needed.
  const canvas = document.getElementById('c');
  const gl = canvas.getContext('webgl');
  // ...
</script>

The inspector injects two floating buttons (Capture + Inspector) into the bottom-right. Press F12 to capture a frame, F11 to toggle the inspector UI.

Using the Chrome extension

npm run build:extension
  1. Open chrome://extensions/ and enable Developer mode.
  2. Click Load unpacked and select the built dist/extension/ folder.
  3. Click the extension icon on any page with a WebGL canvas.

Build everything at once

npm run build:all    # embed + extension

Run the tests

npm test

Runs 10 unit-test suites (132 assertions) covering GL constants, redundancy detection, resource versioning, settings persistence, console bus, frame serializer, and more.

All scripts

Command Description
npm run dev Vite dev server with hot reload
npm run build:embed Standalone IIFE bundle
npm run build:extension Chrome MV3 extension
npm run build:all Both builds
npm test Run unit tests
npm run gen:info Regenerate GLConsts.js / Info.js from Khronos WebGL IDL
npm run lint ESLint
npm run format Prettier

Keyboard shortcuts

Key Action
F12 Capture current frame
F11 Toggle inspector UI
F6 Step back one call
F7 Skip to next draw call
F8 Step forward one call
F9 Run to end of frame
F10 Restart from frame start
Esc Close modal dialogs (texture zoom, etc.)

Architecture overview

  • src/core/host/ — Instrumentation layer: hooks every GL call, tracks resources (buffers, textures, shaders, programs, FBOs, renderbuffers, VAOs, samplers, queries, syncs, transform feedbacks), captures frames, serializes them.
  • src/core/replay/ — Replays captured frames on a mirror context. RedundancyChecker flags calls that set already-cached state. Controller supports stepping, draw isolation, and depth visualization.
  • src/core/ui/ — Inspector window: Trace, Console, Timeline, State, Textures, Buffers, Programs, Shaders, Uniforms, Framebuffers, Renderbuffers tabs. Dark + light themes (Catppuccin-inspired).
  • src/core/shared/ — GL constants (WebGL1+2 + extensions), call metadata, utilities, event bus, settings, console bus.
  • src/extension/ — Chrome MV3: background service worker, content-script bridge, page-world injector.
  • src/embed.js — Standalone entry that hooks HTMLCanvasElement.prototype.getContext.
  • scripts/gen-info.js — Node script that regenerates shared constants/metadata from Khronos WebGL IDL.

Samples

Bundled samples exercise the inspector against realistic GL workloads. Both ship with the dev server (npm run dev).

samples/webgl1-basic/ — Rotating Textured Cube

A compact WebGL 1 scene that exercises the full pipeline in ~300 lines:

  • Custom vertex & fragment shaders with texture sampling and simple diffuse lighting
  • Interleaved VBO (position + UV + normal) and indexed draws
  • Procedural 64×64 checkerboard texture with mipmap generation
  • Two-pass rendering — render to an FBO (framebuffer + color-attachment texture + depth renderbuffer), then blit the FBO texture to the default framebuffer via a fullscreen quad
  • Per-frame rotating MVP matrix

Good for testing the Trace / Buffer / Texture / Program / Framebuffer / Renderbuffer tabs, draw-call isolation across render passes, and shader hot-reload.

samples/webgl2-basic/ — WebGL 2 Feature Showcase

Demonstrates WebGL 2-specific features:

  • Uniform Buffer Objects (UBOs) — shared light/material uniforms across draws
  • Vertex Array Objects (VAOs) — no more per-draw enableVertexAttribArray spam
  • Instanced drawingdrawElementsInstanced with per-instance attributes
  • Transform feedback — capture vertex output back into a buffer
  • Sampler objects — texture parameter state decoupled from textures
  • Occlusion & timer queriesANY_SAMPLES_PASSED, TIME_ELAPSED_EXT
  • Sync fencesfenceSync + clientWaitSync

Good for testing all the WebGL 2 tabs (Samplers, Queries, TransformFeedback, VAO) and state-tracker completeness.


Future Enhancements

Ideas we'd like to explore (contributions welcome):

  • Per-pixel shader debugging — tap a pixel in the replay preview to see every draw that contributed to it.
  • Depth / stencil visualization — toggles in the preview panel to render depth as grayscale or stencil as a heatmap.
  • Overdraw heatmap — render the frame with additive white so overdraw spots glow.
  • Wireframe / normal visualization — patch the shader mirror on the replay context to render just wireframes or normals without touching the host.
  • Network-style waterfall for textures — show when each texture was first uploaded, last modified, GPU memory footprint.
  • GPU-time queries — use EXT_disjoint_timer_query_webgl2 to get actual GPU time per draw.
  • Search across trace — free-text and regex filtering of the call list.
  • Persistent breakpoints — pause the running app on a specific gl.* call or on any error.
  • Diff two captured frames — show which calls / states / resources changed between runs.
  • CSV / CSV-with-binary export — in addition to JSON, export a compact timings CSV for external analysis.
  • Firefox / Safari extension ports — currently MV3 is Chromium-only; DevTools panels on other browsers need separate shimming.
  • WebGPU parallel — a sibling project that applies the same capture/inspect/replay model to WebGPU command encoders.

Credits & License

  • Inspired by and ported from benvanik/WebGL-Inspector (BSD-3-Clause © 2014 Ben Vanik). Huge thanks for the original design — this project wouldn't exist without it.
  • This fork is released under the MIT License — you're free to use, modify, and distribute it (including commercially) with minimal restrictions. Attribution to Ben Vanik's original work is preserved in the LICENSE file.

Commit history is intentionally verbose — every commit message explains why the change was made, not just what changed. Useful as a reading path if you want to understand how each feature evolved.

About

A modern, in-browser WebGL 1 & 2 inspector, debugger, and profiler.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors