{"id":21146556,"url":"https://github.com/jasonwebb/reaction-diffusion-playground","last_synced_at":"2025-07-09T07:32:37.674Z","repository":{"id":38680530,"uuid":"231689855","full_name":"jasonwebb/reaction-diffusion-playground","owner":"jasonwebb","description":"Interactive reaction-diffusion simulation with organic patterns and behaviors that emerge from the interactions of two chemicals mixed together.","archived":false,"fork":false,"pushed_at":"2023-06-24T23:05:35.000Z","size":42423,"stargazers_count":133,"open_issues_count":2,"forks_count":15,"subscribers_count":8,"default_branch":"master","last_synced_at":"2024-01-29T09:17:26.818Z","etag":null,"topics":["generative-art","javascript","morphogenesis","reaction-diffusion","simulation","threejs"],"latest_commit_sha":null,"homepage":"https://jasonwebb.github.io/reaction-diffusion-playground","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jasonwebb.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2020-01-04T01:05:34.000Z","updated_at":"2024-01-26T01:32:30.000Z","dependencies_parsed_at":"2022-08-25T03:42:17.255Z","dependency_job_id":"3de55162-8fc4-441c-a0b9-dd639b259a4d","html_url":"https://github.com/jasonwebb/reaction-diffusion-playground","commit_stats":{"total_commits":148,"total_committers":1,"mean_commits":148.0,"dds":0.0,"last_synced_commit":"b2abbe7470a17e36545547bdd5f9b2dbfd4fa05c"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jasonwebb%2Freaction-diffusion-playground","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jasonwebb%2Freaction-diffusion-playground/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jasonwebb%2Freaction-diffusion-playground/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jasonwebb%2Freaction-diffusion-playground/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jasonwebb","download_url":"https://codeload.github.com/jasonwebb/reaction-diffusion-playground/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":225492695,"owners_count":17482941,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["generative-art","javascript","morphogenesis","reaction-diffusion","simulation","threejs"],"created_at":"2024-11-20T08:56:50.145Z","updated_at":"2024-11-20T08:56:50.688Z","avatar_url":"https://github.com/jasonwebb.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003ccenter\u003e\u003ca href=\"https://jasonwebb.github.io/reaction-diffusion-playground\" title=\"Go to the playground!\"\u003e\u003cimg src=\"https://raw.githubusercontent.com/jasonwebb/reaction-diffusion-playground/master/images/social-media-preview.jpg\" alt=\"The text 'Reaction Diffusion Playground' in a wavy font over a black background with small green dots.\"\u003e\u003c/a\u003e\u003c/center\u003e\n\n\u003ca href=\"https://raw.githubusercontent.com/jasonwebb/reaction-diffusion-playground/master/images/screenshots/all-screenshots.png\" title=\"Sample screenshots\"\u003e\u003cimg src=\"https://raw.githubusercontent.com/jasonwebb/reaction-diffusion-playground/master/images/screenshots/all-screenshots.png\" alt=\"Grid of 12 screenshots, 4 columns and 3 rows, with the text Reaction Diffusion Playground overlaid on top.\"\u003e\u003c/a\u003e\n\n## What is reaction-diffusion?\nReaction-diffusion is a mathematical model describing how two chemicals might _react_ to each other as they _diffuse_ through a medium together. It was [proposed by Alan Turing in 1952](https://www.dna.caltech.edu/courses/cs191/paperscs191/turing.pdf) as a possible explanation for how the interesting patterns of stripes and spots that are seen on the skin/fur of animals like giraffes and leopards form.\n\nThe reaction-diffusion equations really only describes how the concentrations of the chemicals change over time, which means that all of the interesting patterns and behaviors that we see are [emergent phenomena](https://en.wikipedia.org/wiki/Emergence).\n\nHere's what the equations look like:\n\n![The two reaction-diffusion differential equations with boxes around each part, explained in text bubbles nearby.](https://camo.githubusercontent.com/6a5b7b40467455254ed239cfc966eda29f7cfcafda71e1212f407046396017e8/68747470733a2f2f7777772e6b61726c73696d732e636f6d2f72642d6571756174696f6e2e706e67)\n\n_Credit to [Karl Sims](https://www.karlsims.com/rd.html) for the equation illustration above._\n\nThe most important terms, the ones we'll want to turn into tweakable parameters, are:\n\n* `f` - feed rate. Determines how much of chemical A is added to the system in each iteration.\n* `k` - kill rate. Determines how much of chemical B is removed from the system in each iteration.\n* `dA` - diffusion rate for chemical A. Determines how much chemical A spreads to neighboring cells each iteration.\n* `dB` - diffusion rate for chemical B. Determines how much of chemical B spreads to neighboring cells each iteration.\n\nThe other terms in the equation are usually kept constant, but might be worth playing around with once you are comfortable with the core parameters:\n\n* \u003ccode\u003e∇\u003csup\u003e2\u003c/sup\u003e\u003c/code\u003e - the Laplacian operator. Essentially a single value that represents the chemical concentration of the neighbors to the current cell.\n* \u003ccode\u003eAB\u003csup\u003e2\u003c/sup\u003e\u003c/code\u003e - reaction rate. Note that it is subtracted in the equation for chemical A and added in the equation for chemical B. This is how the chemical reaction converting chemical A into chemical B is modelled.\n* \u003ccode\u003eΔt\u003c/code\u003e - timestep. Using `1.0` here means it runs at \"normal\" speed. Smaller values are like slow motion, and larger values make it run faster. Large values can cause the system to collapse.\n\n[Learn more about reaction-diffusion in my morphogenesis-resources repo.](https://github.com/jasonwebb/morphogenesis-resources#reaction-diffusion)\n\n\n## How does this project work?\nMost reaction-diffusion simulations store values representing the concentrations of the two chemicals (`A` and `B`) in a 2D grid format, then applies the reaction-diffusion equations to each cell in the grid. In this simulation, [data textures](https://threejs.org/docs/index.html#api/en/textures/DataTexture) matching the size of the screen (canvas) are used for the 2D grid, and custom shaders are used to apply the reaction-diffusion equations to each pixel (texel) of these textures.\n\nEach pixel/texel of the simulation data texture encodes the `A` and `B` concentrations for that location in the `R` and `G` channels as a normalized float value (`[0.0-1.0]`).\n\nIn each frame of the simulation, a custom fragment shader (`./glsl/simulationFrag.glsl`) reads the values of the last frame's data texture as an input and applies the reaction-diffusion equation to every pixel. Data textures are rendered back and forth between two [render targets](https://threejs.org/docs/index.html#api/en/renderers/WebGLRenderTarget) many times per frame with a technique called ping-pong to speed things up.\n\nOnce the simulation has been run enough times, another fragment shader (`./glsl/displayFrag.glsl`) reads the latest data texture and maps the chemical concentration data to color values (configurable in the UI).\n\nJust about every option you see in the UI controls one or more [uniforms](https://threejs.org/docs/#api/en/core/Uniform) that get passed to these fragment shaders to influence the reaction-diffusion equations or the way the data texture information is translated into colors.\n\n\n## Using the app\n\n![Annotated screenshot of the UI](https://raw.githubusercontent.com/jasonwebb/reaction-diffusion-playground/master/images/ui-guide.jpg)\n\n### Equation parameters\nEach of the four fundamental parameters of the reaction-diffusion equation (`f`, `k`, `dA`, `dB`), along with the timestep increment, can be changed using the sliders found at the top of the right panel. Change them gradually to avoid collapsing the system.\n\n### Interactive parameter map\n\u003ca href=\"https://raw.githubusercontent.com/jasonwebb/reaction-diffusion-playground/master/images/parameter-map-screenshot.png\"\u003e\u003cimg src=\"https://raw.githubusercontent.com/jasonwebb/reaction-diffusion-playground/master/images/parameter-map-screenshot.png\" alt=\"Screenshot of interactive parameter map\" align=\"right\" width=\"200px\"\u003e\u003c/a\u003eUse this map to navigate through the parameter space easily and find areas with interesting patterns and behaviors. `k` values are plotted along the X axis, `f` values along the Y axis.\n\nUse the crosshairs attached to the mouse position to navigate to a region you're interested in, then click to set the main `f` and `k` values to match where you clicked.\n\nThis map is inspired by the [work of Robert Munafo](http://mrob.com/pub/comp/xmorphia/).\n\n### Seed pattern\nChoose a pattern to use in the first frame of the simulation to seed the reaction. Each pattern has some additional options you can play with for different effects.\n\n* **Circle** - radius.\n* **Square** - width, height, scale, and rotation.\n* **Text** - string, size, rotation.\n* **Image** - upload an image from your computer, fit, scale, rotation.\n\nAlso provides buttons to reset the simulation with the selected pattern or clear the canvas completely.\n\n### Rendering style\nControl how the chemical concentration data is translated into visuals.\n\n### Canvas size\nSet the width and height of the simulation area.\n\nYou can also maximize the canvas to fit the entire viewport.\n\n### Global actions\nButtons to pause/play or export an image of the current state of the simulation area.\n\n### Style map\nUpload an image from your computer to vary the `f`, `k`, `dA`, and `dB` values based on the brightness value of each pixel. The secondary values you choose here will become endstops in an interpolation calculation with the primary values (on the right UI pane). In other words, the four equation parameters will be interpolated to be between the original parameter values (on the right pane) and these secondary parameter values (left pane) using the brightness value of each pixel.\n\nIn addition to the reaction-diffusion equation parameters, you can also adjust the uniform scale, rotation, and X/Y offset of the image for different effects.\n\nYour image will automatically be scaled to fit the entire canvas, so it may be stretched. Resize your image to match the width and height of the canvas (or at least its aspect ratio) to minimize distortion.\n\n### Bias\nNormally diffusion occurs evenly in all directions due to the default radially symmetrical Laplacian stencil. Using this X/Y pad you can \"weight\" this stencil to cause diffusion to favor one particular direction.\n\n### Keyboard controls\n\n* `Space` = pause/play.\n* `r` = reset using the currently-selected seed pattern.\n* `s` = save an image of the current canvas content.\n* `u` = show/hide the UI.\n\n### Mouse controls\nClick and drag anywhere on the canvas to increase the concentration of the `B` chemical around the mouse position.\n\nUse your mouse wheel to change the diameter of the area affected by clicking / dragging. The size of the brush is indicated with a circle that follows the mouse.\n\n### MIDI controls\nIf you have an Akai LPD8 Wireless or a Novation Launch Control XL, mappings are provided for the various pads and knobs. See `./js/midi.js` for details.\n\n\n## Technical notes\n\n### Setting up and running locally\n1. Run `npm install` to get all packages.\n2. Run `npm run serve` to start up Webpack and launch the application in a live-reloading browser window.\n\n### Technologies used\n* [ThreeJS](https://threejs.org/) for WebGL conveniences like running custom shaders and managing uniforms.\n* [GLSL](https://www.khronos.org/opengl/wiki/Core_Language_(GLSL)) shaders for running the reaction-diffusion equation for every pixel of the screen and rendering.\n* Vanilla ES6 JavaScript.\n* MIDI support using [WebMidi.js](https://github.com/djipco/webmidi).\n* [Webpack](https://webpack.js.org/) build system with live-reloading dev server.\n* [Github Pages](https://pages.github.com/) to serve the files.\n\n### Architecture and file structure\n\n#### JavaScript\nThe most important file is `entry.js` - that's where the environment, UI, and the simulation itself are set up, and where the main update loop is. It sets up a ThreeJS environment with an orthographic camera and a scene containing a plane mesh that is oriented perpendicular to the camera so that it appears 2D.\n\nIn the `./js` folder are a bunch of modules split into files (all referenced in one way or another through `entry.js`):\n\n* `export.js` - helper functions for downloading the canvas content as an image file.\n* `firstFrame.js` - helper functions for seeding the first frame of the simulation with interesting patterns.\n* `keyboard.js` - global keyboard commands.\n* `map.js` - handles the modal dialog containing the interactive parameter map picker.\n* `materials.js` - ThreeJS materials that associate uniforms with custom shaders. These get attached to the render targets and plane mesh to run and render the simulation.\n* `midi.js` - mappings for MIDI controllers (Akai LPD8 Wireless and Novation Launch Control XL).\n* `mouse.js` - mouse controls.\n* `parameterMetadata.js` - limits and initial values for each of the parameters controlled by the UI.\n* `parameterPresets.js` - presets for the main equation parameters (`f`, `k`, `dA`, `dB`).\n* `parameterValues.js` - variables controlled by the UI.\n* `renderTargets.js` - invisible buffers that allow us run the simulation multiple times per frame while only rendering data to the screen once.\n* `stats.js` - FPS and iteration counters.\n* `ui.js` - UI built with [Tweakpane](https://cocopon.github.io/tweakpane/).\n  * `ui/left-pane.js` - left side of the UI, with style map and bias controls.\n  * `ui/right-pane.js` - right side of the UI, with equation parameters, seeding, and rendering options.\n* `uniforms.js` - variables that are passed into shaders.\n\n#### GLSL\n\nIn the `./glsl` folder are:\n\n* `displayFrag.glsl` - turns chemical concentration data textures into colorful pixels for the screen using a variety of techniques.\n* `displayVert.glsl` - passes vertex data onto the `displayFrag.glsl` shader with no modifications.\n* `passthroughFrag.glsl` - takes a passed texture and renders it as-is to the render targets to create a first frame of data for the simulation to work with.\n* `passthroughVert.glsl` - passes vertex data onto the `displayFrag.glsl` shader with no modifications.\n* `simulationFrag.glsl` - takes a passed texture of encoded chemical concentration data and applies the reaction-diffusion equation to each pixel, spitting out a new texture of data to be rendered to the screen or fed into another simulation pass.\n* `simulationVert.glsl` - passes vertex data along with precomputed texel neighbor coordinates so that they can be automatically interpolated for use in the frag shader.\n\n## References\n\n### Fundamentals\nThese papers, articles, and videos helped me understand how the reaction-diffusion algorithm works.\n\n* [The Chemical Basis of Morphogenesis](http://www.dna.caltech.edu/courses/cs191/paperscs191/turing.pdf) (PDF) paper by Alan Turing (1952)\n* [Reaction-Diffusion Tutorial](https://www.karlsims.com/rd.html) by Karl Sims\n* [Reaction-Diffusion by the Gray-Scott Model: Pearson's Parametrization](https://mrob.com/pub/comp/xmorphia/) by Robert Munafo (mrob)\n* [Reaction Diffusion: A Visual Explanation](https://www.youtube.com/watch?v=LMzYrsfTiEw) by Arsiliath\n* [Coding Challenge #13: Reaction Diffusion Algorithm in p5.js](https://www.youtube.com/watch?v=BV9ny785UNc) by Daniel Shiffman ([Github repo](https://github.com/CodingTrain/website/tree/master/CodingChallenges/CC_013_ReactionDiffusion) with both p5.js and Processing source code)\n\n### Code\nThese articles, repos, and project pages helped me figure out how to build my implementation.\n\n* [Gray-Scott - JavaScript experiments](https://github.com/pmneila/jsexp) by @pmneila\n* [Processing: Reaction Diffusion Halftone patterns](https://vimeo.com/233530691) by Ignazio Lucenti\n* [Reaction Diffusion](https://www.redblobgames.com/x/1905-reaction-diffusion/) (JavaScript + WebGL) by Red Blob Games\n* [Reaction Diffusion](https://kaesve.nl/projects/reaction-diffusion/readme.html) by Ken Voskuil (look in the DOM)\n* [Reaction-Diffusion Simulation in Three.js](https://github.com/colejd/Reaction-Diffusion-ThreeJS) (JavaScript + ThreeJS) by Jonathan Cole\n\n### Creative\nThese projects inspired me to explore some of the creative possibilities of reaction-diffusion.\n\n* [3D Printed Reaction Diffusion Patterns](https://www.instructables.com/id/3D-Printed-Reaction-Diffusion-Patterns/) Instructable by Reza Ali\n* [Silhouect](https://cacheflowe.com/code/installation/silhouect) by Justin Gitlin (@cacheflowe)\n* [Coral Cup](https://n-e-r-v-o-u-s.com/blog/?p=8222) by Nervous System\n* [Reaction Lamps](https://n-e-r-v-o-u-s.com/projects/albums/reaction-products/) by Nervous System\n* [Reaction Table](https://n-e-r-v-o-u-s.com/projects/albums/reaction-table/) by Nervous System\n* [Reaction shelf](https://n-e-r-v-o-u-s.com/blog/?p=992) by Nervous System","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjasonwebb%2Freaction-diffusion-playground","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjasonwebb%2Freaction-diffusion-playground","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjasonwebb%2Freaction-diffusion-playground/lists"}