# 🪐 Lem3D WebGPU Engine — v1.2.5

`Lem3D` is a highly-optimized, lightweight, zero-dependency **WebGPU 3D Engine Library** built with modern TypeScript. Engineered specifically for next-generation web platforms, hardware-instanced rendering workflows, and high-performance interactive graphics, `Lem3D` maps directly to modern low-level GPU hardware layers (Vulkan, Metal, and DirectX 12) through the native browser WebGPU standard.

This guide provides a comprehensive architectural overview, extensive API specifications, deep-dives into mathematical primitives, and rich production-ready code examples to get you up and running with custom shader systems, instanced physics, and skeletal rigs.

---

## 🚀 Architectural Advantages of WebGPU & Lem3D

WebGPU represents the most significant leap in web graphics in over a decade, shifting away from the high-overhead, single-threaded CPU bottleneck state machine of WebGL to an asynchronous, multi-threaded-friendly command queue model.

### ⚡ Why WebGPU & Lem3D Excel:
- **Zero-Allocation Draw Calls**: With **GPU Instancing**, `Lem3D` binds a mesh's static geometry buffer *once*, then feeds transform matrices and color components via a fast instanced vertex buffer. This allows drawing tens of thousands of complex shapes in a single draw call with virtually zero CPU overhead.
- **Explicit Memory Management**: No garbage collection hiccups. GPU buffers and bind groups are allocated deterministically and updated directly using host-shared memory writes (`device.queue.writeBuffer`).
- **Native Compute & Multi-Pass pipelines**: `Lem3D` integrates a built-in multi-pass setup out of the box, utilizing a **Shadow Depth Pass** to render a high-precision directional depth map, which is then sampled using hardware comparison samplers for smooth Percentage-Closer Filtering (PCF) shadows in the main Forward Pass.
- **Pre-Compiled WGSL Pipeline States**: Shaders are written in **WebGPU Shading Language (WGSL)**, providing strong typing, robust math operators, and pre-compiled pipeline state objects (PSOs) for stutter-free frame-rate rendering.

---

## 📦 Installation & Setup

### 1. Modern CDN Integration (ESM)
Directly load `Lem3D` inside any modern browser without a bundler using native ES Module imports:
```javascript
import { Lem3D, WebGPUEngine, createSphereGeometry } from 'https://cdn.jsdelivr.net/npm/lem3d-webgpu@1.2.5/dist/lem3d.esm.js';
```

### 2. Traditional Script Tag (UMD)
For classic, non-module environments, load the global UMD bundle:
```html
<script src="https://cdn.jsdelivr.net/npm/lem3d-webgpu@1.2.5/dist/lem3d.umd.js"></script>
<script>
  // Access via the global window namespace
  const engine = new Lem3D.WebGPUEngine({ canvas: document.getElementById('gl-canvas') });
</script>
```

### 3. Package Registry Installation (Bundler-ready)
To integrate with React, Svelte, Vue, or vanilla bundlers (Vite, Webpack), install via npm:
```bash
npm install lem3d-webgpu gl-matrix
```

Make sure your environment supports TypeScript type declarations (`@webgpu/types`) for compilation-time static analysis.

---

## 🏛️ Rendering Loop Lifecycle & Core Classes

`Lem3D` divides responsibility among three core pillars: `WebGPUEngine` (graphics setup and command scheduler), `WebGPUCamera` (orbital viewport coordinator), and `WebGPUMesh` (GPU resource container and instanced model mapper).

```
   [Browser Tick (requestAnimationFrame)]
                  │
                  ▼
         [WebGPUEngine.tick()]
                  │
      ┌───────────┴───────────┐
      ▼                       ▼
[Shadow Pass (Depth)]   [Forward Pass (Color)]
  - Bind Shadow Pipeline   - Bind Main Pipeline
  - Loop meshes & draw     - Bind Camera Uniforms
  - Write depth texture    - Bind Shadow Texture Map
                           - Loop meshes, apply instancing, & draw
```

---

## 🛠️ Complete Class API Reference

### 1. `WebGPUEngine`
The primary layout controller that initializes adapters, devices, depth textures, shadow maps, and manages the drawing execution loop.

```typescript
import { WebGPUEngine } from 'lem3d-webgpu';

const engine = new WebGPUEngine({
  canvas: myCanvasElement,
  debug: true // Enables verbose device logging & shader compilation tracking
});
```

#### Key Fields:
| Field | Type | Default | Description |
| :--- | :--- | :--- | :--- |
| `canvas` | `HTMLCanvasElement` | *Required* | Target canvas viewport in the DOM. |
| `device` | `GPUDevice \| null` | `null` | Active logical connection to the physical GPU. |
| `camera` | `WebGPUCamera` | `new WebGPUCamera()` | Third-person orbital polar target-following camera. |
| `meshes` | `WebGPUMesh[]` | `[]` | List of instanced meshes drawn during the rendering pass. |
| `lightDir` | `Float32Array` | `[0.5, 1.0, 0.3]` | Direct light path vector (normalized internally). |
| `clearColor` | `GPUColor` | `{r: 0.05, g: 0.05, b: 0.08, a: 1.0}` | RGB background clear color. |
| `keys` | `Record<string, boolean>` | `{}` | Live dictionary logging currently pressed keys. |
| `deltaTime` | `number` | `0.0` | High-precision tick time difference in seconds. |

#### Key Methods:
- `init(): Promise<boolean>`  
  Asynchronously queries physical GPUDevices, configures the Canvas context with the native swap chain format (usually `bgra8unorm`), configures depth/stencil buffers, allocates a high-precision `2048x2048` shadow map texture, compiles WGSL source strings, and binds rendering pipelines. Returns `true` if initialization succeeded.
- `start(): void`  
  Spins up the internal recursive `requestAnimationFrame` loop.
- `stop(): void`  
  Halts the animation loop.
- `handleResize(): void`  
  Recomputes the canvas bounding rect, updates WebGPU projection matrices with the corrected aspect ratio, and rebuilds depth textures to avoid visual stretching.
- `compileCustomShader(fragmentShaderSource: string): Promise<{ success: boolean; error?: string }>`  
  Compiles a custom WGSL fragment shader on the fly. Dynamically updates pipeline bindings without stopping or dropping active meshes.
- `getMetrics(): { fps: number; drawCalls: number; totalInstances: number }`  
  Instantly returns CPU/GPU statistics regarding rendering efficiency.

---

### 2. `WebGPUCamera`
A polar-coordinate camera (`yaw` and `pitch`) revolving around a moving focus target. Supports smooth target tracking, automatic field-of-view (FOV) aspect updates, and desktop/touch drag listeners.

#### Key Fields:
| Field | Type | Default | Description |
| :--- | :--- | :--- | :--- |
| `distance` | `number` | `45.0` | Radial distance from target focus point. |
| `orbitAngle` | `number` | `0.0` | Polar Yaw angle in radians around the Y axis. |
| `pitchAngle` | `number` | `0.6` | Polar Pitch angle in radians, clamped from `-1.4` to `1.4`. |
| `smoothSpeed` | `number` | `0.15` | Interpolation factor (0 to 1) for target-following damping. |
| `target` | `vec3` | `[0, 0, 0]` | Current dynamic center focus vector. |

#### Key Methods:
- `updateFollowTarget(targetPos: vec3): void`  
  Smoothly interpolates the internal camera target focus vector toward `targetPos` using:
  $$\text{target} = \text{target} + (\text{targetPos} - \text{target}) \times \text{smoothSpeed}$$
- `handleMouseDown(clientX: number, clientY: number): void`  
  Locks orbital drag trackers.
- `handleMouseMove(clientX: number, clientY: number): void`  
  Calculates cursor position deltas and adjusts `orbitAngle` and `pitchAngle` accordingly.
- `handleWheel(deltaY: number): void`  
  Modifies orbital focal `distance` (zooming in or out).

---

### 3. `WebGPUMesh`
A self-contained resource binder that contains a static set of vertex geometries and pushes instance color and layout coordinate components straight to GPU buffers.

```typescript
import { WebGPUMesh, createBoxGeometry } from 'lem3d-webgpu';

const maxInstances = 1000;
const geom = createBoxGeometry(1.0, 1.0, 1.0);
const mesh = new WebGPUMesh(engine.device, geom, maxInstances);
```

#### Key Fields:
| Field | Type | Description |
| :--- | :--- | :--- |
| `vertexBuffer` | `GPUBuffer` | Contains static coordinate floats `[px, py, pz, nx, ny, nz, u, v]`. |
| `indexBuffer` | `GPUBuffer` | Contains static triangle indices. |
| `instanceBuffer`| `GPUBuffer` | Contains instance transforms (16-float matrices) and RGB color vectors (3-floats). |
| `instanceCount` | `number` | Active count of instances to draw on this frame. |

#### Key Methods:
- `updateInstances(instances: { transform: mat4; color: Float32Array }[]): void`  
  Accepts a list of transformation matrices and RGB color components. Marshals the array into sequential flat binary streams and uses `queue.writeBuffer` to rewrite instance variables directly inside GPU VRAM, ready for the next vertex fetch stage.

---

## 📐 Procedural Primitives (18 Shapes)

`Lem3D` includes a robust procedural model generation suite. To ensure compatibility with backface culling pipelines, all generators output triangle indices in **Counter-Clockwise (CCW)** winding order. Vertex fields are structured inside a single interleaved flat float array: `[px, py, pz, nx, ny, nz, u, v]`.

```typescript
// Shared geometry signature
interface Geometry {
  vertices: Float32Array; // Set of: px, py, pz, nx, ny, nz, u, v
  indices: Uint16Array;   // 16-bit indices for index drawing
}
```

### Primitives Reference:

#### 1. Sphere — `createSphereGeometry(radius, widthSegments, heightSegments)`
- **Formula**: Coordinates calculated by sweeping polar yaw/pitch angles over spherical coordinates:
  $$x = -r \cos(\theta)\sin(\phi), \quad y = r \cos(\phi), \quad z = r \sin(\theta)\sin(\phi)$$
- **Example**: `createSphereGeometry(1.0, 32, 24)`

#### 2. Cylinder — `createCylinderGeometry(radiusTop, radiusBottom, height, radialSegments)`
- **Formula**: Sweeps circle parameters along a central vertical axis, adding circular caps on the top and bottom. Set `radiusTop = 0` to create a perfect cone with side-normal splits.
- **Example**: `createCylinderGeometry(0.5, 0.5, 2.0, 16)`

#### 3. Box (Cube) — `createBoxGeometry(width, height, depth)`
- **Formula**: Outputs a clean 6-sided box structure. Face vertices are explicitly split (duplicated) to guarantee sharp, clean lighting normal edges.
- **Example**: `createBoxGeometry(1.5, 1.5, 1.5)`

#### 4. Rounded Box — `createRoundedBoxGeometry(width, height, depth, radius, subdivisions)`
- **Formula**: Blends flat box side coordinates with spherical corner projections. Softens sharp edges with a customizable chamfer radius.
- **Example**: `createRoundedBoxGeometry(1.2, 1.2, 1.2, 0.15, 8)`

#### 5. Capsule — `createCapsuleGeometry(radius, height, radialSegments, heightSegments)`
- **Formula**: Creates a cylindrical mid-section capped with two hemispherical domes on the top and bottom. Perfect for collision bounds or character hulls.
- **Example**: `createCapsuleGeometry(0.4, 1.2, 16, 8)`

#### 6. Holographic Grid — `createGridGeometry(sizeX, sizeZ, subX, subZ)`
- **Formula**: Constructs an orthogonal mesh layout of wireframe segments on the XZ plane. Ideal for terrain systems, spatial guidelines, or digital planes.
- **Example**: `createGridGeometry(20.0, 20.0, 10, 10)`

#### 7. Cone — `createConeGeometry(radius, height, radialSegments)`
- **Formula**: Generates a conical geometry with a sharp top apex and a flat circular bottom base.
- **Example**: `createConeGeometry(0.8, 1.8, 24)`

#### 8. Torus — `createTorusGeometry(radius, tube, radialSegments, tubularSegments)`
- **Formula**: Sweeps a circular tube ring along a major planar circle tracking coordinate path:
  $$x = (R + r \cos(v)) \cos(u), \quad y = r \sin(v), \quad z = (R + r \cos(v)) \sin(u)$$
- **Example**: `createTorusGeometry(1.0, 0.3, 16, 32)`

#### 9. Plane — `createPlaneGeometry(width, height)`
- **Formula**: Generates a flat 2D quad canvas centered on the XY plane. Perfect for billboards, user interfaces, or ground decals.
- **Example**: `createPlaneGeometry(2.0, 2.0)`

#### 10. Pyramid — `createPyramidGeometry(width, height, depth)`
- **Formula**: Generates a classic 4-sided pyramid with a flat rectangular bottom base.
- **Example**: `createPyramidGeometry(1.4, 1.6, 1.4)`

#### 11. Prism — `createPrismGeometry(width, height, depth)`
- **Formula**: Creates an extruded, tapered pentagonal prism with clean, flat side panels and cap lids.
- **Example**: `createPrismGeometry(1.0, 1.5, 1.0)`

#### 12. Torus Knot — `createTorusKnotGeometry(radius, tube, tubularSegments, radialSegments, p, q)`
- **Formula**: Sweeps vertices along a mathematical self-weaving knot path wrapped around a torus, defined by the coprimality integers $p$ and $q$.
- **Example**: `createTorusKnotGeometry(1.0, 0.25, 64, 12, 2, 3)`

#### 13. Procedural Flat Disk — `createDiskGeometry(innerRadius, outerRadius, segments)`
- **Formula**: Generates a flat 2D annular ring on the XZ plane ($y=0$) with concentric coordinates and clean upward normals:
  $$x = r \cos(\theta), \quad y = 0, \quad z = r \sin(\theta) \quad (\text{for } r \in [R_{\text{inner}}, R_{\text{outer}}])$$
- **Example**: `createDiskGeometry(0.4, 1.3, 32)`

#### 14. Procedural Bicone — `createBiconeGeometry(radius, height, segments)`
- **Formula**: Fuses two cones base-to-base along the central vertical axis, creating a sharp crease at the waist.
- **Example**: `createBiconeGeometry(1.0, 1.6, 32)`

#### 15. Truncated Icosahedron — `createTruncatedIcosahedronGeometry(radius)`
- **Formula**: Slices the 12 corners of a regular icosahedron to create a semi-regular Archimedean solid with 12 pentagons and 20 hexagons (classic soccer ball geometry). Features flat, face-centric normal shading.
- **Example**: `createTruncatedIcosahedronGeometry(1.25)`

#### 16. Mathematical 3D Heart — `createHeartGeometry(scale)`
- **Formula**: Evaluates a parametric 3D heart equation using spherical coordinates, with numerical approximations for smooth normal vectors:
  $$x = \sin(u)\sin^3(v), \quad y = \sin(u)\left(13\cos(v) - 5\cos(2v) - 2\cos(3v) - \cos(4v)\right)/16, \quad z = \cos(u) \times s$$
- **Example**: `createHeartGeometry(1.0)`

#### 17. Corrugated Wavy Ribbon — `createWavyRibbonGeometry(width, length, waves, amplitude)`
- **Formula**: Generates a waving corrugated ribbon along the Z-axis, calculated via sinusoidal wave paths:
  $$y = \sin\left(\frac{z \times w \times 2\pi}{l}\right) \times A$$
- **Example**: `createWavyRibbonGeometry(1.6, 1.6, 3, 0.25)`

#### 18. Procedural Teardrop — `createTeardropGeometry(radius, height)`
- **Formula**: Generates an organic teardrop profile by tapering a sphere's top along its vertical axis before sweeping it:
  $$y = \frac{h}{2} \cos(t), \quad r = R \sin(t)\left(1.0 - 0.65\cos(t)\right)$$
- **Example**: `createTeardropGeometry(0.9, 1.8)`

---

## 🏰 Pre-Assembled Composite Prefabs (8 Assets)

Prefabs are compiled by merging multiple primitive geometries together using a high-performance CPU-side transformation and geometry-merging pipeline.

```typescript
// Shared prefab signature
export function createMyPrefab(): Geometry;
```

### Prefab Catalog:

#### 1. Cyber Pine Tree — `createPineTreePrefab()`
- **Components**: 1 trunk cylinder + 3 overlapping cone canopies.
- **Visuals**: A clean stylized pine tree, ideal for nature-focused environments or outdoor game worlds.

#### 2. Modular Castle Tower — `createCastleTowerPrefab()`
- **Components**: 1 thick core cylinder + 1 torus detail belt + 4 box crenel battlements.
- **Visuals**: A modular defensive tower, suitable for medieval environments, castle walls, and fortresses.

#### 3. Orbital Space Station — `createSpaceStationPrefab()`
- **Components**: 1 living outer torus ring + 1 central cylinder core shaft + 4 flat solar panel arrays.
- **Visuals**: A high-tech space habitat, perfect for deep space simulations and celestial backdrops.

#### 4. Cyber Sentinel Drone — `createRobotDronePrefab()`
- **Components**: 1 center sphere hull + 2 camera cylinder lenses + 2 cylindrical thruster pods + 2 rectangular ski landing rails.
- **Visuals**: A floating security sentinel drone, complete with details for sci-fi and industrial scenes.

#### 5. High-Tech Quadcopter Drone — `createQuadcopterPrefab()`
- **Components**: 1 flat capsule core + 1 camera gimbal sphere + 4 diagonal structural cylinder strut legs + 4 motor cylinders + 4 double-bladed thin box propellers.
- **Visuals**: A highly authentic quadcopter asset with detailed rotor assemblies, perfect for flight simulation or robotic overlays.

#### 6. Ancient Medieval Water Well — `createWaterWellPrefab()`
- **Components**: 1 wide brickwork wall cylinder + 1 torus trim ring + 2 upright wood support posts + 1 horizontal cylinder crank beam + 1 four-sided peaked cone roof + 1 mini-bucket cylinder.
- **Visuals**: An atmospheric historical medieval well asset, rich in detail.

#### 7. Deep Space Satellite Orbiter — `createSatellitePrefab()`
- **Components**: 1 central cubic electronics body + 2 massive segmented solar panel wings + 2 horizontal connecting struts + 1 front-facing high-gain communications dish cone + 1 forward antenna pointing rod + 1 vertical telemetry antenna rod.
- **Visuals**: An advanced satellite receiver asset, great for orbital space scenes.

#### 8. Industrial Steam Train Locomotive — `createTrainLocomotivePrefab()`
- **Components**: 1 horizontal boiler cylinder + 1 cubic rear cabin box + 1 thin cabin roof overhang + 1 vertical exhaust smokestack + 1 front conical wedge cowcatcher + 6 rotated cylinder drive wheels (3 on each side).
- **Visuals**: A beautifully detailed retro industrial steam engine.

---

## 🦴 Skeletal Animation & Joint Node Mapper

The `Lem3D` skeletal system supports complex, hierarchical character rigs (canine, human, spider, etc.) using connected nodes. Joints are evaluated from the root down to the leaves, multiplying local matrices to build the final world coordinates.

```
[Hip Root (World)]
   ├── [Spine (Local)] ─── [Head (Local)]
   └── [Leg Left (Local)] ── [Foot (Local)]
```

### 📈 Intermediate Bone Interpolation Algorithm
To render organic bone connections rather than disconnected joints, `Lem3D` calculates intermediate segments between a parent and child joint. It interpolates positions along the bone's axis, applying a tapering scale to mimic anatomical bone structures:

$$\mathbf{p}_{\text{interp}} = \text{lerp}(\mathbf{p}_{\text{parent}}, \mathbf{p}_{\text{child}}, t) \quad \text{for } t \in (0, 1)$$

```typescript
// Drawing bone structures dynamically using the Lem3D joint system:
if (bone.parentName) {
  const parentBone = rig.getBone(bone.parentName);
  if (parentBone) {
    const parentPos = vec3.create();
    const childPos = vec3.create();
    
    // Extract translation vectors directly from computed world matrices
    mat4.getTranslation(parentPos, parentBone.worldMatrix);
    mat4.getTranslation(childPos, bone.worldMatrix);

    const boneLength = vec3.distance(parentPos, childPos);
    const numSegments = 5; // Intermediate spheres to generate

    for (let i = 1; i <= numSegments; i++) {
      const t = i / (numSegments + 1);
      const lerpedPos = vec3.create();
      vec3.lerp(lerpedPos, parentPos, childPos, t);

      // Compute tapering scale factor (thicker near joints, thinner in the middle)
      const taperScale = 0.08 * (1.0 - 0.45 * Math.sin(t * Math.PI));
      
      const transform = mat4.create();
      mat4.fromRotationTranslationScale(
        transform,
        quat.create(),
        lerpedPos,
        vec3.fromValues(taperScale, taperScale, taperScale)
      );

      // Push instance to the joint mesh container
      boneMesh.addInstance(transform, boneColor);
    }
  }
}
```

---

## 🎨 Custom WGSL Shader Architecture & Shadows

During execution, `Lem3D` binds uniform parameters to specific group indices. When writing custom fragment shaders, you can tap into these bindings to handle direct lighting, fog, and shadow mappings.

### 📐 Uniform Layout Bindings

#### Bind Group 0 (Camera & Environment):
- `@group(0) @binding(0)`: `CameraUniforms` Buffer
  ```wgsl
  struct CameraUniforms {
      viewProj: mat4x4<f32>,
      viewPos: vec3<f32>,
      lightSpaceMatrix: mat4x4<f32>,
      lightDir: vec3<f32>,
  };
  ```

#### Bind Group 1 (Shadow Maps):
- `@group(1) @binding(0)`: `texture_depth_2d` (Shadow depth texture)
- `@group(1) @binding(1)`: `sampler_comparison` (PCF comparison sampler)

### 🌓 Percentage-Closer Filtering (PCF) Shadow Math
Rather than performing a simple binary depth test which results in jagged, aliased shadow edges, `Lem3D` uses **Percentage-Closer Filtering (PCF)**. It samples the shadow depth map at multiple offsets around the target pixel, blending the results to create soft, realistic shadow edges:

$$\text{Shadow} = \frac{1}{(2N+1)^2} \sum_{x=-N}^{N} \sum_{y=-N}^{N} \text{SampleCompare}(\text{ShadowMap}, \text{UV} + \mathbf{offset}(x,y), \text{Depth} - \text{Bias})$$

```wgsl
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>,
};

@fragment
fn fs_main(in: VertexOutput) -> @location(0) vec4<f32> {
    let N = normalize(in.normal);
    let L = normalize(camera.lightDir);
    
    // Project vertices into light space coordinates [-1, 1]
    let projCoords = in.lightSpacePos.xyz / in.lightSpacePos.w;
    
    // Map coords from clip space [-1, 1] to UV texture space [0, 1]
    let flipY = vec3<f32>(
        projCoords.x * 0.5 + 0.5,
        projCoords.y * -0.5 + 0.5,
        projCoords.z
    );
    
    // Implement manual 3x3 PCF (Percentage-Closer Filtering) kernel for soft shadows
    var shadowSum: f32 = 0.0;
    let texelSize = 1.0 / 2048.0; // Shadow map size is 2048x2048
    let depthBias = 0.0025; // Prevents shadow acne
    
    for (var x: i32 = -1; x <= 1; x++) {
        for (var y: i32 = -1; y <= 1; y++) {
            let offset = vec2<f32>(f32(x), f32(y)) * texelSize;
            shadowSum += textureSampleCompare(
                shadowMap, 
                shadowSampler, 
                flipY.xy + offset, 
                flipY.z - depthBias
            );
        }
    }
    
    let shadowFactor = shadowSum / 9.0;
    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, shadowFactor, inBounds);
    
    // Classic Lambertian Diffuse lighting
    let diffuse = max(dot(N, L), 0.0);
    
    // Combine ambient lighting with filtered shadows
    let lighting = 0.25 + diffuse * shadow * 0.75;
    let finalColor = in.color * lighting;
    
    // Add linear height-fog
    let fogDensity = 0.015;
    let fogFactor = clamp(exp(-fogDensity * in.worldPos.y), 0.0, 1.0);
    let fogColor = vec3<f32>(0.05, 0.05, 0.08); // Matches canvas background clear color
    
    return vec4<f32>(mix(fogColor, finalColor, fogFactor), 1.0);
}
```

---

## 🚀 Hands-On Production Examples

Here are 5 complete, production-ready examples demonstrating various aspects of the engine.

### Example 1: Full-Featured React Canvas Integration
Demonstrates initializing the engine in React, configuring HMR cleanup listeners, and animating a wave of instanced shapes.

```tsx
import React, { useEffect, useRef, useState } from 'react';
import { useWebGPUEngine, WebGPUMesh, createRoundedBoxGeometry } from 'lem3d-webgpu';
import { mat4, vec3 } from 'gl-matrix';

export function InteractiveOceanCanvas() {
  const { canvasRef, engine, isSupported } = useWebGPUEngine({ debug: true });
  const [metrics, setMetrics] = useState({ fps: 0, drawCalls: 0, totalInstances: 0 });
  
  useEffect(() => {
    if (!engine) return;

    // Generate rounded box geometry
    const boxGeometry = createRoundedBoxGeometry(1.0, 1.0, 1.0, 0.1, 4);
    
    // Pre-allocate buffer space on the GPU for 2,000 instances
    const waveMesh = new WebGPUMesh(engine.device!, boxGeometry, 2000);
    engine.meshes = [waveMesh];

    let accumTime = 0;
    let animationFrameId: number;

    const renderLoop = () => {
      accumTime += engine.deltaTime;

      const instances = [];
      const gridDim = 30; // 30x30 grid = 900 cubes

      for (let x = 0; x < gridDim; x++) {
        for (let z = 0; z < gridDim; z++) {
          const u = x / (gridDim - 1);
          const v = z / (gridDim - 1);
          
          // Calculate three-dimensional sine wave displacement
          const posX = (u - 0.5) * 35.0;
          const posZ = (v - 0.5) * 35.0;
          const dist = Math.sqrt(posX * posX + posZ * posZ);
          const posY = Math.sin(dist * 0.4 - accumTime * 2.5) * 1.5;

          const transform = mat4.create();
          mat4.translate(transform, transform, [posX, posY, posZ]);
          mat4.scale(transform, transform, [0.85, 0.85, 0.85]);

          // Transition color based on height coordinate
          const r = 0.1 + u * 0.3;
          const g = 0.3 + posY * 0.2;
          const b = 0.8 + v * 0.2;

          instances.push({
            transform,
            color: new Float32Array([r, g, b])
          });
        }
      }

      // Sync data to the GPU in a single pass
      waveMesh.updateInstances(instances);

      // Smoothly update camera position tracking
      engine.camera.updateFollowTarget(vec3.fromValues(0, 0, 0));

      // Query rendering performance metrics
      setMetrics(engine.getMetrics());

      if (engine.isRunning) {
        animationFrameId = requestAnimationFrame(renderLoop);
      }
    };

    renderLoop();

    // Proper React HMR cleanup listener
    return () => {
      cancelAnimationFrame(animationFrameId);
      if (engine) {
        engine.stop();
      }
    };
  }, [engine]);

  if (!isSupported) {
    return (
      <div className="flex items-center justify-center h-screen bg-neutral-950 text-red-500">
        WebGPU is not enabled or supported in your browser. Try updating Chrome.
      </div>
    );
  }

  return (
    <div className="relative w-full h-screen bg-neutral-950">
      <canvas ref={canvasRef} className="w-full h-full block" />
      
      {/* Absolute Performance Stats Overlay */}
      <div className="absolute top-4 left-4 p-4 rounded-xl bg-neutral-900/95 border border-neutral-800 text-xs font-mono text-neutral-300 backdrop-blur-md">
        <h4 className="font-bold text-[#6366f1] mb-2">🪐 Lem3D Diagnostics</h4>
        <p>FPS: <span className="text-white font-bold">{metrics.fps}</span></p>
        <p>Draw Calls: <span className="text-white font-bold">{metrics.drawCalls}</span></p>
        <p>Instances: <span className="text-white font-bold">{metrics.totalInstances}</span></p>
      </div>
    </div>
  );
}
```

---

### Example 2: Interactive Keyboard Character Controller
Demonstrates utilizing `engine.keys` inside loop updates to handle WASD drone navigation.

```typescript
import { WebGPUEngine, WebGPUMesh, createQuadcopterPrefab } from 'lem3d-webgpu';
import { mat4, vec3, quat } from 'gl-matrix';

export async function initDroneController(canvas: HTMLCanvasElement) {
  const engine = new WebGPUEngine({ canvas, debug: true });
  const isOk = await engine.init();
  if (!isOk) return;

  // Set up the quadcopter mesh
  const droneGeom = createQuadcopterPrefab();
  const droneMesh = new WebGPUMesh(engine.device!, droneGeom, 1);
  engine.meshes = [droneMesh];

  // Starting position coordinates
  const position = vec3.fromValues(0, 2.0, 0);
  let rotationY = 0.0;
  const speed = 8.0; // units per second

  const tick = () => {
    const dt = engine.deltaTime;
    const direction = vec3.create();

    // Check keyboard input states
    if (engine.keys['w'] || engine.keys['arrowup']) {
      direction[2] += 1.0;
    }
    if (engine.keys['s'] || engine.keys['arrowdown']) {
      direction[2] -= 1.0;
    }
    if (engine.keys['a'] || engine.keys['arrowleft']) {
      rotationY += 2.0 * dt; // Rotate counter-clockwise
    }
    if (engine.keys['d'] || engine.keys['arrowright']) {
      rotationY -= 2.0 * dt; // Rotate clockwise
    }
    if (engine.keys[' '] || engine.keys['q']) {
      position[1] += speed * 0.5 * dt; // Gain altitude
    }
    if (engine.keys['shift'] || engine.keys['e']) {
      position[1] = Math.max(0.1, position[1] - speed * 0.5 * dt); // Drop altitude
    }

    // Apply rotation matrix transforms to move relative to heading
    if (vec3.length(direction) > 0) {
      vec3.normalize(direction, direction);
      const moveRotation = quat.create();
      quat.setAxisAngle(moveRotation, vec3.fromValues(0, 1, 0), rotationY);
      vec3.transformQuat(direction, direction, moveRotation);
      vec3.scaleAndAdd(position, position, direction, speed * dt);
    }

    // Compose final transformation matrix
    const transform = mat4.create();
    mat4.translate(transform, transform, position);
    mat4.rotateY(transform, transform, rotationY);

    // Apply rotation wobble animation based on moving state
    if (vec3.length(direction) > 0) {
      mat4.rotateX(transform, transform, 0.15); // Slight tilt forward
    }

    // Push coordinates to the drone mesh buffer
    droneMesh.updateInstances([{
      transform,
      color: new Float32Array([0.2, 0.8, 1.0]) // Cyber Blue hull tint
    }]);

    // Position camera to follow behind the moving drone
    engine.camera.updateFollowTarget(position);
  };

  const render = () => {
    tick();
    if (engine.isRunning) {
      requestAnimationFrame(render);
    }
  };

  engine.start();
  requestAnimationFrame(render);
}
```

---

### Example 3: Dynamic Procedural Joint/Skeletal Rig Setup
Demonstrates dynamically building a jointed segment spine/tail chain that wiggles procedurally.

```typescript
import { WebGPUEngine, WebGPUMesh, createSphereGeometry, createCylinderGeometry } from 'lem3d-webgpu';
import { mat4, vec3, quat } from 'gl-matrix';

export async function initSkeletalSpine(canvas: HTMLCanvasElement) {
  const engine = new WebGPUEngine({ canvas });
  await engine.init();

  // Create joint node geometries
  const jointGeom = createSphereGeometry(0.35, 12, 12);
  const boneGeom = createCylinderGeometry(0.08, 0.08, 1.0, 8);

  const jointMesh = new WebGPUMesh(engine.device!, jointGeom, 50);
  const boneMesh = new WebGPUMesh(engine.device!, boneGeom, 50);

  engine.meshes = [jointMesh, boneMesh];

  let time = 0;
  const numSegments = 10;

  const loop = () => {
    time += engine.deltaTime;

    const jointInstances = [];
    const boneInstances = [];

    // Track sequential joint positions
    const jointPositions: vec3[] = [];
    let currentPos = vec3.fromValues(0, 1.0, 0);
    jointPositions.push(vec3.clone(currentPos));

    let currentAngle = 0;

    for (let i = 1; i < numSegments; i++) {
      // Calculate a progressive wave offset for each segment
      const waveAngle = Math.sin(time * 3.0 - i * 0.6) * 0.35;
      currentAngle += waveAngle;

      const nextPos = vec3.fromValues(
        currentPos[0] + Math.sin(currentAngle) * 1.5,
        currentPos[1],
        currentPos[2] + Math.cos(currentAngle) * 1.5
      );

      jointPositions.push(vec3.clone(nextPos));
      currentPos = nextPos;
    }

    // 1. Position and render Joint Node Spheres
    for (let i = 0; i < jointPositions.length; i++) {
      const transform = mat4.create();
      mat4.fromTranslation(transform, jointPositions[i]);
      
      jointInstances.push({
        transform,
        color: new Float32Array([1.0, 0.3 + (i / numSegments) * 0.7, 0.2])
      });
    }

    // 2. Position and interpolate Bone connecting segments
    for (let i = 0; i < jointPositions.length - 1; i++) {
      const parent = jointPositions[i];
      const child = jointPositions[i + 1];

      const midPoint = vec3.create();
      vec3.add(midPoint, parent, child);
      vec3.scale(midPoint, midPoint, 0.5);

      const direction = vec3.create();
      vec3.sub(direction, child, parent);
      const distance = vec3.length(direction);
      vec3.normalize(direction, direction);

      // Align Cylinder orientation with the connection vector
      const alignRotation = quat.create();
      const upVector = vec3.fromValues(0, 1, 0);
      quat.rotationTo(alignRotation, upVector, direction);

      const transform = mat4.create();
      mat4.fromRotationTranslationScale(
        transform,
        alignRotation,
        midPoint,
        vec3.fromValues(1.0, distance, 1.0) // Stretch along the cylinder's height axis
      );

      boneInstances.push({
        transform,
        color: new Float32Array([0.8, 0.8, 0.9])
      });
    }

    jointMesh.updateInstances(jointInstances);
    boneMesh.updateInstances(boneInstances);

    // Track the middle joint of the spine
    engine.camera.updateFollowTarget(jointPositions[Math.floor(numSegments / 2)]);

    if (engine.isRunning) {
      requestAnimationFrame(loop);
    }
  };

  engine.start();
  requestAnimationFrame(loop);
}
```

---

### Example 4: Dynamic Noise Grid Shader Compile
Demonstrates dynamically compiling and injecting a custom WGSL vertex displacement shader to create animated landscape deformation.

```typescript
import { WebGPUEngine, WebGPUMesh, createGridGeometry } from 'lem3d-webgpu';

export async function setupDynamicNoiseShader(canvas: HTMLCanvasElement) {
  const engine = new WebGPUEngine({ canvas });
  await engine.init();

  // Create high-density grid geometry (60x60 subdivisions)
  const gridGeom = createGridGeometry(40.0, 40.0, 60, 60);
  const gridMesh = new WebGPUMesh(engine.device!, gridGeom, 1);
  engine.meshes = [gridMesh];

  // Set grid to origin coordinates
  gridMesh.updateInstances([{
    transform: new Float32Array(16), // Identity matrix (filled below dynamically)
    color: new Float32Array([0.0, 1.0, 0.5])
  }]);

  // Custom WGSL shader inject code containing sinus-noise displacement calculations
  const vertexShaderWithNoise = `
    struct CameraUniforms {
        viewProj: mat4x4<f32>,
        viewPos: vec3<f32>,
        lightSpaceMatrix: mat4x4<f32>,
        lightDir: vec3<f32>,
    };

    @group(0) @binding(0) var<uniform> camera: CameraUniforms;

    struct VertexInput {
        @location(0) position: vec3<f32>,
        @location(1) normal: vec3<f32>,
        @location(2) uv: vec2<f32>,
        @location(3) instanceTransformRow0: vec4<f32>,
        @location(4) instanceTransformRow1: vec4<f32>,
        @location(5) instanceTransformRow2: vec4<f32>,
        @location(6) instanceTransformRow3: vec4<f32>,
        @location(7) instanceColor: vec3<f32>,
    };

    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>,
    };

    // Fast coordinate noise generator
    fn waveNoise(coord: vec2<f32>) -> f32 {
        let v1 = sin(coord.x * 0.15) * cos(coord.y * 0.15);
        let v2 = sin(coord.x * 0.4) * cos(coord.y * 0.4) * 0.5;
        return v1 + v2;
    }

    @vertex
    fn vs_main(in: VertexInput) -> VertexOutput {
        var out: VertexOutput;

        // Reconstruct instancing transform matrix
        let instanceMatrix = mat4x4<f32>(
            in.instanceTransformRow0,
            in.instanceTransformRow1,
            in.instanceTransformRow2,
            in.instanceTransformRow3
        );

        var worldPos = (instanceMatrix * vec4<f32>(in.position, 1.0)).xyz;

        // Deform Y coordinate height based on XZ planar positions
        let heightOffset = waveNoise(worldPos.xz);
        worldPos.y += heightOffset * 3.0;

        out.worldPos = worldPos;
        out.position = camera.viewProj * vec4<f32>(worldPos, 1.0);
        
        // Approximate procedural normal vector adjustments
        out.normal = in.normal;
        out.color = mix(vec3<f32>(0.1, 0.15, 0.3), vec3<f32>(0.2, 0.9, 0.6), heightOffset * 0.5 + 0.5);
        out.lightSpacePos = camera.lightSpaceMatrix * vec4<f32>(worldPos, 1.0);

        return out;
    }
  `;

  // Dynamically compile and inject custom shader pipeline
  const result = await engine.compileCustomShader(vertexShaderWithNoise);
  if (!result.success) {
    console.error("Shader injection failed:", result.error);
  } else {
    console.log("Custom dynamic landscape shader hot-swapped successfully.");
  }

  engine.start();
}
```

---

### Example 5: High-Performance Benchmark Testing
Demonstrates rendering thousands of active moving instances at 60 FPS using raw GPU instancing buffers.

```typescript
import { WebGPUEngine, WebGPUMesh, createTeardropGeometry } from 'lem3d-webgpu';
import { mat4, vec3 } from 'gl-matrix';

export async function runShatterBenchmark(canvas: HTMLCanvasElement, instanceCount: number = 5000) {
  const engine = new WebGPUEngine({ canvas });
  await engine.init();

  // Create streamlined teardrop geometries
  const geometry = createTeardropGeometry(0.5, 1.0);
  const mesh = new WebGPUMesh(engine.device!, geometry, instanceCount);
  engine.meshes = [mesh];

  // Initialize random speed vectors for each instance
  const speeds = new Float32Array(instanceCount);
  const positions = new Float32Array(instanceCount * 3);
  const colors = new Float32Array(instanceCount * 3);

  for (let i = 0; i < instanceCount; i++) {
    speeds[i] = 1.0 + Math.random() * 3.0;
    
    // Spread coordinates inside a spherical bubble
    const theta = Math.random() * Math.PI * 2;
    const phi = Math.acos((Math.random() * 2) - 1);
    const radius = 5.0 + Math.random() * 25.0;

    positions[i * 3 + 0] = radius * Math.sin(phi) * Math.cos(theta);
    positions[i * 3 + 1] = radius * Math.sin(phi) * Math.sin(theta);
    positions[i * 3 + 2] = radius * Math.cos(phi);

    // Random RGB colors
    colors[i * 3 + 0] = Math.random();
    colors[i * 3 + 1] = Math.random();
    colors[i * 3 + 2] = Math.random();
  }

  const loop = () => {
    const dt = engine.deltaTime;
    const instances = [];

    for (let i = 0; i < instanceCount; i++) {
      // Rotate instances around the center vertical axis
      const speed = speeds[i] * dt * 0.2;
      const x = positions[i * 3 + 0];
      const z = positions[i * 3 + 2];
      
      const cosAngle = Math.cos(speed);
      const sinAngle = Math.sin(speed);

      // Write updated orbital coordinates
      positions[i * 3 + 0] = x * cosAngle - z * sinAngle;
      positions[i * 3 + 2] = x * sinAngle + z * cosAngle;

      // Animate vertical floating patterns
      positions[i * 3 + 1] += Math.sin(engine.deltaTime + i) * 0.05;

      const transform = mat4.create();
      mat4.translate(transform, transform, [
        positions[i * 3 + 0],
        positions[i * 3 + 1],
        positions[i * 3 + 2]
      ]);
      
      // Point instances toward the center coordinate
      mat4.rotateY(transform, transform, Math.atan2(positions[i * 3 + 0], positions[i * 3 + 2]));

      instances.push({
        transform,
        color: colors.subarray(i * 3, i * 3 + 3)
      });
    }

    // Direct memory update call
    mesh.updateInstances(instances);

    if (engine.isRunning) {
      requestAnimationFrame(loop);
    }
  };

  engine.start();
  requestAnimationFrame(loop);
}
```

---

## ⚙️ Requirements & Browser Support

To execute WebGPU pipelines correctly, standard API flags must be enabled on compatible client hardware.

### Compatible Browsers:
- **Google Chrome & Microsoft Edge** (v113+ is enabled fully on desktop platforms, Android support rolling out natively).
- **Opera** (v100+ native support).
- **Mozilla Firefox** (Requires flipping developer flags: input `about:config` inside your address bar and turn `dom.webgpu.enabled` to `true`).
- **Safari** (Requires enabling `WebGPU` under Safari Settings -> Developer Advanced Experiments list).

### 💡 Local Execution Warning:
WebGPU is restricted to **Secure Contexts (HTTPS)** and local loopback addresses (`localhost` and `127.0.0.1`). If you serve your development files over an external IP address or unencrypted host, `navigator.gpu` will return `undefined`. Ensure your staging domains are behind full SSL/TLS certificates.

---

## 🛠️ Diagnostics & Troubleshooting

1. **"Failed to create GPUDevice / GPUAdapter is null"**
   - *Fix*: Check if you are running in a secure HTTPS context. On Windows, make sure your graphics drivers are updated to support Vulkan or DX12. On Linux, run Chrome with `--enable-features=Vulkan` flags if running under Intel integrated chips.
2. **"Buffer size must be a multiple of 4 bytes / alignment errors"**
   - *Fix*: WebGPU uniform updates expect strict memory alignment rules. Matrix floats are 4 bytes. Ensure your `InstanceData` color components consist of exactly 3 floats (12 bytes, multiple of 4), and transformation matrix structures contain exactly 16 floats (64 bytes).
3. **"Shadow mapping is flickering or showing shadow acne"**
   - *Fix*: Increase or decrease the `depthBias` threshold constant in your custom WGSL fragment shader code block. High-range meshes require wider biases to avoid float precision rounding inaccuracies.
4. **"Flickering canvases during React Hot Reloads (HMR)"**
   - *Fix*: Since HMR swaps component files while keeping the page alive, old rendering contexts can remain active. Call `engine.stop()` and unbind all event listeners inside your React `useEffect` cleanups, as demonstrated in Example 1.

---

## 📄 License
This WebGPU Engine library is open-source and distributed under the **MIT License**. Feel free to leverage the pipelines for commercial or personal production.
