97

Abyssal Caustics

A high-performance WebGPU caustics simulation layering multiple Voronoi noise fields.

60 FPS WebGPU

WGSL Shader Source

struct Uniforms { resolution: vec2f, time: f32, padding: f32, mouse: vec2f, speed: f32, scale: f32, }
@group(0) @binding(0) var<uniform> u: Uniforms;

@vertex
fn vs_main(@builtin(vertex_index) vertexIndex: u32) -> @builtin(position) vec4f {
  let pos = array(vec2f(-1.0, -1.0), vec2f( 3.0, -1.0), vec2f(-1.0,  3.0));
  return vec4f(pos[vertexIndex], 0.0, 1.0);
}

fn hash22(p: vec2f) -> vec2f {
  var p3 = fract(vec3f(p.xyx) * vec3f(0.1031, 0.1030, 0.0973));
  p3 = p3 + dot(p3, p3.yzx + 33.33);
  return fract((p3.xx + p3.yz) * p3.zy);
}

fn voronoi(x: vec2f, time: f32) -> vec2f {
  let n = floor(x);
  let f = fract(x);
  var m = vec2f(8.0);
  for(var j = -1; j <= 1; j++) {
    for(var i = -1; i <= 1; i++) {
      let g = vec2f(f32(i), f32(j));
      let o = hash22(n + g);
      let pos = 0.5 + 0.5 * sin(time + 6.2831 * o);
      let d = length(g - f + pos);
      if(d < m.x) { m.x = d; m.y = o.x; }
    }
  }
  return m;
}

@fragment
fn fs_main(@builtin(position) fragCoord: vec4f) -> @location(0) vec4f {
  let uv = fragCoord.xy / u.resolution;
  let t = u.time * u.speed * 0.5;
  let mouseOffset = (u.mouse - 0.5) * 2.0;
  var p = (uv - 0.5) * u.scale + mouseOffset;
  p.x *= u.resolution.x / u.resolution.y;
  
  var v1 = voronoi(p * 2.0 + t, t);
  var v2 = voronoi(p * 4.0 - t * 1.5, t * 1.2);
  var v3 = voronoi(p * 8.0 + vec2f(sin(t), cos(t)), t * 0.8);
  
  let caustics = pow(1.0 - v1.x, 3.0) + pow(1.0 - v2.x, 2.0) * 0.5 + pow(1.0 - v3.x, 2.0) * 0.25;
  let baseColor = vec3f(0.05, 0.1, 0.2);
  let lightColor = vec3f(0.3, 0.7, 1.0) * caustics;
  let finalColor = baseColor + lightColor;
  
  return vec4f(finalColor, 1.0);
}

Properties

#webgpu#caustics#metalforge#fluid
Author: Math Art Core Target: 60 FPS
ESC
↑↓ Navigate Select
101 Mathematical Artworks

Support the Project

Keep mathematical creative coding alive & open source

Or via Direct Payoneer ($0 Fee)
Payoneer Customer ID: $0 Fee Direct
24076084

💡 Payoneer app: Go to Pay → Pay to recipient → Enter ID 24076084.

Thank you for supporting generative mathematical animations! ✨