palette-field@0.1.0
Palette field
Flow without geometry: one fBM field warps another, and the result indexes a cosine palette. OKLab mixing sinks the edges into black.
Controls
#a28baa
#ad95a6
Imports
What this entry shader composes; every module resolves from npm.
import { fbmSimplex2d } from "@vgpu/wgsl-std/noise/simplex";
import { cosinePalette } from "@vshaders/color/palette";
import { mixOklab } from "@vshaders/color/oklab";
import { linearToSrgb3 } from "@vgpu/wgsl-std/color";
Source
The full entry shader, palette-field.wgsl. Copy it and it is yours.
// effect 003 · palette-field — domain-warped fBM driving a cosine palette.
// Flow without geometry: one noise field warps another, and the result
// indexes a palette. OKLab sinks the edges into the page ink.
// Works in linear light; encodes to sRGB once at the end.
import { fbmSimplex2d } from "@vgpu/wgsl-std/noise/simplex";
import { cosinePalette } from "@vshaders/color/palette";
import { mixOklab } from "@vshaders/color/oklab";
import { linearToSrgb3 } from "@vgpu/wgsl-std/color";
// Tunable members follow resolution/time. Defaults live in lib/effects.ts and
// must be set by the runner: an unset uniform member reads as zero. Members are
// ordered so each vec3f lands on a 16-byte boundary with an f32 in its pad.
struct Uniforms {
resolution: vec2f,
time: f32,
// Noise frequency: how many field features fit across the card.
scale: f32,
// Cosine palette mean color, linear light.
bias: vec3f,
// Multiplies time in every animation term.
speed: f32,
// Cosine palette per-channel swing around the bias, linear light.
amplitude: vec3f,
}
@group(0) @binding(0) var<uniform> uniforms: Uniforms;
@fragment
fn main(@builtin(position) position: vec4f) -> @location(0) vec4f {
let res = max(uniforms.resolution, vec2f(1.0));
let uv = position.xy / res;
let aspect = res.x / res.y;
let p = (uv - vec2f(0.5)) * vec2f(aspect, 1.0);
let t = uniforms.time * 0.06 * uniforms.speed;
let drift = fbmSimplex2d(p * uniforms.scale + vec2f(0.0, t), 4, 2.0, 0.5);
let warped = fbmSimplex2d(p * uniforms.scale + vec2f(drift * 0.9, -t * 0.7), 4, 2.0, 0.5);
let base = cosinePalette(
warped * 0.55 + t * 0.35,
uniforms.bias,
uniforms.amplitude,
vec3f(1.0),
vec3f(0.00, 0.15, 0.42)
);
// Sink toward the page ink at the card's edges.
let vignette = smoothstep(1.05, 0.35, length(p));
let ink = vec3f(0.006, 0.007, 0.012);
let color = mixOklab(ink, max(base, vec3f(0.0)), 0.22 + 0.78 * vignette);
return vec4f(linearToSrgb3(clamp(color, vec3f(0.0), vec3f(1.0))), 1.0);
}