Sine wave cube in less than 1K

Remake of a cube rendered with sine waves

I came across this wonderful codepen by Jon Kantner, which in turn is a remake of this dribble by Mark Edwards/Bjango, so the most logical idea was to remake it again in less than 1024 bytes.

Roll in Signed Distance Functions and Ray Marching. A cube is probably the second most trivial 3d primitive after a sphere, so the SDF is relatively easy. Then rotate every frame, ray march to work out colours from a fixed light source, and set an array of brightness. Then sample that array to work out the intensity for drawing sine waves, where the intensity affects the amplitude of the wave.

The renderer on this page has 2x canvases, the pixel shader-esque version, and the sine wave version which is the final product. Press the ‘Toggle renderer’ button to… wait for it… toggle them. In the sine wave version, samples are taken every n lines (20px?), so it’s a known issue that 90%+ of the calculations are pointless in the y axis.

I used terser from the get go to minify code, but after getting everything rendering, just a 3d cube without any sine waves, terser could only terse it down to ~3.5K. Then began the hand minification, and after lots of passes I reached the 1024 byte goal. No real hacks were needed this time; often whilst code golfing we abuse undeclared variables and many, many other NSFW tricks.

This was definitely AI enhanced, using Cursor to get some of the 3d functions up and running since I’m lazy.

Compressed code (1011 bytes):

let e=.01,A=Math.abs,C=Math.cos,M=Math.max,m=Math.min,S=Math.sin,_=Math.sqrt,c=(e,t,l)=>{let r=A(e)-1,n=A(t)-1,a=A(l)-1,o=M(r,0),c=M(n,0),f=M(a,0);return _(o*o+c*c+f*f)+m(M(r,M(n,a)),0)},r=(e,t,l,r,M)=>{let n=C(M),a=S(M),o=e*n+l*a,c=-e*a+l*n,f=C(r),i=S(r);return[o,t*f-c*i,t*i+c*f]},n=(t,l,r)=>{let M=c(t+e,l,r)-c(t-e,l,r),n=c(t,l+e,r)-c(t,l-e,r),a=c(t,l,r+e)-c(t,l,r-e),o=_(M*M+n*n+a*a);return[M/o,n/o,a/o]},z=(e,t,l,M,a)=>{let o=0;for(;o<99;){let f=e*o,i=t*o,h=l*o-5,[m,s,S]=r(f,i,h,M,a),X=c(m,s,S);if(X<.002)return n(m,s,S);o+=X}},d=e=>{let t=5e-4*e,l=89e-5*e,r=400,n=[];for(let e=0;e<16e4;e++){let a=.5*(e%r/r*2-1),o=.5*(1-~~(e/r)/r*2),c=1,f=_(a*a+o*o+c*c);a/=f,o/=f,c/=f;let i=z(a,o,c,t,l);if(i){let[r,a,o]=i,c=C(-t),f=a*S(-t)+o*c,h=C(-l),m=S(-l),s=M(0,-(r*h+f*m));n[e]=.2+.8*s}}X.fillRect(0,0,r,r),X.strokeStyle="#fff";for(let t=0;t<20;t++){let l=20*(t+.5);X.beginPath();for(let t=0;t<r;t++){let M=(n[t+l*r]||0)*r*.03,a=l+S(.6*t+.004*e)*M;t?X.lineTo(t,a):X.moveTo(t,a)}X.stroke()}requestAnimationFrame(d)}

Expanded code:

let e = 0.01, // epsilon
	A = Math.abs,
	C = Math.cos,
	M = Math.max,
	m = Math.min,
	S = Math.sin,
	_ = Math.sqrt,
	// cube:
	c = (x, y, z) => {
		let px = A(x) - 1; // last number is cube size
		let py = A(y) - 1;
		let pz = A(z) - 1;

		let qx = M(px, 0);
		let qy = M(py, 0);
		let qz = M(pz, 0);

		return _(qx * qx + qy * qy + qz * qz) + m(M(px, M(py, pz)), 0);
	},
	// rotate:
	r = (x, y, z, rotX, rotY) => {
		let cosY = C(rotY),
			sinY = S(rotY),
			x1 = x * cosY + z * sinY,
			z1 = -x * sinY + z * cosY,
			cosX = C(rotX),
			sinX = S(rotX);
		return [x1, y * cosX - z1 * sinX, y * sinX + z1 * cosX];
	},
	// Calculate normal using finite differences:
	n = (x, y, z) => {
		let dx = c(x + e, y, z) - c(x - e, y, z);
		let dy = c(x, y + e, z) - c(x, y - e, z);
		let dz = c(x, y, z + e) - c(x, y, z - e);

		let len = _(dx * dx + dy * dy + dz * dz);
		return [dx / len, dy / len, dz / len];
	},
	// Ray marching function:
	z = (rx, ry, rz, rotationX, rotationY) => {
		let t = 0;
		while (t < 99) {
			let x = rx * t,
				y = ry * t,
				z =
					-5 + // camera position z
					rz * t;

			// Rotate the point to match camera rotation
			let [px, py, pz] = r(x, y, z, rotationX, rotationY);

			// Calculate distance to cube
			let dist = c(px, py, pz);

			if (dist < 0.002) {
				// Hit! Calculate normal for shading
				return n(px, py, pz);
			}
			t += dist;
		}
		// return nothing if no hit
	},
	// Render function:
	d = (time) => {
		let rotationX = time * 0.0005,
			rotationY = time * 0.00089;
		let size = 400;

		let tanFovAspect = 0.5; // tan(field of vision / 2);
		let intensities = [];

		for (let i = 0; i < size * size; i++) {
			let x = i % size;
			let y = ~~(i / size);
			// Convert pixel coordinates to normalized device coordinates
			let ndcX = (x / size) * 2 - 1;
			let ndcY = 1 - (y / size) * 2;

			// Calculate ray direction
			let rx =
					tanFovAspect *
					// aspect * // assuming an aspect of 1, ie square canvas, no need for this
					ndcX,
				ry = tanFovAspect * ndcY,
				rz = 1;

			// Normalize ray direction
			let len = _(rx * rx + ry * ry + rz * rz);
			rx /= len;
			ry /= len;
			rz /= len;

			// Ray march
			let result = z(rx, ry, rz, rotationX, rotationY);

			// pixel esque shader pixel index:
			// let idx = i * 4;

			if (result) {
				// Rotate normal back to world space (inverse: -X then -Y)
				let [nx, ny, nz] = result;
				let cosX = C(-rotationX),
					sinX = S(-rotationX);
				let z1 = ny * sinX + nz * cosX;
				let cosY = C(-rotationY),
					sinY = S(-rotationY);
				let worldNormal = nx * cosY + z1 * sinY;
				let dot = M(0, -worldNormal);

				// lighting for pixel esque shader:
				/*
				let ambient = 0.2;
				let intensity = ambient + (1 - ambient) * dot;

        data[idx] = 100 * intensity; // R
				data[idx + 1] = 200 * intensity; // G
				data[idx + 2] = 255 * intensity; // B
				data[idx + 3] = 255; // A
        //*/

				intensities[i] = 0.2 + 0.8 * dot;
			} else {
				// Background for pixel esque shader:
				/*
				let bgIntensity = 0.1;
				data[idx] = bgIntensity * 50;
				data[idx + 1] = bgIntensity * 50;
				data[idx + 2] = bgIntensity * 60;
				data[idx + 3] = 255;
        //*/

				// intensities[i] = 0; // no need, leave it empty
			}
		}

		// pixel esque shader:
		// ctx.putImageData(imageData, 0, 0);

		// Draw horizontal sine waves
		X.fillRect(0, 0, size, size);
		X.strokeStyle = "#fff";
		let numWaves = 20;
		let waveSpacing = size / numWaves;

		for (let w = 0; w < numWaves; w++) {
			let y = (w + 0.5) * waveSpacing;
			// Draw sine wave with amplitude
			X.beginPath();
			for (let x = 0; x < size; x++) {
				const intense = intensities[x + y * size] || 0;
				let amplitude = intense * size * 0.03;
				let waveY = y + S(x * 0.6 + time * 0.004) * amplitude;
				if (x) {
					X.lineTo(x, waveY);
				} else {
					X.moveTo(x, waveY);
				}
			}
			X.stroke();
		}

		requestAnimationFrame(d);
	};

Codepen demo

Complete src