Skip to content

Instantly share code, notes, and snippets.

@kbob
Last active June 17, 2025 19:38
Show Gist options
  • Save kbob/aa03b9e065c641ce6c100962083032e7 to your computer and use it in GitHub Desktop.
Save kbob/aa03b9e065c641ce6c100962083032e7 to your computer and use it in GitHub Desktop.
Bubble Phi Pixelblaze shader
// Bubble Phi
// (Sounds like Boba Tea)
//
// Stream of rising bubbles with low discrepancy quasirandom hues
// https://extremelearning.com.au/unreasonable-effectiveness-of-quasirandom-sequences/#quasiperiodic_tiling
// Constants
// IPHI = (sqrt(5) - 1) / 2 // 1 / phi, the golden ratio
IPHI2 = [0.7548776662466927, 0.5698402909980532]
// Tunable parameters
speed = 1
blend = 0.4
twist = 0.6
bubble_density = 1
hue_scale = 384 // hues repeat after this
// UI parameters
var use_fire_hues
export function beforeRender(delta) {
// t1 - bubble movement
t1 = time(hue_scale * 0.03 / speed)
// t2 - hue rotation
t2 = time(0.05 / speed)
}
export function render3D(index, x, y, z) {
pix_t1 = hue_scale * t1 - bubble_density * y
bubble_number = floor(pix_t1)
bubble_diameter = (wave(pix_t1 - 0.25) + 0.8) / 1.8
// radius - distance from center Y axis
cx = 2 * x - 1
cz = 2 * z - 1
r = sqrt(cx * cx + cz * cz)
// mag - distance from color split plane
if (bubble_number % 2) {
// twist sunwise
tty = t2 + twist * y
} else {
// twist widdershins
tty = -t2 - twist * y
}
rotx = SQRT2 * (wave(tty + 0.25) - 0.5)
rotz = SQRT2 * (wave(tty) - 0.5)
mag = dot(cx, cz, rotx, rotz)
// Hue
if (use_fire_hues) {
// cube fire 3D hue calculation
h = (x + y + z) / 5 + t2
} else {
h1 = phi2_hue(bubble_number, 0)
h2 = phi2_hue(bubble_number, 1)
h = (mag < 0) ? h2 : h1
}
// Saturation
s = 1
// Value
v = smoothstep(0.0, 0.15, bubble_diameter - r) * smoothnotch(0, blend, mag)
hsv(h, s, v)
}
export function render2D(index, x, y) {
// untested
render3D(index, x, y, 0)
}
export function render(index) {
// untested
render3D(index, index / pixelCount, 0, 0)
}
export function toggleFire(isEnabled) {
use_fire_hues = isEnabled
}
function dot(x0, y0, x1, y1) {
return x0 * x1 + y0 * y1
}
function phi2_hue(n, i) {
return frac(0.5 + IPHI2[i] * n)
}
function smoothnotch(center, width, x) {
hw = width / 2
return smoothstep(center, center + hw, x) - smoothstep(center - hw, center, x) + 1
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment