Fragmentum

A procedural animation ported from Shadertoy.

View live demoRaw .ts
/**
 * Procedural 3D animation (ported from Shadertoy). Uses u_time uniform
 * for animation. Spacebar to pause/play.
 */
import ShaderPad from 'shaderpad';

import type { ExampleContext } from '@/examples/runtime';

const fragmentShaderSrc = `#version 300 es
precision highp float;

// Built-in variables.
in vec2 v_uv;
uniform float u_time;
uniform vec2 u_resolution;

out vec4 outColor;

// Fragmentum by Jaenam
// https://www.shadertoy.com/view/t3SyzV

void main() {
	vec2 I = gl_FragCoord.xy;
	vec4 O = vec4(0.0);
	float i,d,s;
    vec2 r = u_resolution;
	vec3 p;
	mat2 R = mat2(cos(u_time/2.+vec4(0,33,11,0)));

	for(O*=i; i++<1e2; O+=max(1.3*sin(vec4(1,2,3,1)+i*.3)/s,-length(p*p)))
		p = vec3((I+I - r.xy)/r.y*d*R, d-8.), p.xz*=R,
		d+=s=.012+.07*abs(max(sin(length(fract(p)*p)),length(p)-4.)-i/1e2);  

	outColor=tanh(O*O/8e5);
}`;

export async function init({ mount }: ExampleContext) {
	const canvas = document.createElement('canvas');
	canvas.style.position = 'fixed';
	canvas.height = canvas.width = 512;
	canvas.style.left = canvas.style.top = '50%';
	canvas.style.transform = 'translate(-50%, -50%)';
	mount.appendChild(canvas);
	const shader = new ShaderPad(fragmentShaderSrc, { canvas });
	let isPlaying = true;
	shader.play();

	const keydownHandler = (e: KeyboardEvent) => {
		if (e.key === ' ') {
			isPlaying = !isPlaying;
			isPlaying ? shader.play() : shader.pause();
		}
	};
	document.addEventListener('keydown', keydownHandler);

	return () => {
		document.removeEventListener('keydown', keydownHandler);
		shader.destroy();
		canvas.remove();
	};
}