shader_legends · TaterHashArt
Hash without Sine — Dave Hoskins hash art
Dave Hoskins's celebrated 'Hash without Sine' family of cross-platform-stable pseudo-random hash functions, presented as art. The canvas is tiled or scattered with integer grid cells and at every cell we plot a coloured point whose position jitter, hue, size and stroke angle are all driven by hash22 (or hash33 for the 3D triptych mode). The artwork is a direct celebration of the shadertoy.com legend whose hash functions have become the default building block for procedural shaders.
Original: https://www.shadertoy.com/view/4djSRW
▶ 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
hash22(p) is the canonical Hoskins 2014 fragment: p3 = fract(p * (0.1031, 0.1030, 0.0973)); p3 += dot(p3, p3.yzx + 33.33); return fract((p3.xx + p3.yz) * p3.zy). hash33(p) is the 3D analog using a different mix. We sample one of {grid22, scatter22, scatter33, streaks} modes; in every case the integer cell id is hashed, and (jitter_x, jitter_y, hue, size) come from the hash output. The cosine palette maps hash.hue to an RGB triple.
Parameters
| Name | Type | Default | Range | Description |
|---|---|---|---|---|
dim | int | 360 | 120–800 | Square output size in pixels. |
cells | int | 40 | 8–80 | Number of integer grid cells per side (grid22 and streaks modes). |
mode | string | grid22 | null–null | Visualization mode: grid22, scatter22, scatter33 (triptych), or streaks. |
point_size | float | 0.65 | 0.1–3 | Multiplier on the per-point radius derived from the hash. |
scatter_count | int | 2500 | 200–8000 | Number of scatter points (scatter22 and scatter33 modes). |
hue_shift | float | 0 | 0–1 | Phase shift applied to the cosine palette. |
Reference
First 60 lines of reference.py. Full source:
library_external/shader_legends/TaterHashArt/reference.py
from __future__ import annotations
from typing import ClassVar
import numpy as np
def _hoskins_hash22(x: np.ndarray, y: np.ndarray) -> tuple[np.ndarray, np.ndarray]:
"""Dave Hoskins's `hash22` (Shadertoy 'Hash without Sine', 4djSRW).
vec2 hash22(vec2 p) {
vec3 p3 = fract(vec3(p.xyx) * vec3(.1031, .1030, .0973));
p3 += dot(p3, p3.yzx + 33.33);
return fract((p3.xx + p3.yz) * p3.zy);
}
"""
p3 = np.stack([x, y, x], axis=-1).astype(np.float64)
p3 = p3 * np.array([0.1031, 0.1030, 0.0973])
p3 = p3 - np.floor(p3)
p3 = p3 + np.sum(p3 * (p3[..., (1, 2, 0)] + 33.33), axis=-1, keepdims=True)
xx = p3[..., 0]
yz = np.stack([p3[..., 1], p3[..., 2]], axis=-1)
out = (np.stack([xx, xx], axis=-1) + yz) * np.stack([p3[..., 2], p3[..., 1]], axis=-1)
return (out[..., 0] - np.floor(out[..., 0])).astype(np.float32), (out[..., 1] - np.floor(out[..., 1])).astype(np.float32)
def _hoskins_hash33(x: np.ndarray, y: np.ndarray, z: np.ndarray) -> tuple[np.ndarray, np.ndarray, np.ndarray]:
"""Dave Hoskins's `hash33` (Shadertoy 'Hash without Sine', 4djSRW)."""
p3 = np.stack([x, y, z], axis=-1).astype(np.float64) * np.array([0.1031, 0.1030, 0.0973])
p3 = p3 - np.floor(p3)
p3 = p3 + np.sum(p3 * (p3[..., (1, 0, 2)] + 33.33), axis=-1, keepdims=True)
x_y = p3[..., 0]
y_z = p3[..., 1]
z_x = p3[..., 2]
o1 = (x_y + y_z) * z_x
o2 = (x_y + z_x) * y_z
o3 = (y_z + z_x) * x_y
return (o1 - np.floor(o1)).astype(np.float32), (o2 - np.floor(o2)).astype(np.float32), (o3 - np.floor(o3)).astype(np.float32)
class TaterHashArt:
"""Hash without Sine — Dave Hoskins (Shadertoy 'Tater').
Re-creates Dave Hoskins's iconic *Hash without Sine* (Shadertoy
`4djSRW`, 2014), a cross-platform-stable family of pseudo-random
hash functions used as a building block in countless Shadertoy
sketches. Rather than rendering the hashes invisibly as primitives,
we *visualise* them: the canvas is tiled with regular 2D integer
grids, and at every grid cell we plot a coloured point whose
position, size and colour are driven by `hash22` or `hash33`.
Modes:
- `grid22` — large grid, each cell shows one `hash22` point.
- `scatter22` — many `hash22` points scattered across the canvas.
- `scatter33` — three sample planes (xy, yz, zx) of `hash33`
composited side-by-side as a triptych.
- `streaks` — for each cell, draw a short coloured stroke whose
angle and length are driven by `hash22`.
""" Try running it locally
The reference implementation is self-contained Python with numpy. Install the package and run:
python library_external/shader_legends/TaterHashArt/reference.py Need help? See Learn for the standard environment setup, or Playground for an in-browser sketchbook.
More from shader legends
Domain Repetition — Inigo Quilez tile-with-warp
shader_legends · IQDomainRepetition
Inigo Quilez's 'Domain Repetition' technique from his 2008 article.
Improved Noise — Ken Perlin (SIGGRAPH 2002, faithful reimplementation)
shader_legends · KenPerlinNoisePure
Ken Perlin's Improved Noise (SIGGRAPH 2002) ported faithfully to numpy.
Pixel City — top-down procedural city
shader_legends · PolygoncityPixelCity
A top-down 50x50 procedural city built from a deterministic hash of grid cells.
Shane Flow Field — particles in an fBM flow
shader_legends · ShaneFlowFieldFBM
Inspired by Shane's Noisey Image Flow Lines (Shadertoy 7sSSzw).
Shane Organic Noise — layered Perlin with rotation and twist
shader_legends · ShaneOrganicNoise
Shane Olsson's 'organic noise' Shadertoy technique: a base Perlin-style gradient noise is sampled in multiple octaves, with each successive layer rotated by an angle proportional to the layer index and twisted by sinusoidal warping about the canvas centre.