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

lem3d-webgpu

v1.2.4

Published

A high-performance, lightweight instanced rendering engine with real-time shadow mapping and dynamic physics helpers built purely on WebGPU.

Readme

🪐 Lem3D WebGPU Engine

Lem3D is a highly-optimized, lightweight, zero-dependency WebGPU 3D Engine Library built with modern TypeScript. Designed specifically for ultra-performance web delivery and hardware-instanced rendering workflows, Lem3D empowers you to develop high-fidelity, real-time 3D interactive graphics, character skeletons, and custom shader simulations directly utilizing next-generation GPU hardware layers.


🚀 Key Features

  • Built for WebGPU (Next-Gen Graphics): Leverages Vulkan, Metal, and DirectX 12 hardware layers under the hood via the browser's native navigator.gpu APIs.
  • Dynamic GPU Instancing Out-of-the-Box: Draw thousands of complex meshes with custom transformations and colors in a single draw call.
  • Real-Time Dynamic Shadow Mapping: Multi-pass projection rendering complete with hardware PCF (Percentage-Closer Filtering) shadow comparison samplers built directly into active pipeline structures.
  • Bone Skeleton Node Mapper: Renders interconnected joint hierarchies with automatic intermediate spline interpolations and clean joints.
  • Live Input Engine & Delta-Ticks: Built-in keyboard state recorders (engine.keys) and high-resolution frame delta time calculations (engine.deltaTime) for frame-rate independent physics/movement.
  • Hot-Swappable WGSL Shaders: Dynamically inject, validate, compile, and reload custom WGSL fragment and vertex shaders on the fly with live syntax-level debug diagnostics.
  • Integrated High-Performance Geometries: Built-in standard mathematical helpers to generate UV-mapped spheres, cylinders, boxes, capsules, rounded boxes, and custom interactive grids.
  • Third-Person Orbit Camera System: Automatic polar coordinate orbital camera controls supporting target-tracking, smooth movement interpolation (lerp), aspect ratio correction, and depth handling.
  • Vite & React Ready: Built-in lazy state hooks (useWebGPUEngine) for elegant framework bindings.

📦 Installation & Integration

Traditional HTML UMD Script Tag

Include Lem3D in your static HTML page from jsDelivr:

<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/lem3d.umd.js"></script>

Modern ES Modules (ESM CDN)

Directly import using the modern browser package standard:

import { Lem3D, WebGPUEngine } from 'https://cdn.jsdelivr.net/npm/[email protected]/dist/lem3d.esm.js';

Package Registry Installation (npm/yarn/pnpm)

Install the core package into your modern bundler/framework projects:

npm install lem3d-webgpu gl-matrix

🚀 Quick Start Guides

1. React Setup with useWebGPUEngine

Integrate the engine into a viewport component using the built-in React hook helper:

import React, { useEffect } from 'react';
import { useWebGPUEngine, WebGPUMesh, createSphereGeometry } from 'lem3d-webgpu';
import { mat4, vec3 } from 'gl-matrix';

export default function RenderCanvas() {
  const { canvasRef, engine, isSupported } = useWebGPUEngine({ debug: true });

  useEffect(() => {
    if (!engine) return;

    // Create high-polygon UV-mapped sphere geometry (radius, radial segments, vertical rings)
    const sphereGeometry = createSphereGeometry(1.0, 32, 24);
    
    // Allocate GPU buffers for up to 500 instances
    const instanceCap = 500;
    const sphereMesh = new WebGPUMesh(engine.device, sphereGeometry, instanceCap);

    // Register mesh to engine drawing list
    engine.meshes = [sphereMesh];

    let rot = 0;
    const tick = () => {
      // Accumulate time scaling factor
      rot += engine.deltaTime * 0.4;

      const instances = [];
      const numCubes = 15;
      
      for (let i = 0; i < numCubes; i++) {
        const transform = mat4.create();
        const heightOffset = Math.sin(rot + i * 0.5) * 1.5;
        
        // Dynamic position, rotation, and scale matrices
        mat4.translate(transform, transform, [i * 2.5 - (numCubes * 1.25), heightOffset, 0]);
        mat4.rotateY(transform, transform, rot);
        mat4.scale(transform, transform, [0.8, 0.8, 0.8]);

        instances.push({
          transform,
          color: new Float32Array([0.15, 0.4 + (i / numCubes) * 0.5, 0.9])
        });
      }

      // Buffer instancing data onto GPU instantly
      sphereMesh.updateInstances(instances);

      // Tell camera to follow the origin center point smoothly
      engine.camera.updateFollowTarget(vec3.fromValues(0, 0, 0));
    };

    // Frame loops registered automatically under the requestAnimationFrame engine tick
    const renderLoop = () => {
      tick();
      if (engine.isRunning) {
        requestAnimationFrame(renderLoop);
      }
    };
    
    requestAnimationFrame(renderLoop);
  }, [engine]);

  if (!isSupported) {
    return <div className="p-4 text-red-500 bg-neutral-900 border border-red-500/30 rounded">WebGPU is not supported in this browser.</div>;
  }

  return (
    <canvas 
      ref={canvasRef} 
      className="w-full h-full block bg-neutral-950" 
      style={{ touchAction: 'none' }}
    />
  );
}

2. Vanilla TypeScript Setup

Initialize the WebGPU core pipelines directly from clear HTML canvases:

import { WebGPUEngine, WebGPUMesh, createBoxGeometry } from 'lem3d-webgpu';
import { mat4 } from 'gl-matrix';

async function initSandbox() {
  const canvas = document.getElementById('render-canvas') as HTMLCanvasElement;
  const engine = new WebGPUEngine({ canvas, debug: true });

  const isSuccess = await engine.init();
  if (!isSuccess) {
    throw new Error("WebGPU initialization failed.");
  }

  // Create a box geometry
  const boxGeometry = createBoxGeometry(1.5, 1.5, 1.5);
  const boxMesh = new WebGPUMesh(engine.device!, boxGeometry, 100);
  engine.meshes = [boxMesh];

  // Specify instanced positioning
  const transform = mat4.create();
  mat4.translate(transform, transform, [0, 0, 0]);
  boxMesh.updateInstances([
    {
      transform,
      color: new Float32Array([0.9, 0.2, 0.3])
    }
  ]);

  // Start the internal requestAnimationFrame canvas loops
  engine.start();
}

window.addEventListener('DOMContentLoaded', initSandbox);

🛠️ API Reference

1. WebGPUEngine

The primary layout coordinator and coordinator of adapter devices, render passes, and shade pipelines.

interface EngineOptions {
  canvas: HTMLCanvasElement;
  debug?: boolean; // Toggles verbose debug logging on device boundaries
}

Core Properties:

| Property | Type | Description | |---|---|---| | canvas | HTMLCanvasElement | The viewport target element on the current DOM. | | adapter | GPUAdapter \| null | Represents physical GPU adapters loaded via navigator.gpu. | | device | GPUDevice \| null | Represents active logical GPU connection. | | camera | WebGPUCamera | Built-in third-person orbital target tracking camera. | | meshes | WebGPUMesh[] | Array of instanced meshes currently in the active render registry. | | clearColor | { r, g, b, a } | Scene background clearing color. Default: { r: 0.05, g: 0.05, b: 0.08, a: 1.0 }. | | lightDir | Float32Array | Normal directional vectors mapping standard light paths (e.g., [0.5, 1.0, 0.3]). | | keys | Record<string, boolean> | Live dictionary containing current keyboard state trackers (WASD / arrows). | | deltaTime | number | Frame-rate independent delta scaling multiplier (seconds elapsed since last tick). |

Core Methods:

  • engine.init(): Promise<boolean>: Requests core physical adapters/devices from browser context, configures target canvas contexts, initializes dynamic shadow pass variables, depth texture pipelines, and WGSL drawing shaders.
  • engine.start(): Sets rendering pipeline to active and triggers recursive requestAnimationFrame ticks.
  • engine.stop(): Halts render pipeline updates.
  • engine.handleResize(): Auto-resizes active high-depth buffers and projection aspects to prevent visual distortion.
  • engine.compileCustomShader(fragmentShaderSource: string): Promise<{ success: boolean; error?: string }>: Dynamically compiles, checks and mounts a WGSL shader code stream to modify meshes in real-time.
  • engine.getMetrics(): Returns key rendering parameters instantly:
    {
      fps: number,
      drawCalls: number,
      totalInstances: number
    }

2. WebGPUCamera

An elegant orbital tracker utilizing polar angles (yaw/pitch) with smooth target tracking and mouse/wheel bindings.

Core Properties:

| Property | Type | Default | Description | |---|---|---|---| | distance | number | 45.0 | Target distance from focal tracking object. | | orbitAngle | number | 0.0 | Radial orbital polar yaw angle. | | pitchAngle | number | 0.6 | Horizontal orbital polar pitch angle (clamped from -1.4 to 1.4). | | smoothSpeed | number | 0.15 | Interpolation dampening coefficient (0 to 1). | | viewMatrix | Float32Array | mat4.create() | Active computed transforms mapping cameras in 3D scene grids. |

Core Methods:

  • camera.updateFollowTarget(targetPos: vec3): Smoothly lerps view target matrices towards coordinate points, preserving polar orbiting distances.
  • camera.handleMouseDown(clientX: number, clientY: number): Activates camera orientation rotation sequences.
  • camera.handleMouseMove(clientX: number, clientY: number): Interpolates trackball differentials to change angles.
  • camera.handleWheel(deltaY: number): Alters orbital focal distances instantly.

3. WebGPUMesh

Translates standard geometric vertices and indexes and handles GPU buffer instancing under single rendering passes.

import { WebGPUMesh } from 'lem3d-webgpu';

const mesh = new WebGPUMesh(device: GPUDevice, geometry: Geometry, maxInstances: number);

Structs & Typedefs:

interface Geometry {
  vertices: Float32Array; // Arranged as sets of: [x, y, z, nx, ny, nz, u, v]
  indices: Uint16Array;   // Index triangles matching CCW winding rules
}

interface InstanceData {
  transform: Float32Array;  // Mat4 translation-rotation-scale matrices (16 elements)
  color: Float32Array;      // RGB instance-specific parameters (3 elements)
}

Core Methods:

  • mesh.updateInstances(instances: InstanceData[]): Copies transformation matrices and color components straight to instancing arrays inside local GPU vertex buffers over active shader pipelines.

4. Advanced Geometry Generatives (lem3d-webgpu/geometry)

Core procedural model templates that instantly output vertex coordinates, indices, and normals:

import { 
  createSphereGeometry, 
  createCylinderGeometry, 
  createBoxGeometry, 
  createRoundedBoxGeometry, 
  createCapsuleGeometry, 
  createGridGeometry 
} from 'lem3d-webgpu/geometry';
  • SpherecreateSphereGeometry(radius: number, widthSegments?: number, heightSegments?: number)
  • CylindercreateCylinderGeometry(radiusTop: number, radiusBottom: number, height: number, radialSegments?: number)
  • Box (Cube)createBoxGeometry(width: number, height: number, depth: number)
  • Rounded Box (Chamfered)createRoundedBoxGeometry(width: number, height: number, depth: number, radius?: number, subdivisions?: number)
  • Capsule (Capped Cylinder)createCapsuleGeometry(radius: number, height: number, radialSegments?: number, heightSegments?: number)
  • Grid Help Ground PlanecreateGridGeometry(sizeX: number, sizeZ: number, subX: number, subZ: number)

🦴 Skeletal Animation & Interpolated Node Mapper

The core repository contains advanced utilities for interconnected joint systems and character rigs (e.g. canine, human, chibi, spiders). By referencing rigid node structures, the engine renders skeletal chains and interpolates joints dynamically:

// Auto-interpolating intermediate joint nodes in the Lem3D 3D Bone Node Mapper:
if (bone.parentName) {
  const parentBone = rig.getBone(bone.parentName);
  if (parentBone) {
    const startPos = vec3.create();
    const endPos = vec3.create();
    mat4.getTranslation(startPos, parentBone.worldMatrix);
    mat4.getTranslation(endPos, bone.worldMatrix);

    // Creates multiple tapered spheres between nodes for organic skeletal connections
    const numIntermediates = 4;
    for (let i = 1; i <= numIntermediates; i++) {
      const t = i / (numIntermediates + 1);
      const lerpedPos = vec3.create();
      vec3.lerp(lerpedPos, startPos, endPos, t);
      
      // Compute tapering scale, pitch quaternions, and color gradients to inject
    }
  }
}

🎨 Custom WGSL Shader Architecture

When developers write custom fragment shader code inside visual code pipelines, the canvas compiles raw assets directly under compliant WGSL structures containing high-precision shadow passes.

Direct Shader Pipeline Layout:

The shader receives global uniform mappings automatically under custom group and binding indexes:

struct CameraUniforms {
    viewProj: mat4x4<f32>,
    viewPos: vec3<f32>,
    lightSpaceMatrix: mat4x4<f32>,
    lightDir: vec3<f32>,
};

@group(0) @binding(0) var<uniform> camera: CameraUniforms;
@group(1) @binding(0) var shadowMap: texture_depth_2d;
@group(1) @binding(1) var shadowSampler: sampler_comparison;

struct VertexOutput {
    @builtin(position) position: vec4<f32>,
    @location(0) worldPos: vec3<f32>,
    @location(1) normal: vec3<f32>,
    @location(2) lightSpacePos: vec4<f32>,
    @location(3) color: vec3<f32>,
};

// Complete Fragment Example incorporating PCF Shadow Checking and ambient blending:
@fragment
fn fs_main(in: VertexOutput) -> @location(0) vec4<f32> {
    let N = normalize(in.normal);
    let L = normalize(camera.lightDir);
    
    // Evaluate shadow coordinate ratios using Depth PCF comparisons
    let projCoords = in.lightSpacePos.xyz / in.lightSpacePos.w;
    let flipY = vec3<f32>(
        projCoords.x * 0.5 + 0.5,
        projCoords.y * -0.5 + 0.5,
        projCoords.z
    );
    
    let shadowSample = textureSampleCompare(shadowMap, shadowSampler, flipY.xy, flipY.z - 0.0035);
    let inBounds = flipY.x >= 0.0 && flipY.x <= 1.0 && flipY.y >= 0.0 && flipY.y <= 1.0 && flipY.z <= 1.0;
    let shadow = select(1.0, shadowSample, inBounds);
    
    // Phong diffuse reflection equation
    let diffuse = max(dot(N, L), 0.0);
    
    // Ambient fallback + dynamic shadow diffuse scaling
    let lighting = 0.28 + diffuse * shadow * 0.72;
    let shadedColor = in.color * lighting;
    
    // Smooth organic edge fog mapping
    return vec4<f32>(shadedColor, 1.0);
}

⚙️ Requirements & Browser Support

  • Browser Contexts: Modern browsers with standard WebGPU integrations enabled.
    • Chrome / Edge / Opera (Version 113+)
    • Firefox (With dom.webgpu.enabled flipped to true in about:config)
    • Safari (Technology Preview with WebGPU toggled under Developer settings)
  • Local Context Check: Always verify standard compatibility before running code loops:
    if (!navigator.gpu) {
      console.warn("Navigator standard WebGPU interface is unavailable. Try Chrome / Edge.");
    }

🚀 Troubleshooting, HMR & Build Optimization

  1. "GPUAdapter is not found / defined" Error
    • Cause: WebGPU is strictly secured to secure HTTPS pipelines or local loopbacks (localhost, 127.0.0.1). If you reside on an external staging environment, verify you utilize an SSL certified entry domain.
  2. Infinite Re-render canvas flickering during HMR (Hot Module Replacement)
    • Cause: Vite's cold HMR swaps module code blocks while retaining background contexts which breaks canvas bindings.
    • Solution: Handle proper cleanup inside your component hook returns to release CPU resources.
      useEffect(() => {
        return () => {
          if (engine) {
            engine.stop();
            // Unbind global event listeners to clear resources
          }
        };
      }, [engine]);
  3. Out-of-memory errors on extensive rigs
    • Cause: WebGPU requires allocating static buffer pools inside WebGPUMesh declarations.
    • Solution: Pre-allocate generous instance limits (e.g. maxInstances = 2000) instead of calling small dynamic capacities in rendering ticks.

📄 License

This library is distributed under the premium, open-source MIT License. Check individual folders for auxiliary information.