export const PARAMS = {
density: { value: 6.0, min: 1.5, max: 20, step: 0.1, label: "Cell Density", folder: "Structure" },
metric: { value: "F1", options: ["F1", "F2-F1", "F2*F1"], label: "Distance Metric", folder: "Structure" },
speed: { value: 0.2, min: 0, max: 1.5, step: 0.01, label: "Animation Speed", folder: "Behavior" },
glow: { value: 0.3, min: 0, max: 1.5, step: 0.01, label: "Glow", folder: "Appearance" },
hue: { value: 280, min: 0, max: 360, step: 1, label: "Base Hue", folder: "Appearance" },
};
export function shaderUniforms(params) {
const metricMap = { 'F1': 0, 'F2-F1': 1, 'F2*F1': 2 };
return {
u_density: { value: params.density },
u_speed: { value: params.speed },
u_glow: { value: params.glow },
u_hue: { value: params.hue },
u_metric: { value: metricMap[params.metric] ?? 0 },
};
}
export function shaderAnimate(uniforms, params) {
uniforms.u_density.value = params.density;
uniforms.u_speed.value = params.speed;
uniforms.u_glow.value = params.glow;
uniforms.u_hue.value = params.hue;
const metricMap = { 'F1': 0, 'F2-F1': 1, 'F2*F1': 2 };
uniforms.u_metric.value = metricMap[params.metric] ?? 0;
}
export function fragmentShader() {
return `
uniform float u_time;
uniform vec2 u_resolution;
uniform float u_density;
uniform float u_speed;
uniform float u_glow;
uniform float u_hue;
uniform int u_metric;
vec3 hash33(vec3 p) {
p = vec3(
dot(p, vec3(127.1, 311.7, 74.7)),
dot(p, vec3(269.5, 183.3, 246.1)),
dot(p, vec3(113.5, 271.9, 124.6))
);
return -1.0 + 2.0 * fract(sin(p) * 43758.5453123);
}
vec2 voronoi3(vec3 p) {
vec3 i = floor(p);
vec3 f = fract(p);
float F1 = 999.0, F2 = 999.0;
for (int z=-1; z<=1; z++) for (int y=-1; y<=1; y++) for (int x=-1; x<=1; x++) {
vec3 g = vec3(float(x), float(y), float(z));
vec3 o = 0.5 + 0.5 * sin(u_time * u_speed + 6.2831 * hash33(i + g));
float d = length(g + o - f);
if (d < F1) { F2 = F1; F1 = d; } else if (d < F2) { F2 = d; }
}
return vec2(F1, F2);
}
vec3 palette(float t, float baseHue) {
vec3 a = vec3(0.5), b = vec3(0.5), c = vec3(1.0);
vec3 d = vec3(0.0, 0.10, 0.20) + baseHue / 360.0;
return a + b * cos(6.2831853 * (c * t + d));
}
void main() {
vec2 uv = (gl_FragCoord.xy - 0.5 * u_resolution) / u_resolution.y;
vec3 p = vec3(uv * u_density, u_time * u_speed * 0.3);
vec2 v = voronoi3(p);
float f = u_metric == 0 ? v.x : (u_metric == 1 ? (v.y - v.x) : v.x * v.y);
vec3 col = palette(f * 0.7, u_hue);
col += u_glow * smoothstep(0.0, 0.05, v.y - v.x);
col = pow(col, vec3(1.0 / 2.2));
gl_FragColor = vec4(col, 1.0);
}
`;
}