Open-source character animation engine, MIT licensed. About 6 months of work. Renders animated mascots in Canvas 2D or WebGL 3D.
For v3.4.1 I wrote 8 elemental shader systems from scratch: fire, water, ice, electricity, earth, nature, light, void. Each one has its own GLSL fragment shader, GPU-instanced models, an overlay that paints onto the mascot mesh, bloom control, and atmospherics. Ice does Snell's law refraction with chromatic dispersion. Electricity is 3-scale 3D Voronoi edge-distance. Fire decouples color from alpha so additive stacking doesn't wash out.
I didn't need 8. I built them to see if the architecture actually repeats. Every element follows the same template: factory, instanced material, overlay shader, gesture configs, registration. 161 gestures across all 8, composed from about 12 archetypes (crown, helix, vortex, barrage, pillar, etc).
The idea is that you can clone one element, swap colors and models, and have something working in days. If you write shaders, go deep on the material. If you don't, the defaults are fine.
Hit shuffle in the demo. Press G for the GPU monitor.
`npm install @joshtol/emotive-engine`
emotiveengine•1h ago
First version was Canvas 2D. Shape morphing and particles. Worked fine for basic emotions but felt limited, so I added a WebGL 3D renderer with custom shaders, bloom, AO, a post-processing chain.
About 6 weeks ago I started the elemental system. Fire first. FBM noise, decoupled color from alpha so additive stacking looks natural instead of washing out. Then water (screen-space refraction, spray particles). By the third element (ice — Snell's law, Voronoi crack lines, chromatic dispersion), the architecture was clearly repeating: factory + instanced GPU material + overlay shader + gesture configs + registration hook. Same five pieces every time.
So I kept going. Electricity, earth, nature, light, void. Eight total in about 6 weeks. Wanted to see if the pattern held or if I'd been fooling myself.
161 gestures later it held. Each gesture is about 20 lines of config composing from archetypes. The factory does the rest.
Shuffle button in the demo shows all 161. Press G for the GPU monitor. `window.profiler` is exposed if you want to poke around.
Happy to talk about any of the shaders, the rendering pipeline, or things I got wrong along the way.