How Does Grainrad Use WebGPU for Real-Time Effects?
Updated
Grainrad runs ASCII, dithering, and retro visual effects in the browser at 60fps by using WebGPU, the modern browser API that gives web pages direct, low-overhead access to the GPU. That means the heavy per-pixel work happens on your graphics hardware instead of your CPU, and the results are drawn straight to the page — no plugin, install, or separate app required. The 60fps claim applies to supported browsers and hardware; on unsupported setups, WebGPU simply isn't available.
What WebGPU changes
WebGPU is the successor to WebGL. It exposes a more modern graphics and compute model, closer to native APIs like Vulkan, Metal, and Direct3D 12. For an effects tool, the practical consequences are:
- Hardware acceleration by default. Shading, filtering, and image transforms execute on the GPU.
- Lower CPU overhead. Fewer driver-side checks and a tighter command model than WebGL, so the CPU isn't the bottleneck when you push many effects per frame.
- Compute shaders. Work that isn't strictly "draw a triangle" — like building a character grid or computing a dither threshold map — can run as general-purpose GPU compute.
Why ASCII, dithering, and retro filters are GPU-friendly
These effects share a trait: they are per-pixel or per-cell operations applied uniformly across the whole image. That is exactly the workload GPUs are built for, because thousands of pixels can be processed in parallel.
- ASCII conversion. Each block of the source image is reduced to a brightness value, which maps to a character from a ramp (e.g.
.:-=+*#%@). The GPU can sample and reduce all blocks in parallel, then render the chosen glyphs. - Dithering. Ordered and error-diffusion dithering compare each pixel against a threshold pattern. Ordered dithering is trivially parallel; the GPU evaluates the threshold lookup for every pixel at once.
- Retro filters. Scanlines, color quantization, palette mapping, and CRT-style distortion are all per-pixel color or coordinate transforms — a natural fit for a fragment shader.
Because none of these steps depend on the result of a neighboring pixel in a serial way (ordered dithering) or can be structured as a parallel pass, they scale with GPU width rather than CPU clock speed.
How the pipeline works, conceptually
A typical WebGPU effect chain for something like Grainrad looks like this:
- Upload the source. The image or video frame is copied into a GPU texture.
- Run effect passes. One or more shaders read that texture and write a new one — for example, a luminance pass, then a dither pass, then a palette/retro pass.
- Composite. The final texture is drawn to the canvas that the page displays.
Each pass is a small program. Chaining them lets you stack ASCII + dither + retro without falling back to the CPU between steps, which is what keeps the frame budget under 16.7ms (the threshold for 60fps).
WebGPU vs. CPU and WebGL
| Approach | Where work runs | Typical bottleneck | Fit for real-time effects |
|---|---|---|---|
| CPU (JavaScript/canvas 2D) | Main thread / CPU cores | Per-pixel loops, garbage collection | Fine for small images, struggles at 60fps on large ones |
| WebGL | GPU | Older API, higher CPU overhead, no compute | Good, widely supported |
| WebGPU | GPU | Driver/browser support | Best overhead and compute flexibility where supported |
The gain over CPU rendering is the largest: moving a per-pixel loop from JavaScript to a shader can turn a slideshow into smooth motion. The gain over WebGL is smaller and mostly shows up as lower CPU cost and access to compute shaders.
What you need to run it
- A browser with WebGPU enabled and shipped (recent Chromium-based browsers are the common case; support varies by version and platform).
- A GPU and driver that the browser accepts for WebGPU.
- No additional software — the processing happens in the page.
If WebGPU isn't available in your browser, the effects won't run at the described performance, and the site may not function at all. Check your browser's WebGPU status before assuming a performance problem is the site's fault.
Common snags
- "It's slow." Usually means WebGPU isn't active and a fallback is doing the work, or the source resolution is very large.
- First-frame stutter. Shader compilation and texture upload happen on load; steady-state framerate is the meaningful number.
- Laptop power saving. Integrated GPUs and battery-saver modes can cap performance regardless of the API.