Shaders were always the hardest thing for me to grasp in Unity. I've used the engine for years (I built a whole 3D game from scratch for my thesis) but every time I opened a shader file my brain just went quiet. The GPU thinks differently, and I never bothered learning its language.
What changed was a YouTube rabbit hole. Sebastian Lague's simulation videos, Richard Lord's boids on Vimeo, Arsiliath's procedural art. Two weekends later, I had my own versions. Not polished projects. Proof-of-concepts, the kind where you tweak a number at 2am and the screen does something unexpected.
Boids
Craig Reynolds (1986): give each bird three rules. Don't crowd your neighbors, fly roughly the same way as them, stay close to the group. No leader, no plan. Thousands together, and flocking just emerges.
Separation, alignment, cohesion. Everything else (the swirling, the splitting, the organic shapes) is emergent.
My version runs hundreds of thousands of agents. About 1% are predators (red/orange), the rest prey (cyan). Prey follow the three classic rules plus one: see a predator, run. Predators don't flock. They chase.
The behavior nobody wrote is the interesting part. Prey cluster into dense swirling groups, just like real fish schooling near a shark. A predator cuts through, the flock splits and reforms behind it. I never coded "split and regroup." It just happens.
To handle hundreds of thousands of agents at 60 fps, a spatial hash grid divides 3D space into boxes. Each agent only checks its box and the 26 neighbors (3x3x3), dropping cost from O(n^2) to roughly O(n). Rendering uses GPU instancing (one draw call), with the vertex shader stretching meshes by velocity for a bioluminescent streak effect.
Reaction-Diffusion
Alan Turing (1952) proposed that patterns on animal skins (leopard spots, zebra stripes, coral branches) could come from two chemicals spreading at different speeds. One activates growth, the other kills it. Where they meet, patterns form by themselves.
The Gray-Scott model: two chemicals, A and B, on a 2D grid. A spreads fast, B spreads slow. Where they meet, A gets eaten and B grows. A is replenished (feed rate f), B decays (kill rate k). Two equations, every pattern below comes from them:
dA/dt = Da*nabla^2*A - AB^2 + f(1-A)
dB/dt = Db*nabla^2*B + AB^2 - (k+f)B
Change f and k and you get spots that divide like cells, fingerprint stripes, spirals, pulsing blobs, coral branches. Same equation, different knobs.
I added three competing species, each with its own inhibitor, all feeding on the same A, suppressing each other on contact. What comes out is a territorial war: three species carving domains, fighting at borders, sometimes swallowing each other whole.
A few tricks make it look alive: anisotropic diffusion weighted by a rotating noise field so patterns flow like currents, Perlin noise modulating feed/kill rates across the grid, and fake bump-mapped lighting that makes the flat 2D simulation look three-dimensional.
What Stays With Me
The boids shader is about 200 lines. The reaction-diffusion kernel not much longer. Just arithmetic: additions, multiplications, a Laplacian here, a cross product there. Nothing looks like a flock. Nothing looks like coral. Press play and there they are.
I ended up building a browser version of these algorithms so you can play with them yourself.
