npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

null-graph

v1.1.0

Published

A direct-to-GPU rendering framework for massive web worlds. Zero scene graph. Zero copy. Infinite scale.

Downloads

321

Readme

NullGraph

Zero scene graph. Zero copy. Infinite scale.

npm version npm downloads bundle size license stars

A Data-Oriented WebGPU rendering framework for massive web worlds.

NullGraph is a brutalist, high-performance rendering library designed specifically for Web Workers and Data-Oriented Design (DOD).

It completely abandons the traditional Object-Oriented Scene Graph (Root -> Node -> Mesh -> Geometry) in favor of mapping raw, contiguous ArrayBuffers directly to WebGPU Storage Buffers.

If you are building an MMO, a voxel engine, or a multiverse with tens of thousands of dynamic entities, NullGraph keeps rendering off your main thread and out of the garbage collector.


Why NullGraph?

A retained scene graph costs you a traversal, a matrix update, and a draw call per object, per frame — on the main thread, allocating as it goes. That is fine at a thousand objects and fatal at a hundred thousand: the frame time becomes a function of how much exists rather than how much is visible, and the garbage collector starts showing up in your frame graph.

NullGraph takes the opposite approach — it does less, and moves what remains to the GPU:

  • Zero Scene Graph: No .traverse(), no .updateMatrixWorld(). The GPU reads your flat array directly.

  • Zero-Copy Streaming: Calculate your ECS layout in a Web Worker, pass the Float32Array to the main thread, and blast it straight to VRAM.

  • Render Queues (Batches): Render thousands of unique object types simultaneously with minimal GPU state changes.

  • No GC Spikes: Memory is pre-allocated. No runtime object creation or destruction.

  • Compute-Driven Indirect Drawing: Offload culling entirely to the GPU. NullGraph supports WebGPU Compute Shaders that dynamically build IndirectDrawArgs, resulting in zero CPU overhead for visibility checks.

  • GPU-Driven Visibility (v1.0.5): Batteries-included culling on the GPU — frustum, Hi-Z occlusion, meshlet normal-cone (backface cluster) rejection, and screen-space-error LOD. Draw-call count becomes proportional to material count, not object count, so 100,000 instances still cost a handful of draws.

  • Shadows That Inherit the Culling: A shadow cascade is just another camera, so caster culling reuses the same GPU cull chain rather than duplicating it — 4 cascades over 100,000 instances is 4 indirect draws per caster mesh. Cached atlas tiles skip both their draw and their cull.

  • Dynamic Global Illumination: Not just an environment map — an irradiance volume filled by GPU probe capture, where each capture shades against the previous volume so bounce light accumulates into multi-bounce GI. Colour bleeding, indoor/outdoor transitions, and lighting that responds when you open a door — no ray tracing, no lightmap bake, no offline step.

  • Multi-Pass Architecture: Seamlessly chain offscreen render passes into screen-space post-processing pipelines (Bloom, CRT, HUD effects) by attaching textures directly to subsequent batches.


What's In The Box

A complete GPU-driven pipeline: geometry goes in as meshlets, the GPU decides what's visible, and the CPU never iterates the scene.

| Subsystem | What ships | |---|---| | Geometry | 13 primitives · one unified vertex/index pool · meshlet clusters (≤64v/≤124t) with bounds, normal cones, and LOD chains | | Visibility | Two-tier GPU culling (instance + meshlet) · Hi-Z occlusion from an r32float max-pyramid · normal-cone rejection · screen-space-error LOD · per-view culling for any camera | | Shadows | Cascaded shadow maps (sphere-fit, texel-snapped, caster-extruded) · shadow atlas with importance tiles, per-tile caching, and eviction · spot + point (6-face) shadows · light-view Hi-Z | | Lighting | 7 light types · clustered-forward froxel binning (subgroup-accelerated when available) · tiled · standard | | Indirect lighting | Split-sum IBL: GGX-prefiltered cube, BRDF LUT, SH-L2 irradiance · procedural or HDR sky · skybox pass | | Global illumination | SH-L1 irradiance volumes · GPU probe capture · multi-bounce convergence · parallax-corrected reflection probes | | Materials | PBR (Cook-Torrance), Lambert, Toon, Matcap, Emissive, Basic — one portable definition per family, shared by every draw path | | Post | 16 effects · lifetime-aliased render targets · zero-allocation param arena | | Platform | Worker rendering via OffscreenCanvas · capability negotiation · zero-copy buffer contracts throughout |

Three properties hold across all of it: draw calls scale with material count, not object count; the frame path allocates nothing (measured, not assumed); and the baseline runs on core WebGPU with no optional features required.

Verification status

Every subsystem is pinned by headless tests — 349 checks across five suites, covering the pure math, every generated WGSL module, and system wiring through mock devices. Run with npm run test:visibility · test:shadows · test:environment · test:geometry · test:post.

The GPU integration harnesses have not been run in a browser yet, and there is currently one only for shadows (test/shadows-gpu/). The maths is verified; the pixels are not. That is the next milestone, not a footnote.

Not in the box (yet)

Deferred / visibility-buffer shading · TAA and motion blur · volumetric fog · virtualized geometry (cluster-LOD streaming) · virtual shadow maps · leak-free DDGI probe visibility · compute skinning. All planned and specced — see the roadmap and architecture tree.


Installation and Setup

NullGraph is distributed as a modular ESM package. To maintain its "Zero-Copy" philosophy, it requires gl-matrix as a peer dependency to ensure your application and the engine share the same math structures.

1. Install via NPM

# Install the core engine
npm install null-graph

# Install required peer dependencies
npm install gl-matrix

# Recommended: Install WebGPU types for IDE autocomplete
npm install @webgpu/types --save-dev

2. Module Architecture

NullGraph uses Subpath Exports to keep your production bundles lean. You only pay for the features you import.

null-graph

The core engine: device and capability negotiation, buffer/texture management, and the linear executor. You hand render() a flat array of ComputeStageNode | RenderPassNode and it walks it in order — consecutive compute stages batch into one WebGPU pass, and a render pass closes it, which is where the compute→draw memory barrier comes from for free. Camera state is one 432-byte uniform (view/proj/their inverses + eye, near/far/fov/aspect) shared by every batch, and indirect draw is wired through: a batch flagged isIndirect is drawn with drawIndexedIndirect from a buffer a compute stage filled.

null-graph/geometry

13 primitive generators, declarative vertex layouts, and the two-layer buffer story: MegabufferBuilder packs every mesh into one vertex + index pool and records per-mesh {indexCount, firstIndex, baseVertex}; MeshletBuilder consumes that pool and partitions each mesh into ≤64-vertex / ≤124-triangle clusters, each with a bounding sphere and a normal cone, plus discrete LOD chains. Meshlets store global indices into the mega pool, so one vertex allocation backs both the coarse and fine draw paths.

null-graph/visibility

GPU-driven culling. Two tiers over the same substrate: instance-tier (one indirect draw per unique mesh, independent of instance count) and meshlet-tier (per-cluster, drawn by vertex pulling over a static index buffer, since WebGPU has no mesh shaders). A compute chain builds an r32float Hi-Z max-reduction pyramid from last frame's depth, then culls by frustum, normal cone, and occlusion, selects LOD by screen-space error, and compacts survivors into the indirect draw args. Nothing is read back to the CPU — dispatch sizes come from CPU-known caps with idle threads early-outing. The cull math has a CPU mirror (cullMath.ts) pinned by headless tests.

null-graph/shadows

Cascaded shadow maps with GPU caster culling. A cascade fills the same 108-float camera layout the cull and draw shaders already consume, so caster culling is the visibility chain pointed at a different uniform rather than new machinery. Cascades are fitted with a rotation-invariant bounding sphere and snapped to whole shadow texels (a box fit shimmers on camera yaw; an unsnapped centre crawls on translation), and the ortho near plane is extruded so off-screen casters still land in the map. Bias is applied on the caster in the depth-only vertex shader. Receiver-side it decorates the light system's WGSL — wrapping getIncidentLight and folding the shadow term into attenuation — so Lambert, Toon and PBR all gain shadows with no material edits.

null-graph/environment

Indirect lighting — the half of the lighting equation that isn't a light. Phase 1 replaces the hardcoded ambient constant with the split-sum IBL model: a GGX-prefiltered environment cube (with solid-angle mip selection, so a sun disc doesn't shatter into fireflies at mid roughness), a split-sum BRDF LUT, and an SH-L2 irradiance projection that fits in 27 floats instead of a cubemap — which is what leaves binding budget for Phase 2. Sources are an equirect HDR, a procedural sky (zero assets), or precomputed coefficients from a Worker.

Phase 2 makes it vary through space: an SH-L1 irradiance volume sampled by hardware trilinear filtering (the 8-probe blend is one textureSampleLevel), filled by GPU probe capture — the shadow atlas architecture rendered in colour, amortized at probesPerFrame. Because each capture shades against the previous volume, bounce light accumulates: multi-bounce global illumination that converges over a few refresh cycles, with no ray tracing and no second data structure. Local reflection probes with parallax-corrected box proxies handle specular, blending to the global cube so a scene with no probes degrades exactly to Phase 1.

Both phases implement the same two WGSL functions, so swapping global IBL for spatial probes costs zero material edits.

null-graph/loaders

GLBParser with resource unpacking, SkeletonManager, and an Animator for keyframe sampling and interpolation, feeding the vertex-shader skinning path in the material builders.

null-graph/materials

Basic, Lambert, Toon, Emissive, Matcap, and Cook-Torrance PBR. Each family is a portable pair — WGSL bindings plus an fs_main body, parameterized by bind-group index — from one source of truth, so the same material drops into a normal batch or a GPU-culled visibility batch unchanged. Lighting arrives as an injected WGSL layout (getVisibleLightCount / getIncidentLight), which is what lets the light system swap clustered for standard without any material knowing.

null-graph/lights

Data-oriented lighting: 7 proxy types writing into a flat 16-float-per-light array a Worker can fill, adopted by reference. Three techniques — standard, tiled-forward, and compute-driven clustered-forward, which bins lights into a 3D froxel grid (logarithmic depth slices) in a compute stage, using subgroup ops when the device negotiated them and an atomic baseline otherwise.

null-graph/post

An explicit, pre-allocated post chain. TransientPool aliases render targets by lifetime analysis so a 12-effect chain reuses a handful of textures, with history: 2 double-buffering reserved for temporal effects. ParamArena keeps every effect's uniforms in one arena with zero per-frame allocation, and ShaderComposer generates each pass's WGSL — 16 effects including Bloom, SSAO, Bokeh, FXAA, and tonemapping.

null-graph/cameras

Orbital, Fly, Follow, and Path controllers as pure state objects — spherical-coordinate math with no DOM dependency — plus optional event proxies, so the same controller runs on the main thread or inside a Worker.

null-graph/debug-ui & null-graph/profiler

Real-time telemetry widgets and WebGPU timestamp-query GPU profiling.


The Architecture Demo Suite

Play the Live Demo

nullgraph.dev

Github Source Code [v1.0.0]

NullGraph-Test-Engine


Documentation

For comprehensive guides and API references, please check our documentation:

Guides

Technical Designs

Implementation-ready specs. Each states its non-goals, cites the engine facts it depends on, and lists the acceptance tests up front.

API References

Roadmap

NullGraph is the high-performance rendering backbone for the Axion Engine.


Core Architecture

  • [x] Multi-Object Render Queue / Batching

  • [x] Depth / Z-Buffer Integration (Proper 3D occlusion)

  • [x] VBO/IBO Geometry Buffer Manager

  • [x] Multi-Pass Rendering & Texture Attachments

  • [x] GPU Compute Frustum Culling & Indirect Drawing

  • [x] Geometry Builder & null-graph/geometry extras

  • [x] Megabuffer (unified vertex/index pool) & Meshlet Builder (bounds, cones, LOD)

  • [x] GPU-Driven Visibility — two-tier culling (instance + meshlet), Hi-Z occlusion, screen-space-error LOD

  • [ ] Deferred / Visibility-Buffer Shading

  • [ ] Virtual Geometry (Nanite-style cluster-LOD DAG)


Materials & Assets

  • [x] Physically Based Rendering (Cook-Torrance BRDF)

  • [x] Integrated PBR Material System (Albedo, Normal, ARM maps)

  • [x] Native GLB/GLTF Parsing & Resource Unpacking

  • [x] Alpha Blending & Additive Transparency States


Animation & Logic

  • [x] Hardware-Accelerated Skeletal Animation (GPU Skinning)

  • [x] Animation Timeline & Keyframe Interpolation (Animator)

  • [ ] Morph Targets / Shape Keys

  • [ ] GPU-Driven Particle Systems (Compute-based)


Lighting & Post-Processing

  • [x] Dynamic Light System (Point / Directional / Spot) via Zero-Copy proxies

  • [x] Real-time Light Culling — Tiled (Forward+) & Compute-Driven Clustered Forward

  • [x] Post-Processing Pipeline (Bloom, SSAO, Tonemap, Custom Effects)

  • [x] Directional Shadows / Cascaded Shadow Maps (CSM) — sphere-fit cascades, texel snapping, GPU caster culling, hardware PCF

  • [x] Shadow Atlas — punctual (spot + point) shadows, importance-driven tiles, per-tile caching, light-view Hi-Z

  • [x] Image-Based Lighting (IBL) & Environment Mapping — GGX prefilter, split-sum BRDF LUT, SH-L2 irradiance, procedural + HDR sky

  • [x] Dynamic Global Illumination — SH-L1 irradiance volumes, GPU probe capture, multi-bounce convergence, parallax-corrected reflection probes

  • [ ] DDGI per-probe visibility (leak-free probes) — needs bind-group budget reclaimed

  • [ ] Volumetric fog & atmospheric scattering


Showcase

Architecture Demos

| AoS | SoA | AoSoA | |:---------------------------------------------------:|:---------------------------------------------------:|:-----------------------------------------------------:| | | | |

GPU Compute & Post-Processing

| GPU Culling | Space Fleet | CRT Effect | |:----------------------------------------------------------:|:----------------------------------------------------------:|:----------:| | | |

PBR Materials & Animation

| Rusty Metal | Skeletal Animation | Morphogenesis | |:-----------------------------------------------------------:|:-------------------------------------------------------------------------:|:-------------------------------------------------------------:| | | | |


📦 Package Stats

| Metric | Value | |--------|-------| | Weekly Downloads | npm | | Version | npm | | License | license | | Minified + GZip | size |


🔗 Related Repositories

| Repository | Description | |--------------------------------------------------------------------------------------|-------------| | NullGraph Test Engine | Interactive demo suite & documentation hub | | Axion Engine | Full game engine built on NullGraph |