createCanvas(windowWidth, windowHeight, WEBGL)
cam = createCapture(VIDEO)
prev = createFramebuffer({ format: FLOAT })
next = createFramebuffer({ format: FLOAT })
automaton = baseMaterialShader().modify({
'sampler2D prev': () => prev,
'sampler2D cam': () => cam,
'vec2 size': () => [width, height],
'float time': () => millis(),
'float rand': `(vec2 n) {
return fract(sin(dot(n, vec2(12.9898, 4.1414))) * 43758.5453);
'Inputs getPixelInputs': `(Inputs inputs) {
float inVal = texture(prev, inputs.texCoord).x;
float camBrightness = smoothstep(0., 1., texture(cam, inputs.texCoord).x);
for (int i = 0; i < 20; i++) {
float angle = float(i)*0.56789 + rand(inputs.texCoord) + time * 0.001;
float r = camBrightness * (25. + 10. * rand(inputs.texCoord + float(i) * 0.1234 + time*0.1));
vec2 coord = inputs.texCoord + vec2(cos(angle), sin(angle)) * r / size;
avg += texture(prev, coord).x / 20.;
float outVal = (inVal < 0.5
? avg > 0.6 // Rule for if it's dead
: avg < 0.8 && avg > 0.3 // Rule for if it's alive
outVal = mix(inVal, outVal, 0.1);
inputs.color = vec4(vec3(outVal), 1.);
let coord = createVector(0,0)
for (let i = 0; i < 300; i++) {
curveVertex(coord.x, coord.y)
coord = createVector(random(-0.5, 0.5)*width, random(-0.5, 0.5)*height)
circle(mouseX - width/2, mouseY - height/2, 20)
function mousePressed() { drawCircle() }
function mouseDragged() { drawCircle() }
[prev, next] = [next, prev];