Last active
June 17, 2025 19:38
-
-
Save kbob/aa03b9e065c641ce6c100962083032e7 to your computer and use it in GitHub Desktop.
Bubble Phi Pixelblaze shader
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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