Tech News
← Back to articles

Show HN: Cellarium: A Playground for Cellular Automata

read original related products more articles

Cellarium

Note: This is a 100% vibe-coded experiment

GPU-accelerated cellular automata in Rust. Write cell behavior in a subset of Rust; a proc macro cross-compiles it to WGSL shaders that run entirely on the GPU via wgpu.

Quick Start

use cellarium :: prelude :: * ; # [ derive ( CellState , Default ) ] struct Life { alive : f32 , } # [ cell ( neighborhood = moore ) ] impl Cell for Life { fn init ( x : f32 , y : f32 , w : f32 , h : f32 ) -> Self { let hash = ( ( x * 12.9898 + y * 78.233 ) . sin ( ) * 43758.5453 ) . fract ( ) ; Self { alive : if hash > 0.6 { 1.0 } else { 0.0 } } } fn update ( self , nb : Neighbors ) -> Self { let n = nb . count ( |c| c . alive > 0.5 ) ; let alive = if self . alive > 0.5 && ( n == 2.0 || n == 3.0 ) { 1.0 } else if self . alive < 0.5 && n == 3.0 { 1.0 } else { 0.0 } ; Self { alive } } fn view ( self ) -> Color { if self . alive > 0.5 { Color :: WHITE } else { Color :: BLACK } } } fn main ( ) { Simulation :: < Life > :: new ( 2048 , 2048 ) . title ( "Game of Life" ) . run ( ) ; }

cargo run --example game_of_life

How It Works

#[derive(CellState)] packs your struct fields into GPU textures (rgba32float, 4 channels each). Fields are never split across textures. #[cell] compiles your update , view , and optional init methods into WGSL fragment shaders at compile time. Simulation::run() opens a window and runs the simulation loop on the GPU — all cells update simultaneously each tick via double-buffered render passes.

All cells read from the same tick-N state and write to tick-N+1. No cell ever sees another cell's in-progress update.

Defining Cell State

... continue reading