shader_legends_3 · TaterBokeh
Bokeh Blur with Light Leaks
A 2D bokeh effect built by stamping 50-200 soft Gaussian discs onto a near-black backdrop, each at a hash-determined centre, radius, and warm-to-cool colour. The discs are additively blended so overlapping regions glow with a light-leak intensity. Per-disc slow drift animates each circle in a slightly different direction, producing the look of out-of-focus Christmas lights or a lens-flare test chart.
Original: https://www.shadertoy.com/results?query=tater+bokeh
▶ Try the live demo (JS port) ▶ Run reference.py via Pyodide 10 formulas have instant JS ports. The Pyodide path runs the actual Python in your browser — first load is ~6 MB, then instant.
Math essence
For each circle c with centre (cx_c, cy_c), radius r_c, colour col_c and peak i_c: stamp(c) = col_c * i_c * exp(-((p - centre_c) / r_c)^2 * tightness). canvas = background + sum_c stamp(c). canvas := canvas / (1 + 0.6 * canvas) (Reinhard tonemap), then multiply by a soft radial vignette.
Parameters
| Name | Type | Default | Range | Description |
|---|---|---|---|---|
dim | int | 400 | 160–800 | Square output size in pixels. |
n_circles | int | 120 | 20–300 | Number of bokeh circles. |
base_radius | float | 0.1 | 0.03–0.3 | Base Gaussian radius in canvas units. |
radius_jitter | float | 0.6 | 0–1.5 | Per-circle radius randomness (0 = all same size). |
drift | float | 0.005 | -0.05–0.05 | Per-step drift of each circle's centre (animated on a torus). |
warm_color | rgb | 1,0.55,0.2 | null–null | Warm end of the colour palette. |
cool_color | rgb | 0.3,0.7,1 | null–null | Cool end of the colour palette. |
accent_color | rgb | 0.95,0.9,0.7 | null–null | Accent colour for the upper-mid range. |
background | rgb | 0.02,0.02,0.06 | null–null | Backdrop colour. |
tightness | float | 2.5 | 0.5–8 | Gaussian falloff exponent: higher = tighter, more ring-like. |
Reference
First 60 lines of reference.py. Full source:
library_external/shader_legends_3/TaterBokeh/reference.py
from __future__ import annotations
from typing import ClassVar
import numpy as np
def _hash11(x: np.ndarray, seed: int) -> np.ndarray:
p = np.int64(x) * np.int64(374761393) + np.int64(seed) * np.int64(668265263)
p = p & np.int64(0xFFFFFFFF)
p = (p ^ (p >> np.int64(13))) * np.int64(1274126177)
p = p & np.int64(0xFFFFFFFF)
p = p ^ (p >> np.int64(16))
return (p & np.int64(0xFFFFFFFF)).astype(np.float32) / np.float32(0xFFFFFFFF)
def _hash12(x: np.ndarray, y: np.ndarray, seed: int) -> np.ndarray:
p = np.int64(x) * np.int64(374761393) + np.int64(y) * np.int64(668265263) + np.int64(seed)
p = p & np.int64(0xFFFFFFFF)
p = (p ^ (p >> np.int64(13))) * np.int64(1274126177)
p = p & np.int64(0xFFFFFFFF)
p = p ^ (p >> np.int64(16))
return (p & np.int64(0xFFFFFFFF)).astype(np.float32) / np.float32(0xFFFFFFFF)
class TaterBokeh:
"""Bokeh blur with light leaks — Dave "Tater" Hoskins (Shadertoy).
Tater (Dave Hoskins) wrote several *bokeh* shaders that draw
50-200 soft Gaussian circles on a dark backdrop, where each
circle's colour is drawn from a warm-to-cool palette and
overlapping circles add their intensities (additive blending)
to produce a *light leak* effect at the intersection. The
trick is that the circles are *not* all the same size: a
per-circle hash picks both a centre, a radius, and a colour,
and a slow per-circle drift animates each disc in a slightly
different direction.
The output looks like out-of-focus Christmas lights or a
lens-flare test chart.
Math essence:
for each circle c:
h = hash(c)
centre_c = (h.x, h.y)
r_c = base_radius * (0.4 + 0.9 * h.r)
col_c = palette(h.hue)
drift_c = (h.dx, h.dy) * speed
for each pixel p:
d = |p - centre_c(t)|
intensity = exp(-(d/r_c)^2)
canvas += col_c * intensity
We render the additive accumulation efficiently by stamping
each circle into its own per-circle buffer and summing them.
"""
family: ClassVar[str] = "shader_legends_3"
sketch: ClassVar[str] = "taterbokeh" Try running it locally
The reference implementation is self-contained Python with numpy. Install the package and run:
python library_external/shader_legends_3/TaterBokeh/reference.py Need help? See Learn for the standard environment setup, or Playground for an in-browser sketchbook.
More from shader_legends_3
Animated FBM Nebula with Chromatic Aberration
shader_legends_3 · AshleyGAnimNebula
A multi-coloured, slowly rotating cosmic gas cloud built from 5 layers of FBM noise at different scales, each layer rotated by a different angle that varies with time.
Atmospheric Perspective Landscape
shader_legends_3 · HubertyAtmospheric
A painterly 2D landscape built from depth-graded FBM bands: a soft sky gradient with a sun disc and cloud streaks, a low-amp haze band in the upper-middle, rolling green midground hills, and a sharp foreground silhouette of trees and grass.
Hash-driven Procedural City Skyline
shader_legends_3 · DaveHoskinsHashCity
A 2D orthographic night-time cityscape whose per-column building heights come from 1D FBM noise and whose lit windows are a per-cell hash threshold.
Recursive Spherical Displacement Wireframe
shader_legends_3 · IQDisplacementSphere
A wireframe sphere whose surface is recursively displaced by spherical harmonics of the form amp * sin(N * theta) * cos(M * phi), rendered as overlapping latitude and meridian polylines plus random surface dots.
Volumetric Clouds from Cellular + FBM
shader_legends_3 · BigWingsClouds
A painterly cumulus-cloud sky built from a Worley/cellular noise layer (cloud puffs) gated by a low-frequency FBM (large-scale cloud coverage) and a high-frequency FBM (in-cloud detail).