README.md

blurz #

Real-time webcam video effects powered by WebGPU shaders and MediaPipe hand tracking.

Position your hands in front of the camera and watch as GPU-powered effects are applied to the quads between your fingertips. Switch between 16 different effects and toggle between single-quad and five-finger quad mode.

Requirements #

  • A browser with WebGPU support (Chrome 113+, Edge 113+, or enable flags in Firefox Nightly)
  • Camera permission granted to the page
  • Two hands visible to the camera (for quad effects)

Usage #

pnpm install
pnpm dev

Open https://blurz.localhost (served via portless — no port juggling). On first run, portless generates a local CA, asks to trust it, and may prompt for your password to bind port 443.

To run the dev server directly without the portless proxy, bypass it with PORTLESS=0 pnpm dev.

Controls #

Input Action
← / → (or ↑ / ↓) Cycle effects
Tap left half of canvas Previous effect
Tap right half of canvas Next effect
Clench both fists Toggle quad mode (single / five-finger)

Single mode: both hands form one quad between index fingers and thumbs — one effect applies to the entire area.

Five-finger mode: five fingers create four adjacent quads — each gets its own dedicated effect.

Available Effects #

  1. Gaussian Blur
  2. Chromatic Aberration
  3. Pixelation
  4. Edge Detect
  5. Kaleidoscope
  6. Invert
  7. Swirl
  8. CRT
  9. Thermal
  10. ASCII
  11. Posterize
  12. Bloom
  13. Displace
  14. Neon Edge
  15. RGB Glitch
  16. Psychedelic
  17. Liquid Chrome

In five-finger mode, quads 13–16 are used (Neon Edge, RGB Glitch, Psychedelic, Liquid Chrome).

Architecture #

src/
├── App.tsx              — Root component: init pipeline, render loop, controls
├── index.tsx            — Entry point
├── index.css            — Styles: HUD, loading, error overlays
├── lib/
│   ├── constants.ts     — Shared constants (finger indices, effect assignments)
│   ├── types.ts         — TypeScript interfaces (Point, QuadCorners)
│   ├── effects.ts       — Effect definitions and catalog
│   ├── webgpu.ts        — WebGPU renderer (textures, pipelines, ping-pong)
│   └── handtrack.ts     — HandTracker class (MediaPipe + smoothing + gestures)
└── shaders/
    ├── preamble.wgsl    — Shared WGSL preamble (VertexOutput, Uniforms, helpers)
    ├── fullscreen-triangle.wgsl  — Fullscreen triangle vertex shader
    ├── copy.wgsl        — External texture → 2D texture copy
    ├── composite.wgsl   — Final compositing + quad outlines
    ├── blur-horizontal.wgsl  — Gaussian blur horizontal pass
    ├── blur-vertical.wgsl    — Gaussian blur vertical pass
    └── effects/         — 16 effect shaders

Pipeline #

  1. Camera captures video → <video> element
  2. Copy pass copies the external video texture into a regular GPUTexture
  3. Hand tracking (MediaPipe) detects landmarks → One Euro smoothing → fist detection → quad geometry
  4. Effect passes run per-quad shaders using ping-pong textures (multi-pass for Gaussian blur)
  5. Composite pass blends the sharp webcam feed with effect textures, drawing white quad outlines

Adding a New Effect #

  1. Create a WGSL fragment shader in src/shaders/effects/ (use VertexOutput and Uniforms from the shared preamble)
  2. Import it in src/lib/effects.ts and add an entry to the EFFECTS array
  3. Optionally assign it to a five-finger quad slot in src/lib/constants.ts

Build #

pnpm build

Produces a static bundle in dist/.