<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: naman</title>
    <description>The latest articles on DEV Community by naman (@n1m21n).</description>
    <link>https://dev.to/n1m21n</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4190043%2Fbc1e112c-b921-44eb-9a03-aad16923dd4c.jpg</url>
      <title>DEV Community: naman</title>
      <link>https://dev.to/n1m21n</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/n1m21n"/>
    <language>en</language>
    <item>
      <title>Every note node in Infinite: generative arpeggiators and algorithmic sequencing</title>
      <dc:creator>naman</dc:creator>
      <pubDate>Wed, 11 Nov 2026 13:15:29 +0000</pubDate>
      <link>https://dev.to/n1m21n/every-note-node-in-infinite-generative-arpeggiators-and-algorithmic-sequencing-418m</link>
      <guid>https://dev.to/n1m21n/every-note-node-in-infinite-generative-arpeggiators-and-algorithmic-sequencing-418m</guid>
      <description>&lt;p&gt;In traditional music production environments, MIDI is treated as a static piano roll. Notes are clicked onto a grid, quantised rigidly, and routed through a single linear track directly into a virtual instrument.&lt;/p&gt;

&lt;p&gt;Infinite re-imagines MIDI and musical timing as an open, modular stream of discrete note events. Notes are not passive rows in an arrangement; they are first-class signals that flow through cables, branch across splitters, undergo algorithmic transformations, and drive both sound engines and 3D visual geometry in real time.&lt;/p&gt;

&lt;p&gt;Infinite provides twenty-four dedicated note processing nodes, spanning hardware input bridges, rhythmic arpeggiators, Markov-chain phrase predictors, physics-based trigger simulations, scale quantizers, and programmable algorithmic note generators.&lt;/p&gt;

&lt;p&gt;Here is an architectural guide to every note node in Infinite, how they process musical events, and how to patch generative music systems on the canvas.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. MIDI Notes: hardware controller &amp;amp; MPE input bridge
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;MIDI Notes&lt;/strong&gt; node connects physical MIDI keyboards, pad controllers, and MPE (MIDI Polyphonic Expression) devices to the Infinite canvas.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/..%2Fassets%2Fnodes%2Fhd%2Fmidi-notes.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/..%2Fassets%2Fnodes%2Fhd%2Fmidi-notes.webp" alt="MIDI Notes node in Infinite" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  How it works
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Multi-channel routing&lt;/strong&gt;: Listens on all channels (Omni) or binds to a specific MIDI channel (&lt;code&gt;1&lt;/code&gt; to &lt;code&gt;16&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;MPE support&lt;/strong&gt;: Full per-note polyphonic pitch bend, slide, and pressure/aftertouch tracking.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Port activity visualization&lt;/strong&gt;: Real-time visual LEDs displaying active note-on gates, polyphonic voice count, and pitch numbers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Event stream outputs&lt;/strong&gt;: Outputs polyphonic note events cleanly buffered for sample-accurate scheduling.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Try it
&lt;/h3&gt;

&lt;p&gt;Connect a USB MIDI keyboard, wire MIDI Notes into an Analog synth, and route per-note MPE pressure into the filter cutoff knob.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;MIDI Notes -&amp;gt; Analog -&amp;gt; Audio Out
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  2. Keyboard: interactive on-screen playable piano
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;Keyboard&lt;/strong&gt; node provides a playable virtual piano keyboard directly inside the node canvas, supporting mouse clicks, multi-touch, and computer QWERTY keyboard typing.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/..%2Fassets%2Fnodes%2Fhd%2Fkeyboard.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/..%2Fassets%2Fnodes%2Fhd%2Fkeyboard.webp" alt="Keyboard node in Infinite" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  How it works
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Octave range navigation&lt;/strong&gt;: Configurable key span with quick octave shift controls.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Musical scale highlighting&lt;/strong&gt;: Highlights active scale notes across white and black keys, preventing accidental off-key inputs during live performance.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Velocity sensitivity&lt;/strong&gt;: Clicking near the bottom of a key triggers high velocity (up to 127), while clicking near the top triggers soft pianissimo notes.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Try it
&lt;/h3&gt;

&lt;p&gt;Select the Dorian scale in the inspector, highlight the scale keys, and jam melodies using your computer keyboard without opening external controllers.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Keyboard -&amp;gt; FM -&amp;gt; Reverb -&amp;gt; Audio Out
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  3. Note Filter: range, channel, and velocity gate
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;Note Filter&lt;/strong&gt; node acts as a selective filter for incoming note streams, allowing only notes meeting specific musical criteria to pass downstream.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/..%2Fassets%2Fnodes%2Fhd%2Fnote-filter.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/..%2Fassets%2Fnodes%2Fhd%2Fnote-filter.webp" alt="Note Filter node in Infinite" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  How it works
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Pitch key zones&lt;/strong&gt;: Set minimum and maximum note limits (e.g. &lt;code&gt;C1&lt;/code&gt; to &lt;code&gt;B2&lt;/code&gt; for bass, &lt;code&gt;C3&lt;/code&gt; to &lt;code&gt;C6&lt;/code&gt; for leads) to create multi-instrument keyboard splits.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Velocity window&lt;/strong&gt;: Filters notes by dynamics, passing only ghost notes (low velocity) or accents (high velocity).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Channel filtering&lt;/strong&gt;: Strips out or isolates specific MIDI channels from multi-timbral controllers.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Try it
&lt;/h3&gt;

&lt;p&gt;Wire one MIDI Notes output into two Note Filters: set filter 1 to notes below C3 for a sub bass synth, and filter 2 to notes above C3 for a shimmering lead.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;MIDI Notes -&amp;gt; Note Filter (Low) -&amp;gt; Analog (Bass)
MIDI Notes -&amp;gt; Note Filter (High) -&amp;gt; Wavetable (Lead)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  4. Note Transpose: chromatic and scale-aware pitch shifting
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;Note Transpose&lt;/strong&gt; node shifts the pitch of incoming note events by octaves and semitones while optionally constraining the shifted notes to a selected musical scale.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/..%2Fassets%2Fnodes%2Fhd%2Fnote-transpose.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/..%2Fassets%2Fnodes%2Fhd%2Fnote-transpose.webp" alt="Note Transpose node in Infinite" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  How it works
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Octave &amp;amp; semitone offsets&lt;/strong&gt;: Shift notes up or down by up to 4 octaves and 12 semitones.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Modulatable transposition&lt;/strong&gt;: The semitone parameter is modulatable, allowing an LFO or step sequencer to modulate chord progressions automatically.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scale snapping&lt;/strong&gt;: Forces transposed notes onto the nearest valid scale degree to prevent dissonant pitch clashes.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Try it
&lt;/h3&gt;

&lt;p&gt;Modulate Note Transpose with a Slow Step Sequencer to shift an arpeggio across root, fourth, and fifth chords every four bars.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Arpeggiator -&amp;gt; Note Transpose -&amp;gt; Wavetable -&amp;gt; Audio Out
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  5. Pitch Bend: expressive pitch deflection router
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;Pitch Bend&lt;/strong&gt; node routes and scales continuous pitch bend wheel messages and modulation signals for connected synthesizers.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/..%2Fassets%2Fnodes%2Fhd%2Fpitch-bend.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/..%2Fassets%2Fnodes%2Fhd%2Fpitch-bend.webp" alt="Pitch Bend node in Infinite" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  How it works
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Configurable bend range&lt;/strong&gt;: Adjust the pitch bend semitone window from 1 semitone to a full octave (&lt;code&gt;-12&lt;/code&gt; to &lt;code&gt;+12&lt;/code&gt; semitones).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Bipolar modulation input&lt;/strong&gt;: Accepts LFO or envelope modulation to produce automatic vibrato and dive bombs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Smoothing&lt;/strong&gt;: Built-in 14-bit interpolation prevents audible stepping during aggressive wheel movements.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Try it
&lt;/h3&gt;

&lt;p&gt;Wire a slow triangle LFO into Pitch Bend to add subtle, expressive pitch wander to vintage synth leads.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;LFO -&amp;gt; Pitch Bend -&amp;gt; Analog -&amp;gt; Audio Out
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  6. Velocity Curve: dynamic touch and curve response
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;Velocity Curve&lt;/strong&gt; node remaps the velocity dynamics of incoming note events, tailoring keyboard touch response to performance preferences.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/..%2Fassets%2Fnodes%2Fhd%2Fvelocity-curve.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/..%2Fassets%2Fnodes%2Fhd%2Fvelocity-curve.webp" alt="Velocity Curve node in Infinite" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  How it works
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Curve profiles&lt;/strong&gt;: Linear, Exponential (emphasising soft touches), Logarithmic (punchy and responsive), and S-curve (compressed dynamics).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Min/max clamping&lt;/strong&gt;: Sets minimum velocity floor and maximum ceiling limits.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fixed velocity mode&lt;/strong&gt;: Locks all incoming notes to a single uniform velocity level (such as 100 for consistent organ or synth-pop lines).&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Try it
&lt;/h3&gt;

&lt;p&gt;Apply an Exponential velocity curve to a physical Karplus-Strong String synth for natural acoustic response when playing delicate arpeggios.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;MIDI Notes -&amp;gt; Velocity Curve (Exp) -&amp;gt; String -&amp;gt; Audio Out
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  7. Gate: rhythmic duration and articulation shaper
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;Gate&lt;/strong&gt; node controls the duration of active note events, turning sustained chords into short staccato bursts or stretching short taps into legato drones.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/..%2Fassets%2Fnodes%2Fhd%2Fgate.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/..%2Fassets%2Fnodes%2Fhd%2Fgate.webp" alt="Gate node in Infinite" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  How it works
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Time and beat modes&lt;/strong&gt;: Set gate length in milliseconds (&lt;code&gt;5ms&lt;/code&gt; to &lt;code&gt;2000ms&lt;/code&gt;) or metric musical divisions (&lt;code&gt;1/16&lt;/code&gt;, &lt;code&gt;1/8&lt;/code&gt;, &lt;code&gt;1/4&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fixed gate vs proportional&lt;/strong&gt;: Choose between fixed note lengths or proportional scaling (e.g. 50% staccato of incoming note length).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Legato tie mode&lt;/strong&gt;: Automatically bridges notes together when consecutive keys overlap.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Try it
&lt;/h3&gt;

&lt;p&gt;Feed an Arpeggiator into Gate set to 15% length to transform an arpeggio into tight, robotic 16th-note staccato plucks.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Arpeggiator -&amp;gt; Gate (15%) -&amp;gt; FM -&amp;gt; Audio Out
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  8. Humanizer: micro-timing shuffle and organic dynamics
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;Humanizer&lt;/strong&gt; node injects subtle, natural human imperfections into rigid, computer-quantized note streams.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/..%2Fassets%2Fnodes%2Fhd%2Fhumanizer.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/..%2Fassets%2Fnodes%2Fhd%2Fhumanizer.webp" alt="Humanizer node in Infinite" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  How it works
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Timing jitter&lt;/strong&gt;: Introduces microscopic Gaussian time offsets (from &lt;code&gt;0ms&lt;/code&gt; to &lt;code&gt;35ms&lt;/code&gt;) to note onsets, simulating the slight imprecisions of live human performance.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Velocity spread&lt;/strong&gt;: Randomizes note velocity around the played value by a customizable percentage window.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pitch drift&lt;/strong&gt;: Adds minute micro-tuning offsets for analog acoustic warmth.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Try it
&lt;/h3&gt;

&lt;p&gt;Place Humanizer between a rigid 16-step Note Sequencer and a drum machine or piano synth to make programmed patterns breathe naturally.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Note Sequencer -&amp;gt; Humanizer -&amp;gt; Sampler (Piano) -&amp;gt; Audio Out
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  9. Quantizer: musical scale and modal pitch snapping
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;Quantizer&lt;/strong&gt; node forces arbitrary pitch numbers, microtonal frequencies, and random pitch modulators onto chosen musical scales and temperaments.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/..%2Fassets%2Fnodes%2Fhd%2Fquantizer.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/..%2Fassets%2Fnodes%2Fhd%2Fquantizer.webp" alt="Quantizer node in Infinite" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  How it works
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Over 40 musical scales&lt;/strong&gt;: Major, Minor, Dorian, Phrygian, Lydian, Mixolydian, Locrian, Harmonic Minor, Melodic Minor, Pentatonic, Blues, Hirajoshi, Insen, Raga, and microtonal modes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Root note transposition&lt;/strong&gt;: Set the tonic key to any pitch (&lt;code&gt;C&lt;/code&gt; through &lt;code&gt;B&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Snap algorithms&lt;/strong&gt;: Snaps to the nearest scale degree either upward, downward, or to the absolute closest interval.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Try it
&lt;/h3&gt;

&lt;p&gt;Feed a Random Modulator or CV voltage into Quantizer set to Japanese Hirajoshi, and pipe the output into a Metallic resonator for generative gamelan melodies.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Random -&amp;gt; Quantizer (Hirajoshi) -&amp;gt; Metallic -&amp;gt; Delay -&amp;gt; Audio Out
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  10. Glide: monophonic portamento and polyphonic slide
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;Glide&lt;/strong&gt; node produces smooth pitch glides between consecutive notes, featuring both classic analog monophonic portamento and multi-voice polyphonic slide.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/..%2Fassets%2Fnodes%2Fhd%2Fglide.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/..%2Fassets%2Fnodes%2Fhd%2Fglide.webp" alt="Glide node in Infinite" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  How it works
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Glide time&lt;/strong&gt;: Continuous portamento rate control (&lt;code&gt;0ms&lt;/code&gt; to &lt;code&gt;3000ms&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Legato-only mode&lt;/strong&gt;: Glides only when two notes overlap in time, leaving non-overlapping notes with instant attack.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Constant time vs constant rate&lt;/strong&gt;: Select whether pitch transitions take the same amount of time regardless of distance, or glide at a fixed semitones-per-second velocity.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Try it
&lt;/h3&gt;

&lt;p&gt;Enable Legato Glide on a bass synth patch, hold a low note while tapping octaves higher, and enjoy smooth analog pitch slides.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;MIDI Notes -&amp;gt; Glide (Legato) -&amp;gt; Analog (Acid Bass) -&amp;gt; Audio Out
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  11. Note Echo: algorithmic MIDI delay and rhythmic repeats
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;Note Echo&lt;/strong&gt; node creates rhythmic echoing MIDI notes, repeating incoming note events across musical intervals with decay and transposition.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/..%2Fassets%2Fnodes%2Fhd%2Fnote-echo.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/..%2Fassets%2Fnodes%2Fhd%2Fnote-echo.webp" alt="Note Echo node in Infinite" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  How it works
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Tempo-synced delay time&lt;/strong&gt;: Set delay intervals to standard, dotted, or triplet metric divisions (&lt;code&gt;1/16&lt;/code&gt;, &lt;code&gt;1/8d&lt;/code&gt;, &lt;code&gt;1/4t&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Feedback &amp;amp; count&lt;/strong&gt;: Controls the number of echo repeats (&lt;code&gt;1&lt;/code&gt; to &lt;code&gt;32&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Velocity decay&lt;/strong&gt;: Gradually scales down the velocity of successive repeats for natural fading.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Semitone pitch transpose&lt;/strong&gt;: Shifts each repeat up or down by a set semitone interval, turning a single key press into an ascending or descending staircase.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Try it
&lt;/h3&gt;

&lt;p&gt;Set Note Echo to a dotted 8th note (&lt;code&gt;1/8d&lt;/code&gt;) with a &lt;code&gt;+7 semitones&lt;/code&gt; (fifth) pitch shift, and play single notes to create layered arpeggiated patterns.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;MIDI Notes -&amp;gt; Note Echo (1/8d, +7) -&amp;gt; Wavetable -&amp;gt; Audio Out
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  12. Note Router: dynamic keyboard splitting and voice dispatching
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;Note Router&lt;/strong&gt; node directs incoming notes across up to four separate output ports based on pitch thresholds, velocity ranges, or voice allocation.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/..%2Fassets%2Fnodes%2Fhd%2Fnote-router.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/..%2Fassets%2Fnodes%2Fhd%2Fnote-router.webp" alt="Note Router node in Infinite" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  How it works
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Split mode&lt;/strong&gt;: Routes notes below a split point to Output 1, and notes above to Output 2.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Velocity dispatch&lt;/strong&gt;: Sends soft notes to an intimate electric piano, and hard accents to a brass synth.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Round-robin voice allocation&lt;/strong&gt;: Cycles notes sequentially across Outputs 1, 2, 3, and 4, allowing four distinct synthesizers to share parts of a polyphonic phrase.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Try it
&lt;/h3&gt;

&lt;p&gt;Set Note Router to Round-Robin and connect three different synths (Analog, FM, and String) to play dynamic hocketing melodies where every note has a unique timbre.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Arpeggiator -&amp;gt; Note Router (Round Robin) -&amp;gt; [Analog, FM, String]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  13. Note Merge: unified polyphonic stream combiner
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;Note Merge&lt;/strong&gt; node combines multiple independent note streams into a single unified polyphonic stream with intelligent collision handling.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/..%2Fassets%2Fnodes%2Fhd%2Fnote-merge.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/..%2Fassets%2Fnodes%2Fhd%2Fnote-merge.webp" alt="Note Merge node in Infinite" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  How it works
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Multi-input bus&lt;/strong&gt;: Combines up to four note sources into one stream.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Duplicate note suppression&lt;/strong&gt;: Prevents hanging notes and double-trigger clicks when two input streams send the same pitch simultaneously.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Voice priority&lt;/strong&gt;: Option to prioritize higher or lower notes during polyphony overflow.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Try it
&lt;/h3&gt;

&lt;p&gt;Merge an algorithmic Arpeggiator pattern with live keyboard playing so you can play expressive solo counter-melodies over automated sequences.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[Arpeggiator, Keyboard] -&amp;gt; Note Merge -&amp;gt; Analog -&amp;gt; Audio Out
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  14. Note Switcher: modulated phrase selector
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;Note Switcher&lt;/strong&gt; node selects which of several incoming note streams passes downstream, controlled via a macro knob or logic trigger.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/..%2Fassets%2Fnodes%2Fhd%2Fnote-switcher.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/..%2Fassets%2Fnodes%2Fhd%2Fnote-switcher.webp" alt="Note Switcher node in Infinite" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  How it works
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Multi-channel selector&lt;/strong&gt;: Seamlessly switches between alternate note patterns without dropping active note-off events.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Modulatable selection index&lt;/strong&gt;: Switch patterns automatically using a slow square LFO or timeline automation track.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Smooth transition handling&lt;/strong&gt;: Sends clean note-off messages to active voices before switching to prevent stuck notes.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Try it
&lt;/h3&gt;

&lt;p&gt;Wire a verse bassline into Input 1 and a chorus bassline into Input 2, then automate the selector with a Macro Toggle for arrangement transitions.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[Pattern A, Pattern B] -&amp;gt; Note Switcher -&amp;gt; Analog -&amp;gt; Audio Out
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  15. Arpeggiator: algorithmic pattern and chord engine
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;Arpeggiator&lt;/strong&gt; node takes held chords and breaks them into rhythmic, tempo-synced melodic sequences.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/..%2Fassets%2Fnodes%2Fhd%2Farpeggiator.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/..%2Fassets%2Fnodes%2Fhd%2Farpeggiator.webp" alt="Arpeggiator node in Infinite" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  How it works
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Directional modes&lt;/strong&gt;: Up, Down, Up/Down, Down/Up, Random, Chord Repeat, and As-Played.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Octave span&lt;/strong&gt;: Sweeps arpeggios across &lt;code&gt;1&lt;/code&gt; to &lt;code&gt;4&lt;/code&gt; octaves with cyclical or ping-pong octave progression.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Gate &amp;amp; swing&lt;/strong&gt;: Adjusts note duration percentage and metric shuffle.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hold toggle&lt;/strong&gt;: Latches played chords so the arpeggio continues cycling after keys are released.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Try it
&lt;/h3&gt;

&lt;p&gt;Hold a minor ninth chord, set Arpeggiator to Up/Down across 3 octaves at 1/16th notes, and route through an analog filter sweep.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Keyboard -&amp;gt; Arpeggiator (Up/Down) -&amp;gt; Analog -&amp;gt; Audio Out
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  16. Note Sequencer: 16-step polyphonic pitch &amp;amp; gate grid
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;Note Sequencer&lt;/strong&gt; node is a classic 16-step grid sequencer with per-step pitch, velocity, octave shift, and gate tie controls.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/..%2Fassets%2Fnodes%2Fhd%2Fnote-sequencer.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/..%2Fassets%2Fnodes%2Fhd%2Fnote-sequencer.webp" alt="Note Sequencer node in Infinite" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  How it works
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Interactive step matrix&lt;/strong&gt;: 16 dedicated pitch knobs with visual semitone displays.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Per-step ties &amp;amp; mutes&lt;/strong&gt;: Tie steps together for long sustained bass notes, or mute steps for syncopated rests.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Variable step length&lt;/strong&gt;: Set pattern length from 1 to 16 steps to create odd-meter polyrhythms (such as 5/16 or 7/16).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Direction modes&lt;/strong&gt;: Forward, Reverse, Ping-Pong, and Brownian random walk.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Try it
&lt;/h3&gt;

&lt;p&gt;Set the sequencer length to 7 steps over 16th notes to produce a shifting polyrhythmic ostinato that cycles across the 4/4 bar line.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Note Sequencer (7 Steps) -&amp;gt; FM -&amp;gt; Delay -&amp;gt; Audio Out
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  17. Random Note Generator: constrained generative melody engine
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;Random Note Generator&lt;/strong&gt; node creates constrained melodic phrases and basslines algorithmically in real time.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/..%2Fassets%2Fnodes%2Fhd%2Frandom-note-generator.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/..%2Fassets%2Fnodes%2Fhd%2Frandom-note-generator.webp" alt="Random Note Generator node in Infinite" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  How it works
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Key &amp;amp; scale constraints&lt;/strong&gt;: Restricts generated notes strictly to a selected musical key and scale.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Interval jump weighting&lt;/strong&gt;: Biases random generation toward small melodic steps (seconds and thirds) rather than wide, disjointed leaps.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rhythmic density&lt;/strong&gt;: Controls the probability of active note triggers per clock tick, introducing musical rests.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Seed repeatability&lt;/strong&gt;: Freeze the random seed to loop an inspiring generated phrase indefinitely.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Try it
&lt;/h3&gt;

&lt;p&gt;Set the scale to Minor Pentatonic, set density to 60%, and pipe the generated notes into a Wavetable pad for an endless generative ambient performance.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Random Note Generator -&amp;gt; Wavetable -&amp;gt; Reverb -&amp;gt; Audio Out
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  18. MIDI File: standard MIDI file canvas player
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;MIDI File&lt;/strong&gt; node loads and plays standard &lt;code&gt;.mid&lt;/code&gt; sequence files directly on the canvas, locked to the global transport clock.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/..%2Fassets%2Fnodes%2Fhd%2Fmidi-file.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/..%2Fassets%2Fnodes%2Fhd%2Fmidi-file.webp" alt="MIDI File node in Infinite" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  How it works
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Drag and drop loading&lt;/strong&gt;: Drop standard Type 0 or Type 1 MIDI files directly onto the node body.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Track isolation&lt;/strong&gt;: Choose which MIDI track to output, or sum all tracks into one polyphonic stream.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Transport synchronization&lt;/strong&gt;: Automatically tracks project tempo, loop markers, and timeline playhead location.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Try it
&lt;/h3&gt;

&lt;p&gt;Drag a complex classical piano MIDI file onto the canvas, route note outputs to a String synth, and use note velocities to drive 3D particle bursts.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;MIDI File -&amp;gt; String -&amp;gt; Audio Out
MIDI File (Velocity) -&amp;gt; Particle System (Speed)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  19. Chorder: single-note harmonizer and chord voicings
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;Chorder&lt;/strong&gt; node converts single incoming note taps into rich multi-voice polyphonic chords.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/..%2Fassets%2Fnodes%2Fhd%2Fchorder.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/..%2Fassets%2Fnodes%2Fhd%2Fchorder.webp" alt="Chorder node in Infinite" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  How it works
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Pre-configured chord types&lt;/strong&gt;: Major, Minor, Sus2, Sus4, Dominant 7th, Major 7th, Minor 7th, 9th, and Diminished.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Custom chord editor&lt;/strong&gt;: Define custom interval offsets (e.g. &lt;code&gt;[0, +7, +12, +16]&lt;/code&gt;) for signature chords.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Root-relative transposition&lt;/strong&gt;: Voicings transpose across the keyboard relative to the incoming note pitch.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Try it
&lt;/h3&gt;

&lt;p&gt;Select Minor 9th voicing, set Arpeggiator downstream, and play single bass notes to trigger sweeping impressionist arpeggios.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Keyboard -&amp;gt; Chorder (Min 9) -&amp;gt; Arpeggiator -&amp;gt; Wavetable -&amp;gt; Audio Out
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  20. Note Stack: interval and octave voice layering
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;Note Stack&lt;/strong&gt; node layers harmonic interval copies on top of played notes to thicken synth leads and basslines.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/..%2Fassets%2Fnodes%2Fhd%2Fnote-stack.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/..%2Fassets%2Fnodes%2Fhd%2Fnote-stack.webp" alt="Note Stack node in Infinite" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  How it works
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Up to 4 interval layers&lt;/strong&gt;: Add octave below (&lt;code&gt;-12&lt;/code&gt;), fifth above (&lt;code&gt;+7&lt;/code&gt;), octave above (&lt;code&gt;+12&lt;/code&gt;), or custom intervals.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Per-voice detuning&lt;/strong&gt;: Applies subtle pitch detuning between stacked voices for rich chorus effects.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Velocity scaling&lt;/strong&gt;: Scales the velocity of stacked intervals relative to the primary note.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Try it
&lt;/h3&gt;

&lt;p&gt;Add an octave below (&lt;code&gt;-12&lt;/code&gt;) and a fifth above (&lt;code&gt;+7&lt;/code&gt;) to an analog saw lead to produce a classic vintage stadium rock synth sound.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;MIDI Notes -&amp;gt; Note Stack (-12, +7) -&amp;gt; Analog -&amp;gt; Audio Out
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  21. Note Capturer: live performance buffer recorder
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;Note Capturer&lt;/strong&gt; node acts as a live MIDI scratchpad, recording incoming performances into a circular memory buffer for playback or loop export.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/..%2Fassets%2Fnodes%2Fhd%2Fnote-capturer.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/..%2Fassets%2Fnodes%2Fhd%2Fnote-capturer.webp" alt="Note Capturer node in Infinite" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  How it works
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Retrospective recording&lt;/strong&gt;: Keeps a continuous rolling buffer of your recent playing, allowing you to capture spontaneous improvisation after it occurs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Bar quantization&lt;/strong&gt;: Trims captured phrases cleanly to musical bar boundaries.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Loop playback&lt;/strong&gt;: Plays captured takes in a continuous loop while leaving the keyboard free for additional layers.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Try it
&lt;/h3&gt;

&lt;p&gt;Improvise freely on your keyboard, press Capture to grab the last 4 bars, and immediately loop the phrase while designing synth patches.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;MIDI Notes -&amp;gt; Note Capturer (Loop) -&amp;gt; Analog -&amp;gt; Audio Out
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  22. Bouncing Balls: physics-based rhythmic trigger generator
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;Bouncing Balls&lt;/strong&gt; node runs an internal physics simulation where virtual spheres bounce inside a gravity well, triggering note events whenever a ball collides with the floor.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/..%2Fassets%2Fnodes%2Fhd%2Fbouncing-balls.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/..%2Fassets%2Fnodes%2Fhd%2Fbouncing-balls.webp" alt="Bouncing Balls node in Infinite" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  How it works
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Gravity &amp;amp; elasticity&lt;/strong&gt;: Balls bounce with physically realistic gravitational acceleration, bouncing rapidly as they reach the floor.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Multi-ball polyphony&lt;/strong&gt;: Simulate up to 8 independent bouncing spheres with differing drop heights and restitution coefficients.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Collision pitch mapping&lt;/strong&gt;: Map collision velocity to note velocity, and bounce frequency to musical pitch.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Try it
&lt;/h3&gt;

&lt;p&gt;Route Bouncing Balls into a Metallic resonator or physical String synth to hear organic, accelerating acoustic impacts mimicking raindrops or dropped marbles.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Bouncing Balls -&amp;gt; Metallic Resonator -&amp;gt; Reverb -&amp;gt; Audio Out
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  23. Note Strum: realistic acoustic chord strumming
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;Note Strum&lt;/strong&gt; node emulates guitar and harp playing by staggering the onset times of notes in a polyphonic chord.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/..%2Fassets%2Fnodes%2Fhd%2Fnote-strum.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/..%2Fassets%2Fnodes%2Fhd%2Fnote-strum.webp" alt="Note Strum node in Infinite" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  How it works
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Strum speed&lt;/strong&gt;: Sets the time delay between consecutive notes (&lt;code&gt;2ms&lt;/code&gt; to &lt;code&gt;150ms&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Direction control&lt;/strong&gt;: Down-strum (low notes to high notes), Up-strum (high notes to low notes), or Alternating.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Velocity decay&lt;/strong&gt;: Gradually tapers velocity across the strum to emulate natural hand dynamics.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Try it
&lt;/h3&gt;

&lt;p&gt;Place Note Strum between a Chorder and a String physical modeling synth for convincing nylon-string acoustic guitar chord strumming.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Keyboard -&amp;gt; Chorder -&amp;gt; Note Strum -&amp;gt; String -&amp;gt; Audio Out
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  24. Field Notes: programmable algorithmic note generation
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;Field Notes&lt;/strong&gt; node allows you to script custom generative algorithms, Markov-chain phrase models, and rhythmic logic directly in Infinite's bare-name Field language.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/..%2Fassets%2Fnodes%2Fhd%2Ffield-notes.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/..%2Fassets%2Fnodes%2Fhd%2Ffield-notes.webp" alt="Field Notes node in Infinite" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  How it works
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Event-driven execution&lt;/strong&gt;: Executes on every clock tick or MIDI input trigger.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;State registers&lt;/strong&gt;: Retains history across steps to calculate Euclidean rhythms, Fibonacci sequences, or cellular automata.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Output note generation&lt;/strong&gt;: Emits note pitch, velocity, and gate events directly to downstream synths.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Example: Fibonacci sequence arpeggiator
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// registers: step_counter, prev_a, prev_b
state a = 1
state b = 1
state step = 0

// advance Fibonacci sequence modulo 12
let next_fib = (a + b) % 12
a = b
b = next_fib
step = step + 1

// map to minor pentatonic scale
let root = 60
let intervals = [0, 3, 5, 7, 10]
let note_out = root + intervals[next_fib % 5]

emit_note(note_out, 90, 120) // pitch, velocity, duration_ms
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Try it
&lt;/h3&gt;

&lt;p&gt;Drop a Field Notes node, enter your own algorithmic rules, and explore generative compositions impossible in conventional static DAWs.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Clock -&amp;gt; Field Notes -&amp;gt; FM -&amp;gt; Delay -&amp;gt; Audio Out
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Modular note architecture
&lt;/h2&gt;

&lt;p&gt;Because Infinite unifies note processing, audio synthesis, and visual rendering onto a single real-time execution graph, these note nodes can drive both sound and visual form simultaneously. &lt;/p&gt;

&lt;p&gt;An Arpeggiator can trigger a synth lead while stepping through colors in an Audio Color Ramp, and the physical collisions of a Bouncing Balls node can displace 3D geometry meshes at the exact microsecond an acoustic chime rings out.&lt;/p&gt;

&lt;p&gt;Drop any note node onto the canvas, cable it into an instrument, and build generative musical systems unconstrained by linear timelines.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://infinitedevices.org/blog/every-note-node-in-infinite-generative-sequencing-guide.html" rel="noopener noreferrer"&gt;https://infinitedevices.org/blog/every-note-node-in-infinite-generative-sequencing-guide.html&lt;/a&gt;. Infinite is a free, open-source DAW for visuals, music and code: &lt;a href="https://infinitedevices.org" rel="noopener noreferrer"&gt;infinitedevices.org&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>midinodes</category>
      <category>generativemusic</category>
      <category>sequencing</category>
      <category>algorithmiccomposition</category>
    </item>
    <item>
      <title>Every synthesizer node in Infinite: the complete sound design guide</title>
      <dc:creator>naman</dc:creator>
      <pubDate>Wed, 11 Nov 2026 13:15:24 +0000</pubDate>
      <link>https://dev.to/n1m21n/every-synthesizer-node-in-infinite-the-complete-sound-design-guide-246e</link>
      <guid>https://dev.to/n1m21n/every-synthesizer-node-in-infinite-the-complete-sound-design-guide-246e</guid>
      <description>&lt;p&gt;Most digital audio workstations isolate sound generation inside third-party plugins. You purchase an instrument, load a floating window, navigate vendor-specific preset systems, and route stereo audio into a rigid mixer channel.&lt;/p&gt;

&lt;p&gt;Infinite approaches synthesis from a different foundation. Every synthesizer lives directly on the open canvas as a modular node. Notes, audio streams, modulation voltages, and visual textures share the same graph and memory space. A single LFO can sweep a wavetable position while warping a 3D geometry mesh, and a reaction-diffusion simulation can directly generate polyphonic audio timbre.&lt;/p&gt;

&lt;p&gt;Infinite features twenty native synthesizer engines, spanning virtual analog, morphing wavetables, 4-operator frequency modulation, Karplus-Strong waveguides, granular cloud generators, extreme spectral time-stretchers, and per-sample programmable JIT kernels.&lt;/p&gt;

&lt;p&gt;Here is an architectural breakdown of every synthesizer node in Infinite, how their sound engines work, and how to patch them.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. Oscillator: dual-oscillator subtractive &amp;amp; FM engine
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;Oscillator&lt;/strong&gt; node is Infinite's foundational sound generator, built upon bandlimited anti-aliased wavetables with linear frequency modulation and phase synchronization.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/..%2Fassets%2Fnodes%2Fhd%2Foscillator.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/..%2Fassets%2Fnodes%2Fhd%2Foscillator.webp" alt="Oscillator node in Infinite"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  How it works
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Waveforms&lt;/strong&gt;: Sine, Triangle, Sawtooth, and Square with variable Pulse Width (&lt;code&gt;0.01&lt;/code&gt; to &lt;code&gt;0.99&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pitch controls&lt;/strong&gt;: Coarse frequency (&lt;code&gt;20 Hz&lt;/code&gt; to &lt;code&gt;8000 Hz&lt;/code&gt;), octave shift (&lt;code&gt;-4&lt;/code&gt; to &lt;code&gt;+4&lt;/code&gt;), semitone offset (&lt;code&gt;-12&lt;/code&gt; to &lt;code&gt;+12&lt;/code&gt;), and fine detune (&lt;code&gt;-50&lt;/code&gt; to &lt;code&gt;+50&lt;/code&gt; cents).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Linear FM input&lt;/strong&gt;: An audio-rate &lt;code&gt;fm_in&lt;/code&gt; pin enables modulation from a secondary oscillator, producing rich sidebands for metallic chimes, FM brass, and aggressive growls.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Portamento&lt;/strong&gt;: Continuous glide parameter (&lt;code&gt;0&lt;/code&gt; to &lt;code&gt;2&lt;/code&gt; seconds) providing constant-rate pitch transitions between notes.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Try it
&lt;/h3&gt;

&lt;p&gt;Patch a secondary Oscillator set to a high octave into the &lt;code&gt;fm_in&lt;/code&gt; port, modulate FM Depth with an Envelope, and route through an Audio Filter for crisp metallic bells.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Random Note Generator -&amp;gt; Oscillator -&amp;gt; Audio Filter -&amp;gt; Audio Out
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  2. Wavetable: 64-table morphing synth with unison
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;Wavetable&lt;/strong&gt; node is Infinite's flagship polyphonic wavetable instrument, featuring 64 factory wavetables that morph smoothly across eight distinct single-cycle frames.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/..%2Fassets%2Fnodes%2Fhd%2Fwavetable.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/..%2Fassets%2Fnodes%2Fhd%2Fwavetable.webp" alt="Wavetable node in Infinite"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  How it works
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;2D table scanning&lt;/strong&gt;: Continuous position interpolation across 8 frames per table, eliminating step clicks or boundary artifacts.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Unison detune &amp;amp; stereo spread&lt;/strong&gt;: Stacks up to 8 voices per note with adjustable frequency detuning and wide stereo placement.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sub-oscillator&lt;/strong&gt;: Integrated sub-harmonic generator providing dedicated low-end weight independently of table morphing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Modulatable position&lt;/strong&gt;: The position parameter can be cabled directly to LFOs, envelope followers, or hand tracking modulators.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Try it
&lt;/h3&gt;

&lt;p&gt;Wire an LFO into the table position input so the waveform continually evolves, then layer chorus for a lush cinematic pad.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Arpeggiator -&amp;gt; Wavetable -&amp;gt; Chorus -&amp;gt; Reverb -&amp;gt; Audio Out
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  3. Analog: polyphonic virtual analog with nonlinear filters
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;Analog&lt;/strong&gt; node models the physical circuit behaviour of vintage analog synthesizers, complete with subtle oscillator drift, saturation stages, and four distinct nonlinear filter topologies.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/..%2Fassets%2Fnodes%2Fhd%2Fanalog.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/..%2Fassets%2Fnodes%2Fhd%2Fanalog.webp" alt="Analog node in Infinite"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  How it works
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Twin drift-stabilized oscillators&lt;/strong&gt;: Dual oscillators with saw, square, triangle, and sine options, pulse width modulation, sub-oscillator, and a pink/white noise source.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Circuit-modeled filters&lt;/strong&gt;: Switchable between a 4-pole Moog transistor ladder, Korg MS-20 resonant lowpass, diode ladder, and state-variable filter (SVF).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;4x oversampling&lt;/strong&gt;: Drives and non-linear filter stages run at 4x internal oversampling to keep aliasing strictly under -80 dB across all octaves.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dual ADSR envelopes&lt;/strong&gt;: Dedicated amplitude and filter envelopes with exponential decay curves.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Try it
&lt;/h3&gt;

&lt;p&gt;Stack three detuned unison voices, select the MS-20 filter model with medium resonance, and sweep cutoff with an envelope for an authentic acid bassline.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;MIDI Notes -&amp;gt; Analog -&amp;gt; Delay -&amp;gt; Audio Out
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  4. FM: 4-operator frequency modulation synthesizer
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;FM&lt;/strong&gt; node delivers classic frequency modulation synthesis using four sine operators configured across eleven classic routing algorithms.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/..%2Fassets%2Fnodes%2Fhd%2Ffm.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/..%2Fassets%2Fnodes%2Fhd%2Ffm.webp" alt="FM node in Infinite"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  How it works
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;11 routing algorithms&lt;/strong&gt;: Ranging from a pure vertical cascade (&lt;code&gt;4 -&amp;gt; 3 -&amp;gt; 2 -&amp;gt; 1&lt;/code&gt;) for complex harmonic teeth, to parallel carriers for additive electric pianos.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Harmonic frequency ratios&lt;/strong&gt;: Per-operator integer and fractional frequency multipliers (&lt;code&gt;0.5x&lt;/code&gt; to &lt;code&gt;32x&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Feedback loop&lt;/strong&gt;: Operator 4 includes self-modulation feedback, transitioning from smooth sines to saw waves and broadband noise.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Per-operator envelopes&lt;/strong&gt;: Individual envelope generators shaping the modulation index over time.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Try it
&lt;/h3&gt;

&lt;p&gt;Select algorithm 5 (two parallel carrier-modulator stacks), tune operator 2 to a 3.5x non-harmonic ratio, and add a brief decay envelope for a crystalline mallet sound.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Arpeggiator -&amp;gt; FM -&amp;gt; Reverb -&amp;gt; Audio Out
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  5. Partials: 64-harmonic additive formant resynthesis
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;Partials&lt;/strong&gt; node performs real-time additive resynthesis, tracking harmonic partials and reproducing acoustic instruments and voices without pitch artifacts.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/..%2Fassets%2Fnodes%2Fhd%2Fpartials.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/..%2Fassets%2Fnodes%2Fhd%2Fpartials.webp" alt="Partials node in Infinite"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  How it works
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Formant preservation&lt;/strong&gt;: When transposing incoming audio across octaves, Partials keeps the spectral formant envelope locked in place, avoiding the unnatural "chipmunk" timbre common to conventional samplers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Spectral tilt &amp;amp; odd/even balance&lt;/strong&gt;: Continuous control over harmonic roll-off slope and the ratio between even and odd harmonics.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Inharmonic stretching&lt;/strong&gt;: Stretches partial frequencies away from integer multiples for bell and metallic timbres.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Residual noise tracking&lt;/strong&gt;: Models the turbulent air and breath left behind by harmonic analysis.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Try it
&lt;/h3&gt;

&lt;p&gt;Load a vocal syllable or acoustic cello sample into Partials, trigger it across three octaves, and hear natural vocal character preserved across the entire keyboard.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;MIDI Notes -&amp;gt; Partials -&amp;gt; Convolution Reverb -&amp;gt; Audio Out
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  6. String: Karplus-Strong physical modeling waveguide
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;String&lt;/strong&gt; node models the physical acoustics of vibrating strings stretched over a resonating wooden body using Karplus-Strong waveguide synthesis.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/..%2Fassets%2Fnodes%2Fhd%2Fstring.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/..%2Fassets%2Fnodes%2Fhd%2Fstring.webp" alt="String node in Infinite"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  How it works
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Physical waveguide loop&lt;/strong&gt;: A delay line length tuned exactly to the note's fundamental frequency, coupled with an internal lowpass reflection filter.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Three exciter modes&lt;/strong&gt;: 

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;Pluck&lt;/em&gt;: Impulse burst simulating a guitar plectrum or finger pick.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Bow&lt;/em&gt;: Continuous friction noise simulating a violin or cello bow.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Strike&lt;/em&gt;: Felt hammer excitation simulating an acoustic piano or hammered dulcimer.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Body resonance &amp;amp; pickup position&lt;/strong&gt;: Configurable acoustic body model and spatial pickup location along the string length.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Try it
&lt;/h3&gt;

&lt;p&gt;Set the exciter mode to Bow, slow the attack time slightly, and play sustained chords for a lush acoustic string ensemble.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Chorder -&amp;gt; String -&amp;gt; Reverb -&amp;gt; Audio Out
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  7. Wave Terrain: topographic image-to-sound synthesis
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;Wave Terrain&lt;/strong&gt; node turns any 2D image, video capture, reaction-diffusion simulation, or procedural texture into a continuous 3D acoustic terrain surface &lt;code&gt;z = T(u, v)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/..%2Fassets%2Fnodes%2Fhd%2Fwave-terrain.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/..%2Fassets%2Fnodes%2Fhd%2Fwave-terrain.webp" alt="Wave Terrain node in Infinite"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  How it works
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Audio-rate orbital paths&lt;/strong&gt;: An oscillator traces a closed orbital trajectory &lt;code&gt;(u(t), v(t))&lt;/code&gt; across the image (circle, ellipse, Lissajous curve, or lemniscate).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Surface height as amplitude&lt;/strong&gt;: As the orbital scan travels across pixels, the image luminance &lt;code&gt;z&lt;/code&gt; becomes the instantaneous audio amplitude.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;10-level Fourier MIP antialiasing&lt;/strong&gt;: Sampling raw image pixels causes harsh aliasing; Infinite computes an internal Real Discrete Fourier Transform (RDFT) MIP pyramid across 10 octaves, ensuring pristine, alias-free polyphonic synthesis across all 8 octaves.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Try it
&lt;/h3&gt;

&lt;p&gt;Feed a live Reaction Diffusion texture into Wave Terrain, route an LFO to orbit radius, and listen to the sound morph as the organic visual pattern blooms.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Reaction Diffusion -&amp;gt; Wave Terrain -&amp;gt; Saturator -&amp;gt; Audio Out
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  8. Equation Synth: Desmos-style mathematical synthesis
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;Equation Synth&lt;/strong&gt; node evaluates custom mathematical expressions &lt;code&gt;y = f(x, a, b, c, d)&lt;/code&gt; directly at 48kHz audio rates, turning formulas into playable instruments.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/..%2Fassets%2Fnodes%2Fhd%2Fequation-synth.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/..%2Fassets%2Fnodes%2Fhd%2Fequation-synth.webp" alt="Equation Synth node in Infinite"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  How it works
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Inline formula parsing&lt;/strong&gt;: Type formulas directly using standard mathematical functions (&lt;code&gt;sin&lt;/code&gt;, &lt;code&gt;cos&lt;/code&gt;, &lt;code&gt;tan&lt;/code&gt;, &lt;code&gt;pow&lt;/code&gt;, &lt;code&gt;abs&lt;/code&gt;, &lt;code&gt;tanh&lt;/code&gt;, &lt;code&gt;floor&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Real-time parameter knobs&lt;/strong&gt;: Four continuous parameters (&lt;code&gt;knobA&lt;/code&gt;, &lt;code&gt;knobB&lt;/code&gt;, &lt;code&gt;knobC&lt;/code&gt;, &lt;code&gt;knobD&lt;/code&gt;) exposed as modulation pins.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Compile-time bandlimiting&lt;/strong&gt;: Evaluated curves are compiled into bandlimited wavetable mipmaps, preventing mathematical sharp edges from creating audible foldback distortion.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Try it
&lt;/h3&gt;

&lt;p&gt;Type &lt;code&gt;sin(x) + a * sin(x * 3) + b * sin(x * 5)&lt;/code&gt;, wire an LFO to &lt;code&gt;knobA&lt;/code&gt;, and listen to third and fifth harmonics fade in and out with algebraic purity.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;MIDI Notes -&amp;gt; Equation Synth -&amp;gt; Formant Filter -&amp;gt; Audio Out
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  9. Spectral Synth: real-time spectrogram resynthesis
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;Spectral Synth&lt;/strong&gt; node scans an image or visual canvas horizontally as a spectrogram, converting visual pixels into audible frequencies.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/..%2Fassets%2Fnodes%2Fhd%2Fspectral-synth.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/..%2Fassets%2Fnodes%2Fhd%2Fspectral-synth.webp" alt="Spectral Synth node in Infinite"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  How it works
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Horizontal scan line&lt;/strong&gt;: A playhead travels across the texture from left to right at tempo-synced rates.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Vertical frequency mapping&lt;/strong&gt;: The vertical $y$-axis maps to acoustic frequency (low frequencies at the bottom, high frequencies at the top), while pixel brightness sets partial amplitude.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Spectral freeze&lt;/strong&gt;: Freeze the playhead at any point along the image to produce an indefinite, unmoving spectral chord.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Try it
&lt;/h3&gt;

&lt;p&gt;Draw three horizontal brush strokes in a Draw node at low, mid, and high positions, patch the texture into Spectral Synth, and hear your sketch played back as a triad.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Draw Canvas -&amp;gt; Spectral Synth -&amp;gt; Delay -&amp;gt; Audio Out
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  10. Metallic: modal physical resonator for bells and plates
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;Metallic&lt;/strong&gt; node models the physical vibrations of acoustic metal and glass objects struck by hard or soft mallets using a bank of coupled two-pole bandpass resonators.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/..%2Fassets%2Fnodes%2Fhd%2Fmetallic.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/..%2Fassets%2Fnodes%2Fhd%2Fmetallic.webp" alt="Metallic node in Infinite"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  How it works
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;8 material presets&lt;/strong&gt;: Steel, Brass, Bell Bronze, Aluminium, Glass, Wood, Ceramic, and Titanium.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Modal dispersion&lt;/strong&gt;: Modes follow non-integer frequency ratios corresponding to the physical vibration equations of circular plates and rectangular bars.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stiffness &amp;amp; decay&lt;/strong&gt;: Stiffness controls modal frequency clustering, while decay adjusts the acoustic damping rate across high versus low modes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Strike hardness&lt;/strong&gt;: Blends from a soft felt mallet impulse to a sharp metal point impact.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Try it
&lt;/h3&gt;

&lt;p&gt;Trigger Metallic from the Bouncing Balls note generator for an acoustic gamelan performance where notes ring and decay naturally in space.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Bouncing Balls -&amp;gt; Metallic -&amp;gt; Reverb -&amp;gt; Audio Out
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  11. Sampler: polyphonic multisample engine
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;Sampler&lt;/strong&gt; node provides polyphonic sample playback with precision loop boundaries, pitch tracking, and real-time live audio recording.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/..%2Fassets%2Fnodes%2Fhd%2Fsampler.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/..%2Fassets%2Fnodes%2Fhd%2Fsampler.webp" alt="Sampler node in Infinite"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  How it works
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Playback modes&lt;/strong&gt;: One-Shot, Forward Loop, Reverse Loop, and Ping-Pong bidirectional loop.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Live buffer recording&lt;/strong&gt;: An audio &lt;code&gt;record_in&lt;/code&gt; port allows capturing incoming microphone feeds, guitar inputs, or synth stems straight into memory.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Root pitch tracking&lt;/strong&gt;: Tracks MIDI keyboard pitch relative to a configurable base key with crossfade loop smoothing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Envelope shaping&lt;/strong&gt;: Built-in ADSR envelope for smooth sample transitions.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Try it
&lt;/h3&gt;

&lt;p&gt;Record an ambient field recording through &lt;code&gt;record_in&lt;/code&gt;, set the loop mode to Ping-Pong with a 100ms crossfade, and play rich chords across the keyboard.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Microphone -&amp;gt; Sampler (Record In) -&amp;gt; MIDI Notes -&amp;gt; Sampler -&amp;gt; Audio Out
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  12. Slicer: transient-detecting beat chopper
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;Slicer&lt;/strong&gt; node analyzes incoming audio loops, detects transient attacks, and slices the recording into individual hits mapped across MIDI notes.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/..%2Fassets%2Fnodes%2Fhd%2Fslicer.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/..%2Fassets%2Fnodes%2Fhd%2Fslicer.webp" alt="Slicer node in Infinite"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  How it works
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Onset detection&lt;/strong&gt;: High-precision transient peak detection algorithm automatically finding drum hits and percussive transients.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Metric grid fallback&lt;/strong&gt;: Option to slice by strict musical divisions (1/8, 1/16, or 1/32 notes) locked to transport BPM.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Per-slice control&lt;/strong&gt;: Individual start/end offsets, pitch offsets, and reverse triggers per slice.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;MIDI pad mapping&lt;/strong&gt;: Slices automatically map upward from MIDI note C1 for instant pad controller performance.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Try it
&lt;/h3&gt;

&lt;p&gt;Feed a drum break into Slicer, connect an Arpeggiator with a random pattern, and generate an endless supply of breakbeat permutations.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Drum Loop -&amp;gt; Slicer -&amp;gt; Arpeggiator -&amp;gt; Slicer -&amp;gt; Audio Out
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  13. PaulStretch: extreme spectral time-stretching
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;PaulStretch&lt;/strong&gt; node implements the legendary Paul Nasca spectral time-stretch algorithm, expanding audio recordings from 10x to 1000x their original length without pitch shifts.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/..%2Fassets%2Fnodes%2Fhd%2Fpaulstretch.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/..%2Fassets%2Fnodes%2Fhd%2Fpaulstretch.webp" alt="PaulStretch node in Infinite"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  How it works
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Windowed FFT analysis&lt;/strong&gt;: Deconstructs incoming audio into heavily overlapping spectral windows (typically 0.25 to 2.0 seconds wide).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Phase randomization&lt;/strong&gt;: Completely randomizes the phase angle of every frequency bin while preserving original magnitude, eliminating comb filtering and phase cancellation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Extreme stretch factors&lt;/strong&gt;: Stretches a 3-second vocal sample into a 5-minute ambient drone that retains acoustic warmth.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Unison &amp;amp; detune&lt;/strong&gt;: Adds multi-voice spectral unison for shimmering cinematic textures.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Try it
&lt;/h3&gt;

&lt;p&gt;Load a short acoustic piano chord into PaulStretch, set Stretch to 50x, open the FFT window to 1.5 seconds, and send the result into a Limiter for an ambient soundscape.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Piano Sample -&amp;gt; PaulStretch (50x) -&amp;gt; Limiter -&amp;gt; Audio Out
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  14. Molder: harmonic partial decomposition and waveshaping
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;Molder&lt;/strong&gt; node decomposes incoming audio into tracked sinusoidal partials and residual noise, then applies nonlinear wavefolding and dynamic mutation curves.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/..%2Fassets%2Fnodes%2Fhd%2Fmolder.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/..%2Fassets%2Fnodes%2Fhd%2Fmolder.webp" alt="Molder node in Infinite"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  How it works
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Sinusoidal tracking&lt;/strong&gt;: Extracts frequency tracks and energy envelopes from any incoming sample.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mutation roll&lt;/strong&gt;: The Roll button mutates frequency tracks, introducing harmonic permutations and metallic shifts.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Nonlinear folding&lt;/strong&gt;: Compresses partial amplitudes through polynomial folding curves, producing grit and analog saturation.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Try it
&lt;/h3&gt;

&lt;p&gt;Send a clean acoustic vocal recording into Molder, trigger the Roll parameter via a macro button, and listen to the voice transform into alien harmonic drones.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Sampler -&amp;gt; Molder -&amp;gt; Chorus -&amp;gt; Audio Out
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  15. Grain Molder: granular feature sorting and risers
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;Grain Molder&lt;/strong&gt; node chops an audio buffer into thousands of overlapping micro-grains, analyzes their acoustic properties (loudness, spectral centroid, or pitch), and sorts them in ascending or descending order.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/..%2Fassets%2Fnodes%2Fhd%2Fgrain-molder.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/..%2Fassets%2Fnodes%2Fhd%2Fgrain-molder.webp" alt="Grain Molder node in Infinite"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  How it works
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Micro-grain slicing&lt;/strong&gt;: Deconstructs buffers into grains between 20ms and 150ms with Hann window envelopes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Acoustic feature classification&lt;/strong&gt;: Measures root-mean-square (RMS) energy, brightness, and pitch density for every grain.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sorting engine&lt;/strong&gt;: Reorders grains along the playback timeline according to the chosen metric.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Amount slider&lt;/strong&gt;: Morphs continuously from original chronological playback to fully sorted granular order.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Try it
&lt;/h3&gt;

&lt;p&gt;Load a busy drum break, set Sort Mode to Level, and automate the Amount slider from 0% to 100% over four bars to produce a natural granular riser.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Drum Loop -&amp;gt; Grain Molder (Amount) -&amp;gt; Audio Filter -&amp;gt; Audio Out
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  16. Granular: real-time polyphonic granular cloud engine
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;Granular&lt;/strong&gt; node shreds recorded or live audio into micro-sound grains (10ms to 500ms), scattering them across space and time to produce granular clouds, textures, and pitch-shifted shimmers.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/..%2Fassets%2Fnodes%2Fhd%2Fgranular.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/..%2Fassets%2Fnodes%2Fhd%2Fgranular.webp" alt="Granular node in Infinite"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  How it works
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Grain density &amp;amp; size&lt;/strong&gt;: Generates up to 64 simultaneous overlapping grains with customizable duration and emission rate.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Position scrub &amp;amp; spray&lt;/strong&gt;: Controls the center read head position in the buffer, while Spray introduces random time offsets.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pitch randomization&lt;/strong&gt;: Randomly scatters grain playback speeds across customizable semitone windows.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Freeze toggle&lt;/strong&gt;: Instantly locks the read head to sample an infinitesimal sliver of sound indefinitely.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Try it
&lt;/h3&gt;

&lt;p&gt;Pipe a live guitar input into Granular, hit Freeze during a sustained chord, and widen Pitch Spray to turn a single strum into an ethereal cloud of sound.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Audio In -&amp;gt; Granular (Freeze) -&amp;gt; Stereo Delay -&amp;gt; Audio Out
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  17. Field Synth: programmable per-sample JIT DSP kernel
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;Field Synth&lt;/strong&gt; node is Infinite's most flexible sound engine: a polyphonic synthesizer whose entire voice algorithm is written in Infinite's bare-name Field language and compiled directly into native machine code.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/..%2Fassets%2Fnodes%2Fhd%2Ffield-synth.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/..%2Fassets%2Fnodes%2Fhd%2Ffield-synth.webp" alt="Field Synth node in Infinite"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  How it works
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Bare-name syntax&lt;/strong&gt;: Write DSP code with plain algebraic expressions (&lt;code&gt;freq&lt;/code&gt;, &lt;code&gt;phase&lt;/code&gt;, &lt;code&gt;out&lt;/code&gt;) without sigils or boilerplate.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Per-sample execution&lt;/strong&gt;: Runs on the audio thread at 48kHz with zero garbage collection or allocation overhead.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dynamic user knobs&lt;/strong&gt;: Define custom parameters in code that automatically expose modulatable pins on the node body.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Polyphonic voice architecture&lt;/strong&gt;: The engine handles note allocation, voice stealing, and per-voice registers automatically.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Example: resonant dual-oscillator kernel
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// inputs: f (frequency), t (time), gate (0..1)
state p1 = 0.0
state p2 = 0.0

// phase accumulators
let inc = f * (6.2831853 / 48000.0)
p1 = p1 + inc
if p1 &amp;gt; 6.2831853 { p1 = p1 - 6.2831853 }

p2 = p2 + inc * 1.005 // slight detune
if p2 &amp;gt; 6.2831853 { p2 = p2 - 6.2831853 }

// soft-clipped sum
let raw = sin(p1) * 0.5 + sin(p2) * 0.5
out = tanh(raw * 1.5) * gate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Try it
&lt;/h3&gt;

&lt;p&gt;Drop a Field Synth, paste the kernel above, connect MIDI Notes, and immediately enjoy a clean, detuned analog lead with zero external dependencies.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;MIDI Notes -&amp;gt; Field Synth -&amp;gt; Limiter -&amp;gt; Audio Out
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  18. Drum Sequencer: 16-step polyphonic drum engine
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;Drum Sequencer&lt;/strong&gt; node is an integrated 8-track, 16-step drum machine combining analog drum synthesis circuits with an intuitive pattern grid.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/..%2Fassets%2Fnodes%2Fhd%2Fdrum-sequencer.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/..%2Fassets%2Fnodes%2Fhd%2Fdrum-sequencer.webp" alt="Drum Sequencer node in Infinite"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  How it works
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;8 synthesized drum voices&lt;/strong&gt;: Dedicated circuits for Kick, Snare, Closed Hat, Open Hat, Clap, Low Tom, High Tom, and Percussion.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Individual audio outputs&lt;/strong&gt;: Includes a master stereo mix output plus eight individual audio outs (&lt;code&gt;1&lt;/code&gt; to &lt;code&gt;8&lt;/code&gt;) for per-channel external processing and mixing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Step velocity &amp;amp; swing&lt;/strong&gt;: Per-step velocity sliders with configurable shuffle percentage.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Transport lock&lt;/strong&gt;: Automatically locks to Infinite's global BPM and timeline transport.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Try it
&lt;/h3&gt;

&lt;p&gt;Wire individual output 1 (Kick) to an Audio Analyze node, and use its bass energy output to drive the scale of a 3D Sphere in sync with the beat.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Drum Sequencer (Kick Out) -&amp;gt; Audio Analyze -&amp;gt; 3D Sphere (Scale)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  19. MPC: 16-pad vintage sampling groovebox
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;MPC&lt;/strong&gt; node captures the tactile immediacy and groove feel of classic 16-pad hardware samplers.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/..%2Fassets%2Fnodes%2Fhd%2Fmpc.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/..%2Fassets%2Fnodes%2Fhd%2Fmpc.webp" alt="MPC node in Infinite"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  How it works
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;16 dynamic sample pads&lt;/strong&gt;: Drag and drop audio files onto any of the 16 pads.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;16-level velocity mode&lt;/strong&gt;: Spreads either volume or pitch across all 16 pads for expressive melodic playing of a single sample.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Note repeat&lt;/strong&gt;: Hold a pad while pressing Note Repeat to generate rhythmic rolls quantized to 1/8, 1/16, or 1/32 triplets.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Choke groups&lt;/strong&gt;: Assign pads to mutually exclusive mute groups (such as open and closed hi-hats).&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Try it
&lt;/h3&gt;

&lt;p&gt;Load a vocal chop onto pad 1, turn on 16-Level Tuning, and play pitched vocal melodies straight from a MIDI keyboard or pad controller.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;MIDI Notes -&amp;gt; MPC -&amp;gt; Saturator -&amp;gt; Audio Out
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  20. Looper: multi-layer live performance phrase looper
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;Looper&lt;/strong&gt; node is designed for live improvisation, enabling bar-quantized audio phrase recording, seamless overdubbing, and speed manipulation.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/..%2Fassets%2Fnodes%2Fhd%2Flooper.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/..%2Fassets%2Fnodes%2Fhd%2Flooper.webp" alt="Looper node in Infinite"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  How it works
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Bar-quantized punch-in&lt;/strong&gt;: Automatically rounds start and stop commands to the nearest bar boundary (1, 2, 4, 8, or 16 bars).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Non-destructive overdubbing&lt;/strong&gt;: Layer takes indefinitely with an adjustable decay feedback control to prevent buildup.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reverse &amp;amp; half-speed&lt;/strong&gt;: Instant reverse toggle and half-speed playback for tape-style pitch drop effects.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Boundary crossfades&lt;/strong&gt;: Applies 5ms micro-crossfades across loop seams, eliminating clicks on imperfect takes.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Try it
&lt;/h3&gt;

&lt;p&gt;Record a 2-bar guitar or vocal loop, hit Dub to add counter-melodies, and toggle Reverse for an immediate backwards psychedelic texture.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Audio In -&amp;gt; Looper -&amp;gt; Stereo Delay -&amp;gt; Audio Out
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Synthesis on a unified graph
&lt;/h2&gt;

&lt;p&gt;Because Infinite shares a single execution graph across audio, 2D compositing, and 3D geometry, these twenty synthesizers are not confined to traditional DAW audio tracks. &lt;/p&gt;

&lt;p&gt;You can drive a Wavetable position from a particle system's average kinetic energy, strike a Metallic resonator whenever a 3D bouncing sphere collides with a floor plane, or scan a generative reaction-diffusion texture through Wave Terrain at 48kHz.&lt;/p&gt;

&lt;p&gt;Drop any synthesizer onto the canvas, wire it up, and explore sound design unconstrained by plugin windows.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://infinitedevices.org/blog/every-synthesizer-node-in-infinite-sound-design-guide.html" rel="noopener noreferrer"&gt;https://infinitedevices.org/blog/every-synthesizer-node-in-infinite-sound-design-guide.html&lt;/a&gt;. Infinite is a free, open-source DAW for visuals, music and code: &lt;a href="https://infinitedevices.org" rel="noopener noreferrer"&gt;infinitedevices.org&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>synthesizers</category>
      <category>sounddesign</category>
      <category>modularsynth</category>
      <category>dsp</category>
    </item>
    <item>
      <title>Granular synthesis in modular audio: soundscapes and grain clouds</title>
      <dc:creator>naman</dc:creator>
      <pubDate>Wed, 11 Nov 2026 13:15:18 +0000</pubDate>
      <link>https://dev.to/n1m21n/granular-synthesis-in-modular-audio-soundscapes-and-grain-clouds-48p7</link>
      <guid>https://dev.to/n1m21n/granular-synthesis-in-modular-audio-soundscapes-and-grain-clouds-48p7</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fpnevkdh5txrobfctclyp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fpnevkdh5txrobfctclyp.png" alt="Technical architecture diagram of granular synthesis in modular audio, grain windowing, and feature sorting" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Granular synthesis in modular audio transforms continuous recorded sound into swarms of microscopic acoustic quanta. Rather than playing back an audio recording as a fixed linear timeline, granular synthesis deconstructs source audio into tiny acoustic fragments called grains, typically lasting between 5 and 100 milliseconds. By controlling the density, duration, pitch transposition, spatial distribution, and playback position of hundreds of simultaneous grains, sound designers can stretch time to infinity, dissolve field recordings into shimmering ambient clouds, or restructure rhythmic loops into completely new acoustic textures.&lt;/p&gt;

&lt;p&gt;In &lt;a href="https://infinitedevices.org" rel="noopener noreferrer"&gt;Infinite&lt;/a&gt;, granular processing is not confined to an isolated plugin window or a static offline bounce. Granular processing operates directly on the real-time node canvas, where per-sample DSP, modulation signals, and GPU graphics interact within a single unified graph. Audio from microphones, live instruments, or loaded audio samples can be continuously streamed into granular buffers, modulated by low-frequency oscillators and rhythmic sequencers, and patched simultaneously into spatial delay networks and reactive visual shaders.&lt;/p&gt;

&lt;p&gt;This guide explores the technical foundations of real-time granular synthesis, the mathematics of grain windowing and energy normalisation, the architecture of Infinite's native &lt;code&gt;Granular&lt;/code&gt; and &lt;code&gt;Grain Molder&lt;/code&gt; nodes, and practical routing recipes for experimental sound design.&lt;/p&gt;

&lt;h2&gt;
  
  
  Principles of micro-sound and granular synthesis
&lt;/h2&gt;

&lt;p&gt;The physical concept of micro-sound originates in the pioneering work of physicist Dennis Gabor and composer Iannis Xenakis, later formalized by Curtis Roads in &lt;em&gt;Microsound&lt;/em&gt;. Gabor demonstrated that any continuous acoustic signal can be represented as a two-dimensional matrix of time-frequency quanta, analogous to quantum wave packets in quantum mechanics.&lt;/p&gt;

&lt;p&gt;A single isolated grain lasting 20 milliseconds is too short for the human auditory system to perceive as a continuous musical tone. When heard alone, a micro-grain sounds like a dry click or brief tap. However, when dozens or hundreds of grains are scheduled in rapid succession or layered simultaneously, a psychoacoustic transformation occurs:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Quasi-synchronous grain streams&lt;/strong&gt;: when grains are emitted at strictly regular periodic intervals, the repetition rate introduces a perceived fundamental pitch equal to the emission frequency ($f_0 = 1 / \Delta t$). At low rates (1 to 20 Hz), the listener hears a rapid train of distinct impulses or rhythmic ratchets. As the emission density exceeds 30 to 40 Hz, the individual grains fuse into a continuous pitched tone, a phenomenon known as pulsar synthesis.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Asynchronous grain clouds&lt;/strong&gt;: when grain onset times, durations, and read positions are perturbed by stochastic jitter, the periodic pulse dissolves. The ear no longer tracks individual events or synthetic pitch pulses; instead, it perceives a diffuse, textural acoustic cloud. By modulating the variance of read offsets (position spray) and pitch jitter, a sound designer can smoothly transition from pristine sample playback to lush, cinematic drones.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Time-domain representation of grain emission:

Periodic Train (Pulsar):
  +---+     +---+     +---+     +---+     +---+
  | g |     | g |     | g |     | g |     | g |     --&amp;gt; Perceived fundamental pitch
  +---+     +---+     +---+     +---+     +---+
  |&amp;lt;-- Delta t --&amp;gt;|

Stochastic Cloud (Asynchronous):
     +-----+         +---+
     | g1  |         |g3 |       +------+
     +-----+         +---+       |  g5  |           --&amp;gt; Diffuse ambient texture
        +-------+          +--+  +------+
        |  g2   |          |g4|
        +-------+          +--+
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Controlling this transformation requires precise real-time scheduling. In traditional tape-based composition, cutting and splicing thousands of microscopic fragments was a laborious manual task. In modern digital audio environments, digital signal processors generate, interpolate, envelope, and accumulate hundreds of active grains per audio buffer without latency or dropouts.&lt;/p&gt;

&lt;h2&gt;
  
  
  Anatomy of a grain: windows and envelopes
&lt;/h2&gt;

&lt;p&gt;Extracting a raw slice of digital audio creates abrupt discontinuities at the start and end boundaries. If a grain begins or ends away from a natural zero-crossing, the instantaneous voltage step creates high-frequency spectral splatter, perceived as harsh clicks and buzzing.&lt;/p&gt;

&lt;p&gt;To eliminate boundary clicks, every grain must be multiplied by a smooth windowing envelope $w(t)$ over its normalized lifespan $t \in [0, 1]$. The shape of this window determines both the temporal attack and the harmonic colour of the grain cloud:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Window function comparison:

Hann:            Gaussian:        Exponential Decay:
    .-'-.            .---.            |\
  .'     '.        .'     '.          | \
 /         \      /         \         |  \..__
'-----------'    '-----------'        '-------'
Smooth spectrum  Optimal focus        Snappy strike
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Infinite provides five distinct window functions within its native granular DSP engine:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Hann window
&lt;/h3&gt;

&lt;p&gt;The raised cosine window is the standard choice for smooth time-stretching and ambient texture generation:&lt;/p&gt;

&lt;p&gt;$$w(t) = 0.5 \cdot (1 - \cos(2\pi t))$$&lt;/p&gt;

&lt;p&gt;The Hann window provides gentle attack and release slopes, with spectral sidelobes falling off at 18 dB per octave. It eliminates all transient clicks while preserving the harmonic purity of melodic source material.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Gaussian window
&lt;/h3&gt;

&lt;p&gt;The Gaussian curve offers optimal mathematical localisation in both the time and frequency domains:&lt;/p&gt;

&lt;p&gt;$$w(t) = \exp\left(-8 \cdot (2t - 1)^2\right)$$&lt;/p&gt;

&lt;p&gt;Because the Gaussian curve approaches zero smoothly without abrupt truncation, it produces minimal spectral smearing. Grains windowed with a Gaussian envelope retain focused transient clarity, making it ideal for vocal textures and acoustic instruments.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Triangle window
&lt;/h3&gt;

&lt;p&gt;The Bartlett or triangular window applies symmetric linear ramps:&lt;/p&gt;

&lt;p&gt;$$w(t) = 1 - 2 \cdot |t - 0.5|$$&lt;/p&gt;

&lt;p&gt;With sharper transitions at the apex and boundaries, the triangle window introduces subtle high-frequency harmonic edge, lending a bright, crystalline character to dense grain clouds.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Exponential decay window
&lt;/h3&gt;

&lt;p&gt;Unlike symmetric windows, the exponential decay window mimics natural acoustic impact envelopes:&lt;/p&gt;

&lt;p&gt;$$w(t) = \sin(\pi t) \cdot \exp(-3t) \cdot 2.3$$&lt;/p&gt;

&lt;p&gt;This envelope combines a rapid, snappy onset with a curved decay tail. When applied to granular playback, it transforms sustained audio buffers into percussive micro-bursts, rain droplets, and metallic scatter.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Trapezoid window
&lt;/h3&gt;

&lt;p&gt;The trapezoid window features steep linear attack and decay slopes (12% of total grain duration) flanking an 88% flat sustain plateau:&lt;/p&gt;

&lt;p&gt;$$w(t) = \max\left(0, \min\left(1, \min\left(\frac{t}{0.12}, \frac{1 - t}{0.12}\right)\right)\right)$$&lt;/p&gt;

&lt;p&gt;This envelope preserves the natural uncoloured amplitude of the source material for the majority of the grain duration, applying brief micro-fades only at the boundaries. It is particularly effective for granular loop slicing and stutter effects.&lt;/p&gt;

&lt;h3&gt;
  
  
  High-order fractional interpolation
&lt;/h3&gt;

&lt;p&gt;When grains are pitch-shifted or played back at arbitrary speed ratios, the read position rarely aligns with discrete integer sample indices. Truncating to the nearest sample or using simple linear interpolation introduces noticeable aliasing and high-frequency noise.&lt;/p&gt;

&lt;p&gt;Infinite's granular engine employs 4-point, 3rd-order Hermite cubic interpolation (&lt;code&gt;ReadSampleHermite&lt;/code&gt;) for every sample lookup. Hermite interpolation fits a smooth cubic polynomial across four neighbouring sample points ($y_{-1}, y_0, y_1, y_2$), matching both position and first-order derivatives. This ensures continuous, artifact-free playback across pitch transpositions spanning multiple octaves.&lt;/p&gt;

&lt;h2&gt;
  
  
  Real-time engine architecture in Infinite
&lt;/h2&gt;

&lt;p&gt;Executing granular synthesis in real time requires strict concurrency control and zero-allocation memory discipline. In Infinite, the granular subsystem separates duties between two core components:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;GranularNode&lt;/code&gt; (main UI thread)&lt;/strong&gt;: manages sample loading, waveform cache rendering, start and end trim markers, parameter serialisation to &lt;code&gt;.inf&lt;/code&gt; patch files, and user interaction.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;AudioGranularNode&lt;/code&gt; (real-time audio thread)&lt;/strong&gt;: executes inside the high-priority OS audio callback, advancing the master scan playhead, spawning active grains, computing Hermite interpolation, and accumulating stereo output buffers.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;+-----------------------------------------------------------------+
|                           MAIN THREAD                           |
|                                                                 |
|  [GranularNode]                                                 |
|         |                                                       |
|         +---&amp;gt; Sample file loading (.wav, .flac, .aif)           |
|         +---&amp;gt; Waveform peak cache generation                    |
|         +---&amp;gt; Visual start/end trim drag handles                |
|         +---&amp;gt; ParamRef registration for modulation cables       |
+-----------------------------------------------------------------+
                                |
                   Lock-free SampleSlot &amp;amp; Atomic Params
                                |
                                v
+-----------------------------------------------------------------+
|                          AUDIO THREAD                           |
|                                                                 |
|  [AudioGranularNode]                                            |
|         |                                                       |
|         +---&amp;gt; Live recording stream from Audio In pin           |
|         +---&amp;gt; Master scan playhead accumulator                  |
|         +---&amp;gt; Pre-allocated Grain pool (kMaxGrains = 64)        |
|         +---&amp;gt; Stochastic RNG for jitter &amp;amp; pitch spray           |
|         +---&amp;gt; Hermite 4-point cubic interpolation               |
|         +---&amp;gt; Power-preserving energy normalisation             |
|         +---&amp;gt; Constant-power stereo panning                     |
+-----------------------------------------------------------------+
                                |
                   Lock-free Visual Snapshot Ring
                                |
                                v
+-----------------------------------------------------------------+
|                         VIEWPORT / UI                           |
|                                                                 |
|  Real-time grain dots rendering at 60 fps over waveform         |
+-----------------------------------------------------------------+
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Pre-allocated grain pools and zero allocation
&lt;/h3&gt;

&lt;p&gt;The audio thread must never allocate heap memory (&lt;code&gt;malloc&lt;/code&gt; or &lt;code&gt;new&lt;/code&gt;) or block on mutexes. Infinite pre-allocates a fixed pool of grain structures (&lt;code&gt;kMaxGrains = 64&lt;/code&gt;) when the node is instantiated. When the spawn timer expires, the engine scans the pool for an inactive slot or reclaims the oldest finished grain.&lt;/p&gt;

&lt;p&gt;If a new audio file is loaded during playback, the audio thread swaps sample buffers via an atomic lock-free &lt;code&gt;SampleSlot&lt;/code&gt;. The old buffer is safely released on the background thread only after the audio thread has released its reference, preventing audio glitches.&lt;/p&gt;

&lt;h3&gt;
  
  
  Power-preserving energy normalisation
&lt;/h3&gt;

&lt;p&gt;In granular synthesis, changing grain density or grain length dramatically alters the number of overlapping grains. At low density (e.g. 5 grains per second of 20 ms duration), overlap is minimal. At high density (e.g. 80 grains per second of 300 ms duration), twenty or more grains may sound simultaneously.&lt;/p&gt;

&lt;p&gt;Summing twenty overlapping grains without compensation causes severe digital clipping and distortion. Conversely, dividing the output by the maximum theoretical grain count leaves sparse grain streams inaudibly quiet.&lt;/p&gt;

&lt;p&gt;Infinite solves this using automatic power-preserving energy normalisation. For each spawned grain, the engine calculates the overlap factor based on duration and spawn interval:&lt;/p&gt;

&lt;p&gt;$$\text{overlapFactor} = \max\left(1.0, \frac{\text{totalFrames}}{\text{intervalFrames}}\right)$$&lt;/p&gt;

&lt;p&gt;$$\text{grainGain} = \frac{1}{\sqrt{\text{overlapFactor}}}$$&lt;/p&gt;

&lt;p&gt;By scaling each grain inversely by the square root of the overlap factor, the engine maintains constant root-mean-square (RMS) acoustic energy across radical density and length automations.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Granular node: clouds, spray and freeze
&lt;/h2&gt;

&lt;p&gt;The native &lt;code&gt;Granular&lt;/code&gt; node provides a complete suite of controls for sculpting micro-sound clouds:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F1i98y2wxy3x39gpuks5i.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F1i98y2wxy3x39gpuks5i.webp" alt="Granular node in Infinite" width="800" height="952"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Playhead positioning and scan speed
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;position&lt;/code&gt; [0.0 to 1.0]&lt;/strong&gt;: sets the base playback read position within the sample buffer. When patched to an external modulation source, such as an LFO or envelope, this acts as a precision scrubbing control.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;scan&lt;/code&gt; [-2.0x to +2.0x]&lt;/strong&gt;: enables autonomous playhead movement. Positive values scrub forward at fractional or accelerated speeds; negative values scrub backward. When set to 0.0, the playhead remains stationary, sustaining a micro-slice indefinitely.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;start&lt;/code&gt; and &lt;code&gt;end&lt;/code&gt; [0.0 to 1.0]&lt;/strong&gt;: visual trim markers that constrain grain emission to a specific region of interest. When &lt;code&gt;loop&lt;/code&gt; is active, the scan playhead and spawned grains wrap seamlessly between these boundaries.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Dispersion and stochastic jitter
&lt;/h3&gt;

&lt;p&gt;Uniform grain emission sounds robotic and synthetic. To create organic, living textures, &lt;code&gt;Granular&lt;/code&gt; provides dedicated dispersion controls:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;randomPos&lt;/code&gt; (Position spray)&lt;/strong&gt;: adds Gaussian stochastic jitter to the spawn position of each grain. Small amounts (5% to 15%) introduce subtle acoustic shimmer; large amounts (50% to 100%) scatter grains across the entire buffer, dissolving temporal structure into an ambient wash.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;randomLength&lt;/code&gt;&lt;/strong&gt;: introduces random variation to individual grain durations, preventing repetitive flutter rhythms.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;randomPitch&lt;/code&gt; [0 to 24 semitones]&lt;/strong&gt;: applies random pitch transposition to each grain. Setting this to 12 semitones produces wide harmonic octave clouds; micro-tuning settings (0.2 to 0.5 semitones) create lush natural chorusing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;randomPan&lt;/code&gt; and &lt;code&gt;width&lt;/code&gt;&lt;/strong&gt;: scatters grains across the stereo field using constant-power equal-energy panning ($pan_L = \cos\theta, pan_R = \sin\theta$).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;reverseProb&lt;/code&gt; [0.0 to 1.0]&lt;/strong&gt;: sets the probability that an individual grain will play backward. Mixing 20% to 30% reverse grains adds ethereal spectral backwards tails without reversing the master playback direction.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Freeze mode and live buffer capture
&lt;/h3&gt;

&lt;p&gt;Toggling &lt;code&gt;freeze&lt;/code&gt; halts advancement of the master scan playhead. The engine continues spawning overlapping grains from the current position with all active spray and pitch jitter parameters intact. This captures an infinite, stationary drone from any transient sound.&lt;/p&gt;

&lt;p&gt;Additionally, &lt;code&gt;Granular&lt;/code&gt; includes a dedicated audio input pin (&lt;code&gt;record in&lt;/code&gt;). Sound designers can route live microphone signals, modular synth patches, or drum tracks directly into the node. Toggling record captures incoming audio into the internal ring buffer in real time, allowing immediate granular manipulation of live performance inputs.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Grain Molder node: topological sorting and scrambling
&lt;/h2&gt;

&lt;p&gt;While standard granular engines process audio chronologically, the &lt;code&gt;Grain Molder&lt;/code&gt; node introduces a radically different paradigm: time-domain grain sorting.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F3s17fl5v37oporj4kj9n.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F3s17fl5v37oporj4kj9n.webp" alt="Grain Molder node in Infinite" width="800" height="816"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Grain Molder&lt;/code&gt; slices incoming audio buffers into overlapping grains (10 to 500 ms) and evaluates an acoustic metric for every slice:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;Level&lt;/code&gt; (RMS amplitude)&lt;/strong&gt;: calculates the root-mean-square energy of each grain. Sorting by level arranges the audio from quietest grains to loudest grains, or vice versa.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;Brightness&lt;/code&gt; (Spectral centroid)&lt;/strong&gt;: calculates the high-frequency energy distribution or zero-crossing rate. Sorting by brightness groups dark, low-frequency segments together, transitioning progressively into sharp, bright transients.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;Random&lt;/code&gt;&lt;/strong&gt;: generates a deterministic, seed-based pseudo-random permutation of grain indices.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Grain sorting process in Grain Molder:

Original chronological order:
[G1: quiet] [G2: loud] [G3: medium] [G4: peak] [G5: silent]

Sorted by Level (ascending order):
[G5: silent] [G1: quiet] [G3: medium] [G2: loud] [G4: peak]  --&amp;gt; Natural riser
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The Amount control: continuous order interpolation
&lt;/h3&gt;

&lt;p&gt;The defining control of &lt;code&gt;Grain Molder&lt;/code&gt; is the &lt;strong&gt;&lt;code&gt;amount&lt;/code&gt;&lt;/strong&gt; slider [0.0 to 1.0]. Rather than snapping abruptly between original playback and sorted order, &lt;code&gt;amount&lt;/code&gt; provides a continuous morph:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;At &lt;strong&gt;0.0&lt;/strong&gt;, the buffer plays back in its original chronological sequence.&lt;/li&gt;
&lt;li&gt;At &lt;strong&gt;1.0&lt;/strong&gt;, the buffer plays back in strictly sorted metric rank order.&lt;/li&gt;
&lt;li&gt;At intermediate values (e.g. &lt;strong&gt;0.45&lt;/strong&gt;), grains undergo continuous partial scrambling, introducing subtle rhythmic dislocations while preserving the overarching melodic contour.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When applied to complex acoustic material such as acoustic drum loops or orchestral recordings, automating the &lt;code&gt;amount&lt;/code&gt; slider from 0.0 to 1.0 over four bars produces a natural, glitch-free build-up or riser without requiring volume automation or pitch risers.&lt;/p&gt;

&lt;h2&gt;
  
  
  Modular routing: modulation, effects and visuals
&lt;/h2&gt;

&lt;p&gt;The power of granular synthesis expands exponentially when connected to Infinite's modular canvas. Because parameters in Infinite are exposed as typed &lt;code&gt;ParamRef&lt;/code&gt; targets, any slider can be modulated by external control signals.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Modular canvas signal flow:

  [Audio In] --------&amp;gt; (record in)
                           |
  [LFO / Random] ----&amp;gt; (position)
                           |
  [Step Sequencer] --&amp;gt; (pitchShift)
                           |
                     [ Granular ]
                           |  (Stereo Audio Out)
                           +------------------------+
                           |                        |
                           v                        v
                    [ Stereo Delay ]        [ AudioTexture ]
                           |                        |
                    [ Reverb ]              [ AudioDisplacement ]
                           |                        |
                    [ Audio Out ]           [ Render 3D ]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Patch 1: Ambient orchestral shimmer cloud
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Drop an audio sample containing acoustic strings or piano into a &lt;code&gt;Granular&lt;/code&gt; node.&lt;/li&gt;
&lt;li&gt;Set &lt;code&gt;grainLength&lt;/code&gt; to 140 ms, &lt;code&gt;density&lt;/code&gt; to 35 Hz, and select the &lt;code&gt;Gaussian&lt;/code&gt; window shape.&lt;/li&gt;
&lt;li&gt;Set &lt;code&gt;scan&lt;/code&gt; to 0.05x for ultra-slow forward progression.&lt;/li&gt;
&lt;li&gt;Set &lt;code&gt;randomPos&lt;/code&gt; to 20%, &lt;code&gt;randomPitch&lt;/code&gt; to 12 semitones, and &lt;code&gt;randomPan&lt;/code&gt; to 85%.&lt;/li&gt;
&lt;li&gt;Wire a slow sine &lt;code&gt;LFO&lt;/code&gt; (0.05 Hz) into &lt;code&gt;position&lt;/code&gt; to gently wander across the sample.&lt;/li&gt;
&lt;li&gt;Connect the stereo audio output of &lt;code&gt;Granular&lt;/code&gt; into a &lt;code&gt;Stereo Delay&lt;/code&gt; node, followed by a lush &lt;code&gt;Reverb&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Engage &lt;code&gt;freeze&lt;/code&gt; during dense chords to lock the texture into an infinite, evolving ambient pad.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Patch 2: Granular drum break scrambler
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Load a classic breakbeat into a &lt;code&gt;Grain Molder&lt;/code&gt; node.&lt;/li&gt;
&lt;li&gt;Set &lt;code&gt;grainMs&lt;/code&gt; to 60 ms and choose the &lt;code&gt;Level&lt;/code&gt; sorting mode.&lt;/li&gt;
&lt;li&gt;Wire a synchronized ramp LFO running at 1/2 bar into the &lt;code&gt;amount&lt;/code&gt; parameter.&lt;/li&gt;
&lt;li&gt;As the LFO ramps from 0% to 100%, the break progressively reassembles itself from quiet ghost notes into clustered snare and kick peaks, creating an automated rhythmic fill.&lt;/li&gt;
&lt;li&gt;Route the output into an &lt;code&gt;AudioMeter&lt;/code&gt; to observe peak levels, ensuring the mix sits cleanly inside your master bus.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Patch 3: Synaesthetic granular audiovisuals
&lt;/h3&gt;

&lt;p&gt;Granular synthesis produces intricate acoustic micro-transients that are ideally suited for driving real-time computer graphics. In Infinite, audio and visuals share the same memory space:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Tap the stereo audio cable exiting &lt;code&gt;Granular&lt;/code&gt; and patch it into an &lt;code&gt;AudioTexture&lt;/code&gt; node.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;AudioTexture&lt;/code&gt; converts time-domain grains and spectral bands into a dynamic GPU texture.&lt;/li&gt;
&lt;li&gt;Connect the texture into an &lt;code&gt;AudioDisplacement&lt;/code&gt; node deforming a high-density &lt;code&gt;Mesh Sphere&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;As grains trigger and scatter across the stereo field, the 3D sphere ripples and pulses in direct synchronisation with individual grain windows.&lt;/li&gt;
&lt;li&gt;Pipe the deformed geometry into a &lt;code&gt;Render 3D&lt;/code&gt; node to view the resulting particle mesh in the live viewport.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For broader procedural routing possibilities, explore Infinite's &lt;a href="https://infinitedevices.org/library.html" rel="noopener noreferrer"&gt;node library&lt;/a&gt; and our companion architectural guide on &lt;a href="https://infinitedevices.org/blog/node-based-daw-modular-audio-routing.html" rel="noopener noreferrer"&gt;node-based DAW workflows&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Comparing granular synthesis and spectral stretching
&lt;/h2&gt;

&lt;p&gt;While both granular synthesis and spectral processing manipulate audio in non-linear ways, they operate on different mathematical principles:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Parameter&lt;/th&gt;
&lt;th&gt;Granular Synthesis (&lt;code&gt;Granular&lt;/code&gt;)&lt;/th&gt;
&lt;th&gt;Spectral Stretching (&lt;code&gt;PaulStretch&lt;/code&gt;)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Domain&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Time-domain windowed micro-quanta&lt;/td&gt;
&lt;td&gt;Frequency-domain STFT phase randomisation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Grain duration&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;5 ms to 1000 ms&lt;/td&gt;
&lt;td&gt;2048 to 65536 FFT sample bins&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Pitch manipulation&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Per-grain Hermite rate transposition&lt;/td&gt;
&lt;td&gt;Spectral bin frequency shifting&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Transient response&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Preserves micro-attacks with tight windows&lt;/td&gt;
&lt;td&gt;Diffuses all transients into glassy pads&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Memory model&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Lock-free sample ring buffers&lt;/td&gt;
&lt;td&gt;Overlap-add IFFT synthesis buffers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Primary application&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Clouds, texture scatter, live glitch, stutter&lt;/td&gt;
&lt;td&gt;Extreme ambient stretching (10x to 1000x)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;For extreme time-stretching exceeding 50x duration, spectral algorithms such as &lt;a href="https://infinitedevices.org/blog/paulstretch-extreme-spectral-time-stretching.html" rel="noopener noreferrer"&gt;PaulStretch&lt;/a&gt; excel at eliminating all perceived grain repetition. For rhythmic manipulation, micro-sound scattering, and interactive live performance, real-time granular synthesis remains unmatched.&lt;/p&gt;

&lt;h2&gt;
  
  
  Technical limits and performance considerations
&lt;/h2&gt;

&lt;p&gt;When authoring complex granular patches in Infinite, several practical engineering limits apply:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Voice ceiling and CPU load&lt;/strong&gt;: the &lt;code&gt;AudioGranularNode&lt;/code&gt; engine tracks up to 64 simultaneous active grains (&lt;code&gt;kMaxGrains&lt;/code&gt;). Each active grain performs four Hermite cubic sample reads and window evaluation calculations per sample. On modern Apple Silicon and x86_64 multi-core processors, running two to four granular engines consumes less than 3% CPU. However, pushing multiple instances to maximum density (100 Hz with 1000 ms length) will saturate the pre-allocated grain pool.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Buffer capacity&lt;/strong&gt;: the live recording buffer captures up to 60 seconds of uncompressed 32-bit floating point audio at 44.1 or 48 kHz. Recording beyond this duration sets the internal overflow flag and halts writing to prevent memory exhaustion.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stand-alone and host architecture&lt;/strong&gt;: Infinite is a standalone application and modular plugin host; it does not ship as an AAX plugin for Avid Pro Tools. It hosts native VST3 and AU plugins, routes MIDI and audio bidirectionally, and exports rendered compositions headless via its command-line interface.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;Granular synthesis bridges the gap between micro-sound physics and musical sound design. By combining high-order Hermite interpolation, flexible window envelopes, stochastic spray generators, and topological metric sorting within a unified modular canvas, Infinite provides an expressive platform for real-time acoustic exploration.&lt;/p&gt;

&lt;p&gt;To begin building your own granular clouds, download the latest release of &lt;a href="https://infinitedevices.org" rel="noopener noreferrer"&gt;Infinite&lt;/a&gt;, open the canvas, and patch an audio sample into &lt;code&gt;Granular&lt;/code&gt;.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://infinitedevices.org/blog/granular-synthesis-modular-audio-sound-design.html" rel="noopener noreferrer"&gt;https://infinitedevices.org/blog/granular-synthesis-modular-audio-sound-design.html&lt;/a&gt;. Infinite is a free, open-source DAW for visuals, music and code: &lt;a href="https://infinitedevices.org" rel="noopener noreferrer"&gt;infinitedevices.org&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>granularsynthesis</category>
      <category>modularaudio</category>
      <category>sounddesign</category>
      <category>ambientmusic</category>
    </item>
    <item>
      <title>L-system procedural 3D branching and fractal generation</title>
      <dc:creator>naman</dc:creator>
      <pubDate>Wed, 11 Nov 2026 13:15:13 +0000</pubDate>
      <link>https://dev.to/n1m21n/l-system-procedural-3d-branching-and-fractal-generation-1l4j</link>
      <guid>https://dev.to/n1m21n/l-system-procedural-3d-branching-and-fractal-generation-1l4j</guid>
      <description>&lt;p&gt;An l-system procedural 3d branching architecture brings the algorithmic elegance of formal rewriting grammars into real-time computer graphics and modular audiovisual performance. In traditional generative design, procedural geometry often relies on explicit loops, mathematical trigonometric functions, or Perlin noise fields. While noise produces organic displacement and sine waves yield predictable oscillation, neither method captures the developmental morphology of living organisms: structured self-similarity, hierarchical vascular branching, and recursive form unfolding across space and time.&lt;/p&gt;

&lt;p&gt;In modular workstations like &lt;a href="https://infinitedevices.org/" rel="noopener noreferrer"&gt;Infinite&lt;/a&gt;, the Lindenmayer system bridges formal language theory, three-dimensional geometry, and live sound design. By evaluating production rules inside a native &lt;code&gt;L-System&lt;/code&gt; node, creative coders can grow intricate botanical canopies, generate procedural coral and crystal formations, and modulate geometric growth parameters live using incoming audio frequencies.&lt;/p&gt;

&lt;p&gt;Here is how Lindenmayer grammars operate, how three-dimensional turtle geometry navigates space, how branch strands are swept into watertight polygonal tubes, and how to patch audio-reactive procedural trees on a unified canvas.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fnqblmzzwp4wedmjcgk96.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fnqblmzzwp4wedmjcgk96.png" alt="L-system procedural 3D branching diagram showing rewrite grammar, turtle orientation vectors, tree hierarchy, and node graph" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Formal grammars and parallel rewriting
&lt;/h2&gt;

&lt;p&gt;The mathematical foundation of Lindenmayer systems was developed in 1968 by Hungarian theoretical biologist and botanist Aristid Lindenmayer. Originally formulated to study the growth patterns of multicellular algae, mosses, and vascular plants, L-systems belong to the family of formal rewriting grammars.&lt;/p&gt;

&lt;p&gt;In classical Chomsky grammars used across compiler design, production rules are applied sequentially, replacing one non-terminal symbol at a time. In contrast, an L-system applies its replacement rules in parallel across every symbol in the string simultaneously. This parallel replacement reflects biological cell division, where multiple biological structures grow and divide at the same physical instant.&lt;/p&gt;

&lt;p&gt;A deterministic context-free L-system (known formally as a DOL-system) is defined by three components:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Alphabet: A finite set of formal symbols &lt;code&gt;V&lt;/code&gt; containing characters that can be replaced or walked by a geometry interpreter.&lt;/li&gt;
&lt;li&gt;Axiom: An initial seed string &lt;code&gt;omega&lt;/code&gt; of symbols chosen from &lt;code&gt;V&lt;/code&gt; that defines the starting state of the organism.&lt;/li&gt;
&lt;li&gt;Production rules: A mapping &lt;code&gt;P&lt;/code&gt; that associates predecessor characters with successor replacement strings.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Consider the canonical branching plant grammar:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Axiom: X
Rules: X = F+[[X]-X]-F[-FX]+X; F = FF
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;During generation zero, the system state consists solely of the axiom &lt;code&gt;X&lt;/code&gt;. In the first generation, the production rule replaces &lt;code&gt;X&lt;/code&gt; with its successor:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Generation 0: X
Generation 1: F+[[X]-X]-F[-FX]+X
Generation 2: FF+[[F+[[X]-X]-F[-FX]+X]-F+[[X]-X]-F[-FX]+X]-FF[-FFF+[[X]-X]-F[-FX]+X]+F+[[X]-X]-F[-FX]+X
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As iterations advance, the length of the string increases exponentially. In the native &lt;code&gt;L-System&lt;/code&gt; node inside Infinite, string expansion is governed by safety caps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The maximum number of generations is bounded by &lt;code&gt;kMaxIterations = 10&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The total rewritten symbol buffer is capped at &lt;code&gt;kMaxSymbols = 200000&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If a grammar expands beyond the symbol limit, rewriting terminates cleanly and issues a diagnostic notification. This safety ceiling guarantees that complex grammars never exhaust host memory or block real-time rendering during live performances.&lt;/p&gt;

&lt;h2&gt;
  
  
  Turtle geometry in three dimensions
&lt;/h2&gt;

&lt;p&gt;Once a string of symbols is rewritten, it must be translated into spatial form. This translation is performed by a three-dimensional turtle geometry interpreter, extending Seymour Papert's original two-dimensional Logo turtle into Cartesian space.&lt;/p&gt;

&lt;p&gt;The turtle maintains an internal state consisting of a spatial position &lt;code&gt;(px, py, pz)&lt;/code&gt; and three mutually orthogonal unit vectors that form an orthonormal frame in three dimensions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Heading vector &lt;code&gt;H&lt;/code&gt;: points in the direction the turtle is currently facing and moving forward.&lt;/li&gt;
&lt;li&gt;Left vector &lt;code&gt;L&lt;/code&gt;: points to the local left side of the turtle.&lt;/li&gt;
&lt;li&gt;Up vector &lt;code&gt;U&lt;/code&gt;: points along the local normal vector perpendicular to the heading and left vectors.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The orientation triad satisfies the cross-product relationship:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;H x L = U
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As the interpreter parses the rewritten symbol string from left to right, each character commands the turtle to move or reorient its local frame:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;F&lt;/code&gt;: Move forward by the current step length while drawing geometry.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;f&lt;/code&gt;: Move forward by the current step length without drawing geometry, creating intentional structural gaps.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;+&lt;/code&gt;: Turn left by the branching angle, spinning vectors &lt;code&gt;H&lt;/code&gt; and &lt;code&gt;L&lt;/code&gt; around axis &lt;code&gt;U&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-&lt;/code&gt;: Turn right by the branching angle, spinning vectors &lt;code&gt;H&lt;/code&gt; and &lt;code&gt;L&lt;/code&gt; in the opposite direction around axis &lt;code&gt;U&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;&amp;amp;&lt;/code&gt;: Pitch down by the branching angle, spinning vectors &lt;code&gt;H&lt;/code&gt; and &lt;code&gt;U&lt;/code&gt; around axis &lt;code&gt;L&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;^&lt;/code&gt;: Pitch up by the branching angle, spinning vectors &lt;code&gt;H&lt;/code&gt; and &lt;code&gt;U&lt;/code&gt; in the opposite direction around axis &lt;code&gt;L&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;\&lt;/code&gt;: Roll left by the branching angle, spinning vectors &lt;code&gt;L&lt;/code&gt; and &lt;code&gt;U&lt;/code&gt; around axis &lt;code&gt;H&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;/&lt;/code&gt;: Roll right by the branching angle, spinning vectors &lt;code&gt;L&lt;/code&gt; and &lt;code&gt;U&lt;/code&gt; in the opposite direction around axis &lt;code&gt;H&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;|&lt;/code&gt;: Reverse direction by 180 degrees, inverting the heading vector.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Because repeated floating-point matrix rotations accumulate subtle numerical errors over thousands of symbols, Infinite executes an orthonormal renormalisation step following each rotation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nc"&gt;Renormalize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Turtle&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="kt"&gt;float&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;u&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
   &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;float&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
   &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;len&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;sqrt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;len&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mf"&gt;1e-6f&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
         &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;/=&lt;/span&gt; &lt;span class="n"&gt;len&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
   &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This normalisation guarantees that the turtle orientation vectors never shear or collapse, maintaining geometric fidelity across deep recursive iterations.&lt;/p&gt;

&lt;h3&gt;
  
  
  Branching stacks and hierarchical state
&lt;/h3&gt;

&lt;p&gt;Botanical forms require branching structures where subsidiary twigs diverge from parent boles while preserving the original growth trajectory. In L-systems, this hierarchy is encoded through pushdown automata symbols:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;[&lt;/code&gt;: Push the current turtle state onto a lifo stack. The saved state includes spatial coordinates &lt;code&gt;(px, py, pz)&lt;/code&gt;, orientation frame vectors &lt;code&gt;H&lt;/code&gt;, &lt;code&gt;L&lt;/code&gt;, &lt;code&gt;U&lt;/code&gt;, current branch radius, and current step length. The branch radius is then multiplied by &lt;code&gt;radiusScale&lt;/code&gt;, and the step length is multiplied by &lt;code&gt;lengthScale&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;]&lt;/code&gt;: Terminate the active branch and pop the saved turtle state from the stack, restoring the parent branch position, frame orientation, radius, and step length.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Through this stack mechanism, a single linear string encodes complex tree canopies with nested sub-branches of proportional thickness and length.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tube extrusion and branching radii
&lt;/h2&gt;

&lt;p&gt;Drawing wireframe polylines produces an informative schematic, but visual rendering demands solid three-dimensional geometry with surface normals, cross-sectional volume, and UV mapping for material shaders.&lt;/p&gt;

&lt;p&gt;The native &lt;code&gt;L-System&lt;/code&gt; node solves this by sweeping each continuous branch strand into a watertight polygonal cylinder via &lt;code&gt;MeshOps::TubeAlong&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Strand points -&amp;gt; Cylindrical cross-sections -&amp;gt; Triangular quad strips -&amp;gt; Watertight mesh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Key physical parameters govern this mesh synthesis:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;sides&lt;/code&gt;: Controls the radial polygon count of the cross-sections, adjustable between 3 (producing low-poly crystalline trunks) and 24 (producing smooth organic boughs).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;radius&lt;/code&gt;: Sets the absolute base radius of the primary trunk.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;radiusScale&lt;/code&gt;: The geometric multiplier applied to &lt;code&gt;radius&lt;/code&gt; each time a sub-branch is pushed with &lt;code&gt;[&lt;/code&gt;. A value of &lt;code&gt;0.75&lt;/code&gt; ensures parent limbs are sturdier than daughter branches, mirroring Leonardo da Vinci's botanical rule of trees.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;taper&lt;/code&gt;: Governs linear narrowing along the length of each strand segment, ensuring branches taper toward their terminal buds rather than ending abruptly as blunt cylinders.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;length&lt;/code&gt; and &lt;code&gt;lengthScale&lt;/code&gt;: Control the physical reach of the primary trunk and the rate at which daughter twigs shorten toward the perimeter.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To prevent GPU memory saturation during live performances, Infinite enforces a hard cap of &lt;code&gt;kMaxStrands = 6000&lt;/code&gt; extruded tubes. Any additional branches beyond this limit remain present in the polyline curve but are excluded from polygonal mesh extrusion.&lt;/p&gt;

&lt;h2&gt;
  
  
  Dual mesh and polyline representations
&lt;/h2&gt;

&lt;p&gt;A distinctive design decision of the &lt;code&gt;L-System&lt;/code&gt; node is its dual output contract: it concurrently provides both a three-dimensional polygonal &lt;code&gt;Mesh&lt;/code&gt; and a continuous three-dimensional &lt;code&gt;Polyline&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;L-System Node
  ├── GetMesh()  -&amp;gt; Watertight 3D polygonal geometry (tubes, vertices, normals, UVs)
  └── GetCurve() -&amp;gt; Continuous 3D polyline path (reconstructed traversal points)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This dual pipeline opens versatile creative workflows:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Polygonal mesh rendering: The mesh connects directly to standard 3D rendering pipelines, accepting PBR materials, casting shadow maps, and responding to scene lighting.&lt;/li&gt;
&lt;li&gt;Path tracking and camera choreography: The &lt;code&gt;Polyline&lt;/code&gt; output connects to the &lt;code&gt;Path&lt;/code&gt; node. Because the turtle traverses the tree in deterministic order, a &lt;code&gt;Camera 3D&lt;/code&gt; can be constrained to glide along the polyline path, flying smoothly through the interior vascular channels of the fractal tree canopy.&lt;/li&gt;
&lt;li&gt;Particle flow guides: Downstream simulation nodes can distribute emitters or flow particles along the polyline curve, creating glowing sap rising through procedural veins.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Real-time audio modulation and kinetic foliage
&lt;/h2&gt;

&lt;p&gt;Because Infinite evaluates its node graph in real time, the parameters of the &lt;code&gt;L-System&lt;/code&gt; node can be dynamically modulated by audio analysis or control signals. Unlike pre-rendered 3D assets, a procedural grammar can breathe and pulse in direct synchronisation with music.&lt;/p&gt;

&lt;p&gt;Consider the following audio-reactive modulation pairings:&lt;/p&gt;

&lt;h3&gt;
  
  
  Modulating branching angles with frequency bands
&lt;/h3&gt;

&lt;p&gt;By connecting the low-frequency band of an &lt;code&gt;Audio Analyze&lt;/code&gt; node to the &lt;code&gt;angle&lt;/code&gt; parameter of &lt;code&gt;L-System&lt;/code&gt;, the physical divergence of the tree branches expands and contracts in response to bass transients:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;At quiet moments (&lt;code&gt;angle = 18.0&lt;/code&gt;), branches align closely with the primary trunk, producing a slender, dormant cypress form.&lt;/li&gt;
&lt;li&gt;On heavy kick drum or bass hits (&lt;code&gt;angle = 38.0&lt;/code&gt;), branches fan outward into an open, blossoming canopy.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Because changing the branching angle preserves the total number of vertices and triangles, angle modulation incurs zero memory allocation overhead, running at full display frame rates without dropped frames.&lt;/p&gt;

&lt;h3&gt;
  
  
  Modulating length and scale with melodic envelopes
&lt;/h3&gt;

&lt;p&gt;Connecting mid-range or high-frequency energy to &lt;code&gt;lengthScale&lt;/code&gt; dynamically alters the density of the outer foliage. When a synth arpeggio or percussion roll plays, outer branches extend outward and recoil, giving the tree an organic breathing kinetic presence.&lt;/p&gt;

&lt;h3&gt;
  
  
  Modulating growth iterations across musical sections
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;iterations&lt;/code&gt; parameter governs structural complexity. Routing a slow step sequencer or an arrangement automation curve to &lt;code&gt;iterations&lt;/code&gt; allows a seed to sprout at generation 1 during an ambient intro, expand to generation 3 in the first verse, and erupt into a fully unfurled generation 5 fractal canopy at the musical drop.&lt;/p&gt;

&lt;h2&gt;
  
  
  Composing procedural scenes in Infinite
&lt;/h2&gt;

&lt;p&gt;To assemble a finished audiovisual composition, the &lt;code&gt;L-System&lt;/code&gt; node is wired into the standard 3D rendering graph alongside lighting and camera nodes.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Audio In ──────────&amp;gt; Audio Analyze ──[Low Band]──&amp;gt; Math ──&amp;gt; L-System (angle)
                                                               │
                                                         [Mesh Output]
                                                               │
Light 3D ──&amp;gt; Scene 3D ─────────────────────────────────────&amp;gt; Material ──&amp;gt; Render 3D ──&amp;gt; Viewport
                                                                            ▲
Camera 3D ──────────────────────────────────────────────────────────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here is the step-by-step assembly process:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Add the audio chain: Place an &lt;code&gt;Audio In&lt;/code&gt; node, wire it into &lt;code&gt;Audio Analyze&lt;/code&gt;, and extract the &lt;code&gt;low&lt;/code&gt; output band. Route this through a &lt;code&gt;Math&lt;/code&gt; node to map incoming zero-to-one signal ranges into the desired angular span, such as &lt;code&gt;20.0&lt;/code&gt; to &lt;code&gt;40.0&lt;/code&gt; degrees.&lt;/li&gt;
&lt;li&gt;Add the generator: Place an &lt;code&gt;L-System&lt;/code&gt; node. Connect the scaled audio signal into the &lt;code&gt;angle&lt;/code&gt; parameter input. Set the &lt;code&gt;axiom&lt;/code&gt; to &lt;code&gt;X&lt;/code&gt; and &lt;code&gt;rules&lt;/code&gt; to &lt;code&gt;X=F+[[X]-X]-F[-FX]+X;F=FF&lt;/code&gt;. Set &lt;code&gt;iterations&lt;/code&gt; to 4 or 5.&lt;/li&gt;
&lt;li&gt;Apply materials: Wire the mesh output into a &lt;code&gt;Material&lt;/code&gt; node. Assign a deep organic albedo colour, set &lt;code&gt;roughness&lt;/code&gt; to &lt;code&gt;0.65&lt;/code&gt; for natural wood scattering, and configure a subtle emissive tint modulated by high-frequency audio energy.&lt;/li&gt;
&lt;li&gt;Set up lighting and camera: Connect the material into a &lt;code&gt;Render 3D&lt;/code&gt; node. Add a &lt;code&gt;Camera 3D&lt;/code&gt; positioned at &lt;code&gt;(0.0, 1.5, 4.0)&lt;/code&gt; targeting the centre of the tree canopy. Add two &lt;code&gt;Light 3D&lt;/code&gt; nodes: a warm directional key light and a cool cyan rim light to highlight branch contours against the dark ground.&lt;/li&gt;
&lt;li&gt;Combine with shaders: In Infinite, you can pair 3D geometry with 2D post-processing. Take the render output and composite it with background gradients or &lt;a href="https://infinitedevices.org/blog/audio-reactive-glsl-shaders.html" rel="noopener noreferrer"&gt;real-time GLSL shaders&lt;/a&gt; for depth of field and atmospheric haze.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;To explore pre-configured templates and community patches featuring procedural geometry, visit the &lt;a href="https://infinitedevices.org/library.html" rel="noopener noreferrer"&gt;patch library&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Algorithmic variations and botanical grammars
&lt;/h2&gt;

&lt;p&gt;The flexibility of Lindenmayer systems lies in their grammatical versatility. By modifying the axiom and replacement rules, the exact same node architecture generates fundamentally distinct natural forms.&lt;/p&gt;

&lt;h3&gt;
  
  
  Classic 3D bush
&lt;/h3&gt;

&lt;p&gt;This classic grammar produces balanced spherical shrubbery with uniform outward branching:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Axiom: A
Rules: A = [&amp;amp;+F[A]][&amp;amp;-F[A]][^+F[A]][^-F[A]]; F = FF
Angle: 28.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The four-way branch split combines pitch (&lt;code&gt;&amp;amp;&lt;/code&gt;, &lt;code&gt;^&lt;/code&gt;) and yaw (&lt;code&gt;+&lt;/code&gt;, &lt;code&gt;-&lt;/code&gt;) rotations, producing full three-dimensional volumetric foliage.&lt;/p&gt;

&lt;h3&gt;
  
  
  Monopodial pine tree
&lt;/h3&gt;

&lt;p&gt;For coniferous trees where a dominant central trunk continues upward while subordinate whorls emerge at regular intervals:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Axiom: !(1)F(100)/(45)A
Rules: A = [&amp;amp;(30)B]F(10)/(45)A; B = [&amp;amp;(30)F(20)]F(10)/(45)B
Angle: 25.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, the primary trunk maintains vertical dominance while lateral branch clusters spiral radially around the central stem.&lt;/p&gt;

&lt;h3&gt;
  
  
  3D Hilbert space-filling curve
&lt;/h3&gt;

&lt;p&gt;L-systems are not limited to biological plants; they also describe space-filling fractals and recursive mathematical curves:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Axiom: X
Rules: X = ^\XF^/XFX-F^//XFX&amp;amp;F+//XFX-F/X-
Angle: 90.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When evaluated with 90-degree turning angles, this grammar weaves a single continuous polyline through every sub-cube of a three-dimensional lattice. When swept into tubes and modulated with audio, it creates intricate kinetic geometric sculptures.&lt;/p&gt;

&lt;p&gt;For broader techniques combining mathematical deformation with procedural meshes, see our guide on &lt;a href="https://infinitedevices.org/blog/procedural-3d-geometry-nodes-and-audio-deformation.html" rel="noopener noreferrer"&gt;procedural 3D geometry nodes&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;L-system procedural 3D branching provides an expressive bridge between theoretical linguistics, computer graphics, and live music performance. By encoding complex natural structures into concise symbolic grammars, artists can generate organic botanical forms that remain entirely deterministic, mathematically pure, and lightweight.&lt;/p&gt;

&lt;p&gt;Through Infinite's native &lt;code&gt;L-System&lt;/code&gt; node, these formal grammars live inside an interactive modular graph. Artists can manipulate branch cross-sections, route geometry along motion paths, and modulate angles and lengths in real time to the rhythm of incoming audio. The result is a procedural instrument where mathematics, sound, and visual form grow together on a single canvas.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://infinitedevices.org/blog/l-system-procedural-3d-branching-fractals.html" rel="noopener noreferrer"&gt;https://infinitedevices.org/blog/l-system-procedural-3d-branching-fractals.html&lt;/a&gt;. Infinite is a free, open-source DAW for visuals, music and code: &lt;a href="https://infinitedevices.org" rel="noopener noreferrer"&gt;infinitedevices.org&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>lsystem</category>
      <category>procedural3d</category>
      <category>generativeart</category>
      <category>creativecoding</category>
    </item>
    <item>
      <title>Drum and bass Reese bass sound design in modular synthesisers</title>
      <dc:creator>naman</dc:creator>
      <pubDate>Wed, 11 Nov 2026 13:15:05 +0000</pubDate>
      <link>https://dev.to/n1m21n/drum-and-bass-reese-bass-sound-design-in-modular-synthesisers-36km</link>
      <guid>https://dev.to/n1m21n/drum-and-bass-reese-bass-sound-design-in-modular-synthesisers-36km</guid>
      <description>&lt;p&gt;Few sounds define underground electronic music as completely as the Reese bass. Originating on the Casio CZ-1 synthesiser under Kevin Saunderson's Reese moniker in 1988, the patch became the sonic cornerstone of jungle, drum and bass, techstep, and neurofunk. Producers from Renegade Soundwave to Ed Rush, Optical, Dillinja, and Noisia transformed what began as a simple pair of detuned oscillators into an evolving, multi-band instrument of pressure and texture.&lt;/p&gt;

&lt;p&gt;Achieving authentic drum and bass Reese bass sound design requires understanding the acoustic physics of phase cancellation, harmonic saturation, and multi-band routing. In conventional digital audio workstations, setting up this architecture requires dozens of plugin windows, complex auxiliary buses, and clunky phase-alignment utilities.&lt;/p&gt;

&lt;p&gt;In Infinite, the entire signal path lives directly on a unified node canvas. You can route audio, control voltages, and real-time graphics without latency penalties or auxiliary routing bottlenecks. Here is a step-by-step engineering breakdown of how to construct a professional, club-ready Reese bass from scratch.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F30m286c6kzqeb27rx6rg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F30m286c6kzqeb27rx6rg.png" alt="Technical diagram of modular drum and bass Reese bass sound design featuring band splitting, detuned oscillators, distortion, and audio-reactive visuals"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Acoustic foundations of the Reese bass
&lt;/h2&gt;

&lt;p&gt;At its core, a Reese bass is generated by the physical phenomenon of acoustic beating. When two periodic waveforms with nearly identical frequencies &lt;code&gt;f_1&lt;/code&gt; and &lt;code&gt;f_2&lt;/code&gt; are summed together, their phase relationship continuously shifts between constructive interference and destructive interference.&lt;/p&gt;

&lt;p&gt;The resulting composite waveform pulsates at a beat frequency determined by the absolute difference between the two oscillators:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;f_beat = |f_1 - f_2|
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If an oscillator plays an F1 note at 43.65 Hz and a second oscillator is detuned sharp by +9 cents (approximately 43.88 Hz), the beat frequency is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;f_beat = |43.88 - 43.65| = 0.23 Hz
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This 0.23 Hz differential produces a slow, hypnotic swelling cycle every 4.3 seconds. If the detune is widened to +25 cents, the beating accelerates into an aggressive growl.&lt;/p&gt;

&lt;h3&gt;
  
  
  The sub-bass phase cancellation trap
&lt;/h3&gt;

&lt;p&gt;While acoustic beating sounds rich across the midrange, it introduces a severe physical defect in the sub-bass register below 90 Hz. When the two detuned saw waves drift into anti-phase (180 degrees apart), their fundamental frequencies cancel each other out completely.&lt;/p&gt;

&lt;p&gt;On a large club sound system, this cancellation causes the low end to collapse periodically. The dancefloor feels a momentary drop in kinetic weight every time the waveforms cross zero. To build a Reese bass that translates powerfully across large subwoofers, you must decouple the sub fundamental from the detuned mid band using multi-band frequency splitting.&lt;/p&gt;




&lt;h2&gt;
  
  
  Dual oscillator core in the Analog node
&lt;/h2&gt;

&lt;p&gt;The foundation of the patch begins with the &lt;a href="https://infinitedevices.org/nodes/analog.html" rel="noopener noreferrer"&gt;&lt;code&gt;Analog&lt;/code&gt;&lt;/a&gt; node. Rather than using pre-recorded wavetables or sample loops, Infinite generates anti-aliased analogue waveforms in real time using band-limited step correction.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[ Note In ] ---&amp;gt; pitch ---&amp;gt; [ Analog Node ]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Oscillator configuration
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Oscillator 1&lt;/strong&gt;: Set the waveform to Sawtooth. Set the octave to 0 and the coarse pitch to 0 semitones. This oscillator serves as our pitch reference.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Oscillator 2&lt;/strong&gt;: Set the waveform to Sawtooth. Set the coarse pitch to 0 semitones and the fine tune control to +8.5 cents. The subtle pitch disparity creates our primary acoustic beating.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sub oscillator&lt;/strong&gt;: Configure the internal sub oscillator to a pure Sine wave, pitched exactly -1 octave down (-12 semitones). We will extract this pure sine during the band-split phase to serve as our mono sub anchor.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Phase mode&lt;/strong&gt;: Ensure phase sync is disabled so both oscillators run free. Synchronising oscillator phase on every note-on event produces an artificial, static attack. Free-running oscillators guarantee that every note triggers with a slightly different phase alignment, mimicking vintage analogue hardware.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Glide and legato&lt;/strong&gt;: Set polyphony to Mono Legato and dial in a glide time between 35 ms and 55 ms. Smooth pitch portamento between notes is essential for drum and bass basslines.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You can inspect pre-configured synthesiser templates in the &lt;a href="https://infinitedevices.org/library.html" rel="noopener noreferrer"&gt;Infinite Library&lt;/a&gt; to see how monophonic glide circuits are wired into note graphs.&lt;/p&gt;




&lt;h2&gt;
  
  
  Multi-band crossover: isolating the sub fundamental
&lt;/h2&gt;

&lt;p&gt;To resolve the phase cancellation dilemma, we split the output of the &lt;code&gt;Analog&lt;/code&gt; node into two discrete frequency bands at 110 Hz:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Sub band (20 Hz to 110 Hz)&lt;/strong&gt;: Contains only the solid, monophonic fundamental frequency. This band bypasses all distortion, modulation, and spatial effects to remain completely mono and phase-stable.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Grit band (110 Hz to 20 kHz)&lt;/strong&gt;: Contains the rich detuned saw harmonics. This band is aggressively saturated, filtered, and widened.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;We implement this split using two &lt;a href="https://infinitedevices.org/nodes/audio-filter.html" rel="noopener noreferrer"&gt;&lt;code&gt;Filter&lt;/code&gt;&lt;/a&gt; nodes operating in parallel.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;                     +---&amp;gt; [ Filter: Lowpass 110 Hz ] ---&amp;gt; (Sub Bus: Mono)
                     |
[ Analog Output ] ---+
                     |
                     +---&amp;gt; [ Filter: Highpass 110 Hz ] ---&amp;gt; [ Distortion Node ]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Configuring the crossover filters
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Sub filter&lt;/strong&gt;: Set filter topology to 4-pole Butterworth Lowpass (24 dB per octave rolloff). Set the cutoff frequency to 110 Hz with zero resonance (Q = 0.707).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Grit filter&lt;/strong&gt;: Set filter topology to 4-pole Butterworth Highpass (24 dB per octave rolloff). Set the cutoff frequency identically to 110 Hz with zero resonance (Q = 0.707).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Because both filters share matching 24 dB per octave Butterworth responses at identical corner frequencies, their phase shifts align smoothly at the crossover point without phase cancellation or comb-filter notches across the 110 Hz boundary.&lt;/p&gt;




&lt;h2&gt;
  
  
  Nonlinear waveshaping and harmonic saturation
&lt;/h2&gt;

&lt;p&gt;With the sub fundamental safely isolated, we can subject the highpassed grit band to heavy nonlinear processing without compromising the low end.&lt;/p&gt;

&lt;p&gt;We patch the highpass output directly into the &lt;code&gt;Distortion&lt;/code&gt; node. In drum and bass production, clean saw waves sound thin and dated. Squeezing them through asymmetric clipping generates complex odd and even harmonics that fill out the 300 Hz to 4 kHz frequency band.&lt;/p&gt;

&lt;h3&gt;
  
  
  The mathematics of asymmetric saturation
&lt;/h3&gt;

&lt;p&gt;A standard symmetric waveshaper clips positive and negative signal peaks identically:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;f(x) = tanh(k * x)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Symmetric clipping generates only odd harmonics (3rd, 5th, 7th), resulting in a hollow, square-wave tonality. To produce the snarling, guttural character characteristic of neurofunk, we introduce a DC bias offset before saturation. This asymmetry generates prominent even harmonics (2nd, 4th, 6th):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;f(x) = tanh(k * (x + bias)) - tanh(k * bias)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Parameter settings in the Distortion node
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Drive&lt;/strong&gt;: Increase drive to +14 dB to push the detuned saw beating into hard saturation. As the beating waveforms periodically crest, the distortion unit saturates them into dense square-like plateaus.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mode&lt;/strong&gt;: Select Asymmetric Tube Fold.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Bias&lt;/strong&gt;: Set bias to +0.22. This introduces even-order harmonic sweetness.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Oversampling&lt;/strong&gt;: Engage 4x oversampling. Hard nonlinear distortion creates harmonic energy that can exceed the Nyquist frequency (24 kHz at a 48 kHz sample rate). 4x oversampling suppresses aliasing artifacts, preserving high-frequency clarity.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Post-tilt equaliser&lt;/strong&gt;: Add a gentle +2.5 dB high-shelf boost starting at 2.2 kHz to compensate for high-frequency energy lost during saturation.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For a deeper exploration of custom mathematical waveshaping kernels, consult our technical guide on &lt;a href="https://infinitedevices.org/blog/per-sample-dsp-audio-kernels-in-field-language.html" rel="noopener noreferrer"&gt;per-sample DSP audio kernels in Field language&lt;/a&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Formant sweeps with modulated twin notch filters
&lt;/h2&gt;

&lt;p&gt;The signature vocal quality of modern Reese basses is created by sweeping notch and comb filters across the saturated spectrum. When an audio signal with dense harmonic content passes through narrow rejection notches, human ears perceive vowel-like vocal formants (such as "ow", "ah", and "ee").&lt;/p&gt;

&lt;p&gt;We insert a second &lt;code&gt;Filter&lt;/code&gt; node after the distortion stage, configured in twin-notch rejection mode.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[ Distortion Out ] ---&amp;gt; [ Filter: Twin Notch ] ---&amp;gt; [ Chorus Node ]
                               ^
                               |
                        [ Modulator LFO ]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Wiring the modulator LFO
&lt;/h3&gt;

&lt;p&gt;To bring the sound to life, we patch a &lt;code&gt;Modulator&lt;/code&gt; node to animate the filter cutoff frequency:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Modulator shape&lt;/strong&gt;: Select a morphed triangle-to-sine wave or a slow chaotic random walk.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sync rate&lt;/strong&gt;: Synchronise the LFO to the global transport, selecting 1/2 bar or 1/4 dotted divisions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Slew rate&lt;/strong&gt;: Set a 12 ms slew filter on the LFO output to prevent abrupt parameter jumps from causing audible clicks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Modulation depth&lt;/strong&gt;: Map the LFO output to the notch filter cutoff parameter with a modulation depth of 65 percent. As the bassline sustains, the notches sweep dynamically between 400 Hz and 3.2 kHz, producing the iconic moving vowel resonance.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Stereo widening and mono compatibility on club systems
&lt;/h2&gt;

&lt;p&gt;In professional sound design, width creates perceived size. However, spreading low frequencies across the stereo field is catastrophic in club venues, where subwoofer arrays are driven in mono. If out-of-phase low-frequency information reaches a mono subwoofer summing amplifier, the sound cancels itself out in the room.&lt;/p&gt;

&lt;p&gt;Because we established a multi-band split earlier in our patch, we can apply aggressive stereo expansion exclusively to the highpassed grit band, leaving the sub fundamental completely untouched in mono.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[ Sub Filter: Lowpass 110 Hz ] ------------------------+---&amp;gt; [ Audio Out: Left (Mono Sum) ]
                                                       |
[ Grit: Saturated &amp;amp; Notched ] ---&amp;gt; [ Chorus Node ] ---+---&amp;gt; [ Audio Out: Stereo Width ]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Configuring the Chorus node
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Haas delay spread&lt;/strong&gt;: Introduce a small micro-delay between the left and right channels (0.0 ms on the left channel, +14.2 ms on the right channel). This exploits the psychoacoustic Haas effect to stretch the perceived stereo image far beyond the physical speaker positions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Modulation depth&lt;/strong&gt;: Keep chorus modulation gentle (rate at 0.28 Hz, depth at 25 percent) to avoid disorienting pitch warble.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dry and wet balance&lt;/strong&gt;: Set wet mix to 60 percent.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Verifying phase correlation with the Audio Meter
&lt;/h3&gt;

&lt;p&gt;To ensure our stereo width does not cause phase issues when summed to mono, we connect the master output into an &lt;a href="https://infinitedevices.org/nodes/audio-meter.html" rel="noopener noreferrer"&gt;&lt;code&gt;Audio Meter&lt;/code&gt;&lt;/a&gt; node.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;Audio Meter&lt;/code&gt; displays a real-time goniometer and phase correlation coefficient:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;+1.0&lt;/strong&gt;: Perfect mono correlation (identical left and right channels).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;0.0&lt;/strong&gt;: Wide stereo separation with healthy decorrelation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;-1.0&lt;/strong&gt;: Total anti-phase cancellation (summing to mono will result in complete silence).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With our band-split architecture, the phase correlation meter remains pinned between +0.88 and +0.96. The sub-110 Hz foundation is completely vertical and mono, while the high-frequency grit spreads wide across the stereo perimeter.&lt;/p&gt;




&lt;h2&gt;
  
  
  Audio-reactive visual modulation on the unified canvas
&lt;/h2&gt;

&lt;p&gt;One of Infinite's most compelling design capabilities is that audio synthesis and real-time graphics share the same underlying execution engine. In standard production workflows, synchronising visuals to a bassline requires rendering an audio file, importing it into TouchDesigner or Blender, running an offline FFT, and tweaking sensitivity curves by hand.&lt;/p&gt;

&lt;p&gt;In Infinite, we can tap the exact modulation signals driving our Reese bass and route them straight into visual shaders and 3D geometry nodes in real time.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;                           +---&amp;gt; [ Filter: Twin Notch ] ---&amp;gt; [ Audio Out ]
                           |
[ Modulator LFO ] ---------+
                           |
                           +---&amp;gt; [ Audio Texture ] ---&amp;gt; [ Render 3D: Mesh Displacement ]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Patching audio-reactive graphics
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Audio Texture node&lt;/strong&gt;: We cable the output of the highpassed grit band directly into an &lt;code&gt;Audio Texture&lt;/code&gt; node. The node converts the instantaneous audio waveform and frequency spectrum into a 512x1 floating-point GPU texture buffer.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Render 3D node&lt;/strong&gt;: We pipe the &lt;code&gt;Audio Texture&lt;/code&gt; into a &lt;code&gt;Render 3D&lt;/code&gt; node to displace the vertices of a high-density geometric icosphere or wireframe terrain.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Direct beat coupling&lt;/strong&gt;: Because the visual vertex shader samples the actual audio waveform buffer at 60 frames per second, the 3D geometry pulses and ripples in physical lockstep with the acoustic beating frequencies of the detuned saw waves. Every time the oscillators slip into constructive interference, the geometry expands.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;To learn more about bridging sound and procedural visuals, read our companion guide on &lt;a href="https://infinitedevices.org/blog/make-your-first-audio-reactive-visual.html" rel="noopener noreferrer"&gt;making your first audio-reactive visual in Infinite&lt;/a&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Summary parameter reference and routing checklist
&lt;/h2&gt;

&lt;p&gt;Here is a quick reference table of every node, parameter, and cable connection in this Reese bass architecture:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Node name&lt;/th&gt;
&lt;th&gt;Parameter&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;th&gt;Purpose&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Analog&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Oscillator 1&lt;/td&gt;
&lt;td&gt;Sawtooth (0 st, 0 ct)&lt;/td&gt;
&lt;td&gt;Pitch root reference&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Analog&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Oscillator 2&lt;/td&gt;
&lt;td&gt;Sawtooth (0 st, +8.5 ct)&lt;/td&gt;
&lt;td&gt;Acoustic beating generator&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Analog&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Oscillator 3&lt;/td&gt;
&lt;td&gt;Sine (-12 st, 0 ct)&lt;/td&gt;
&lt;td&gt;Pure sub fundamental anchor&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Analog&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Portamento&lt;/td&gt;
&lt;td&gt;Mono Legato (45 ms)&lt;/td&gt;
&lt;td&gt;Authentic glide between bassline notes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;Filter&lt;/code&gt; (Sub)&lt;/td&gt;
&lt;td&gt;Topology&lt;/td&gt;
&lt;td&gt;4-pole Lowpass (110 Hz)&lt;/td&gt;
&lt;td&gt;Isolates monophonic low end&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;Filter&lt;/code&gt; (Grit)&lt;/td&gt;
&lt;td&gt;Topology&lt;/td&gt;
&lt;td&gt;4-pole Highpass (110 Hz)&lt;/td&gt;
&lt;td&gt;Extracts midrange for saturation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Distortion&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Drive &amp;amp; Bias&lt;/td&gt;
&lt;td&gt;+14.5 dB Drive, +0.22 Bias&lt;/td&gt;
&lt;td&gt;Asymmetric even/odd harmonic fold&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Distortion&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Oversampling&lt;/td&gt;
&lt;td&gt;4x Polyphase IIR&lt;/td&gt;
&lt;td&gt;Prevents Nyquist aliasing harshness&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;Filter&lt;/code&gt; (Notch)&lt;/td&gt;
&lt;td&gt;Topology&lt;/td&gt;
&lt;td&gt;Twin Notch (Q = 4.8)&lt;/td&gt;
&lt;td&gt;Dynamic vocal formant resonances&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Modulator&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Rate &amp;amp; Shape&lt;/td&gt;
&lt;td&gt;1/2 Bar Sync, Slew 12 ms&lt;/td&gt;
&lt;td&gt;Sweeps notch filters smoothly&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Chorus&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Haas Offset&lt;/td&gt;
&lt;td&gt;+14.2 ms Right Channel&lt;/td&gt;
&lt;td&gt;Wide stereo imaging on high band&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Audio Meter&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Correlation&lt;/td&gt;
&lt;td&gt;Minimum +0.85 Target&lt;/td&gt;
&lt;td&gt;Confirms mono club sound safety&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Audio Texture&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Buffer&lt;/td&gt;
&lt;td&gt;512x1 Float16 GPU Buffer&lt;/td&gt;
&lt;td&gt;Bridges acoustic beat into visual shaders&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Engineering limits and practical considerations
&lt;/h2&gt;

&lt;p&gt;When deploying complex multi-band synthesis graphs in production, keep the following practical engineering guidelines in mind:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Headroom management&lt;/strong&gt;: Asymmetric distortion and resonant notch filtering introduce gain peaks. Always leave at least -3 dBFS of digital headroom on the Reese track before it hits the master limiter. Excessive peak levels into the master bus can trigger inter-sample clipping when converted to lossy streaming formats like AAC or MP3.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Crossover frequency tuning&lt;/strong&gt;: While 110 Hz is the standard crossover frequency for drum and bass, adjust this boundary based on your track's root key. For tracks in F (fundamental at ~43 Hz, second harmonic at ~87 Hz), 100 Hz to 110 Hz works cleanly. For tracks in A (fundamental at ~55 Hz, second harmonic at ~110 Hz), shift the crossover down to 85 Hz to prevent the second harmonic from splitting awkwardly across both filters.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Equaliser carve for kick drums&lt;/strong&gt;: A dense Reese bass occupies significant energy between 80 Hz and 200 Hz. Use an envelope or sidechain compressor keyed to your kick drum to duck the Reese by 4 dB to 6 dB during the initial 40 ms of the kick transient.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;By building your bass sound design on a unified modular graph, you eliminate plugin latency drift, retain absolute control over low-end phase integrity, and create instruments that bridge sound and visuals into a single cohesive performance.&lt;/p&gt;

&lt;p&gt;Explore ready-to-run synthesiser patches and creative coding instruments in the &lt;a href="https://infinitedevices.org/library.html" rel="noopener noreferrer"&gt;Infinite Library&lt;/a&gt;, or review our tutorial on &lt;a href="https://infinitedevices.org/blog/electronic-music-sound-design-sub-bass-pluck-pad.html" rel="noopener noreferrer"&gt;sub bass, pluck, and ambient pad sound design&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://infinitedevices.org/blog/drum-and-bass-reese-bass-sound-design.html" rel="noopener noreferrer"&gt;https://infinitedevices.org/blog/drum-and-bass-reese-bass-sound-design.html&lt;/a&gt;. Infinite is a free, open-source DAW for visuals, music and code: &lt;a href="https://infinitedevices.org" rel="noopener noreferrer"&gt;infinitedevices.org&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>drumandbass</category>
      <category>sounddesign</category>
      <category>reesebass</category>
      <category>modularsynth</category>
    </item>
    <item>
      <title>Audio-reactive 3D particle systems in real time</title>
      <dc:creator>naman</dc:creator>
      <pubDate>Wed, 11 Nov 2026 13:14:58 +0000</pubDate>
      <link>https://dev.to/n1m21n/audio-reactive-3d-particle-systems-in-real-time-59eh</link>
      <guid>https://dev.to/n1m21n/audio-reactive-3d-particle-systems-in-real-time-59eh</guid>
      <description>&lt;p&gt;An audio reactive particle system transforms live musical transients and spectral frequencies into streams of kinetic points in three-dimensional space. From gentle dust motes drifting across an ambient soundscape to explosive shockwaves synchronised with sub-bass kick drums, particle systems provide an organic bridge between acoustic energy and computer graphics.&lt;/p&gt;

&lt;p&gt;In real-time visual engines and audiovisual workstations like &lt;a href="https://infinitedevices.org/" rel="noopener noreferrer"&gt;Infinite&lt;/a&gt;, audio and geometry share a unified execution graph. Rather than rendering pre-baked animations or relying on loose open sound control messages across network sockets, simulation nodes evaluate physical differential equations directly alongside audio-rate buffers. This enables deterministic, frame-accurate responses to rhythm and spectral timbre.&lt;/p&gt;

&lt;p&gt;Here is how real-time particle mechanics operate under the hood, how numerical integration handles drag and velocity, how procedural 3D turbulence vector fields create fluid motion, and how to patch an audio-reactive particle pipeline using native nodes.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fmgd3p9n1obip7td6fp7y.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fmgd3p9n1obip7td6fp7y.png" alt="Technical architecture diagram of real-time audio-reactive 3D particle simulation showing numerical integration, 3D turbulence force fields, and modular node graph"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What makes particle systems feel musical
&lt;/h2&gt;

&lt;p&gt;A common pitfall in generative music visualisation is mapping raw audio volume directly to particle count or size. When overall loudness drives everything, the visual output becomes a muddy, fluttering cloud that feels detached from the rhythmic structure of the music.&lt;/p&gt;

&lt;p&gt;Musicality in a particle system requires separating three physical aspects of sound:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Rhythmic transients&lt;/strong&gt;: Sudden bursts of energy (such as kick drums, snare rimshots, and hi-hat attacks) should trigger discrete physical events: spawning a cluster of new particles or imparting an instantaneous impulse shockwave.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Harmonic spectral balance&lt;/strong&gt;: Sustained tonal components (such as basslines, synth pads, or vocals) should influence persistent environmental force fields: shaping gravity, drag, curl noise turbulence, and orbital attraction.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Temporal decay and resonance&lt;/strong&gt;: Particle lifetimes and trail lengths should correspond to musical tempo divisions, ensuring kinetic movement breathes in sync with the song rather than piling up into visual noise.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;By decoupling instantaneous onset triggers from continuous vector fields, particles behave like physical matter reacting to sound waves propagating through a medium.&lt;/p&gt;

&lt;h2&gt;
  
  
  Numerical physics: fixed-step Euler integration
&lt;/h2&gt;

&lt;p&gt;At the core of any particle engine is numerical integration: advancing position and velocity forward across discrete steps in time.&lt;/p&gt;

&lt;p&gt;In Infinite, the &lt;a href="https://infinitedevices.org/nodes/particle-system.html" rel="noopener noreferrer"&gt;&lt;code&gt;Particle System&lt;/code&gt;&lt;/a&gt; node maintains an internal state array of particle records. Each particle stores position, velocity, remaining lifetime, initial lifetime, and scalar seed data.&lt;/p&gt;

&lt;p&gt;To prevent simulation instability when frame rates vary during heavy rendering passes, the physics simulation runs on a fixed timestep:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="n"&gt;kFixedStep&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;1.0f&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mf"&gt;120.0f&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="c1"&gt;// 120 Hz internal physics update&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If a frame takes longer than usual (for example, during a window resize or shader compilation), the accumulator advances in discrete 120 Hz sub-steps up to a hard cap, preventing explosive time-step jumps.&lt;/p&gt;

&lt;h3&gt;
  
  
  The equations of motion
&lt;/h3&gt;

&lt;p&gt;For each active particle at time &lt;code&gt;t&lt;/code&gt;, the simulator computes acceleration by summing directional gravity &lt;code&gt;g&lt;/code&gt;, external atmospheric forces, and fluid turbulence:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;F_total = g + F_turbulence + F_external
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The updated velocity &lt;code&gt;v(t + dt)&lt;/code&gt; applies acceleration and accounts for atmospheric drag:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;v(t + dt) = (v(t) + F_total * dt) * (1.0 - drag * dt)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Position &lt;code&gt;p(t + dt)&lt;/code&gt; then advances along the newly computed velocity vector:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;p(t + dt) = p(t) + v(t + dt) * dt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Linear drag acts as a damping factor: without it, particles in an active turbulence field would continuously gain kinetic energy until flying off to infinity. Setting drag between &lt;code&gt;0.05&lt;/code&gt; and &lt;code&gt;0.2&lt;/code&gt; creates a natural terminal velocity reminiscent of smoke particles or underwater sediment.&lt;/p&gt;

&lt;h2&gt;
  
  
  3D turbulence and procedural vector force fields
&lt;/h2&gt;

&lt;p&gt;Static directional gravity produces predictable fountain effects. To create organic, swirling motion where particles dance like embers or schooling fish, simulations apply procedural 3D noise vector fields.&lt;/p&gt;

&lt;p&gt;Rather than sampling expensive perlin noise textures across memory, real-time particle kernels compute value noise and pseudo-curl fields analytically:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="k"&gt;inline&lt;/span&gt; &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="nc"&gt;Noise3D&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;z&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;sin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;12.9898f&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;78.233f&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;z&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;37.719f&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;43758.5453f&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;floor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;2.0f&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mf"&gt;1.0f&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the &lt;code&gt;Particle System&lt;/code&gt; node, turbulence is evaluated in three spatial dimensions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight glsl"&gt;&lt;code&gt;&lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;nx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Noise3D&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;turbScale&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;turbScale&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;z&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;turbScale&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;ny&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Noise3D&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;turbScale&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mf"&gt;19.1f&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;turbScale&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;z&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;turbScale&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;nz&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Noise3D&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;turbScale&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;turbScale&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mf"&gt;31.7f&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;z&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;turbScale&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nc"&gt;F_turbulence&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Vec3&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ny&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;nz&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;turbulenceAmount&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When &lt;code&gt;turbulence&lt;/code&gt; is modulated by an audio feature (such as spectral flux or mid-frequency energy), complex vortex structures suddenly twist and expand whenever an instrument enters the mix, returning to laminar flow during quiet breakdowns.&lt;/p&gt;

&lt;h2&gt;
  
  
  Isolating audio transients for explosive particle bursts
&lt;/h2&gt;

&lt;p&gt;To create tight rhythmic synchronisation, incoming audio must pass through envelope extraction before reaching the particle emitter.&lt;/p&gt;

&lt;p&gt;In a modular graph, the &lt;code&gt;Audio In&lt;/code&gt; node captures multi-channel audio from your interface, system sound, or DAW routing. This feeds directly into an &lt;code&gt;Audio Analyze&lt;/code&gt; node, which divides the audio spectrum into frequency bands and tracks both peak amplitudes and transient envelopes:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Sub-bass band (20 Hz to 120 Hz)&lt;/strong&gt;: Isolates kick drums and bass stabs. Connecting this output to the particle emitter's &lt;code&gt;rate / sec&lt;/code&gt; parameter creates explosive bursts on downbeats.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Spectral flux&lt;/strong&gt;: Measures the rate of change across frequency bins. A sudden brass chord or snare strike produces a high spectral flux value, ideal for driving &lt;code&gt;turbulence&lt;/code&gt; or &lt;code&gt;spread&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;High-frequency envelope (6 kHz to 16 kHz)&lt;/strong&gt;: Tracks hi-hats, shakers, and cymbal sizzle. Modulating particle &lt;code&gt;start size&lt;/code&gt; or &lt;code&gt;speed random&lt;/code&gt; with high frequencies adds crisp kinetic shimmer to rapid rhythmic passages.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Because modulation values update at UI and block intervals without latency, particle emission synchronises tightly with what the audience hears.&lt;/p&gt;

&lt;h2&gt;
  
  
  Point trails, ribbon geometry, and GPU rendering
&lt;/h2&gt;

&lt;p&gt;Individual floating points can look sparse on large display projections. To give particles visual weight and continuity, Infinite pairs the &lt;code&gt;Particle System&lt;/code&gt; with downstream geometry generators and compositing nodes.&lt;/p&gt;

&lt;h3&gt;
  
  
  Turning points into continuous ribbons with &lt;code&gt;Point Trails&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;Point Trails&lt;/code&gt; node samples point positions across successive frames and extrudes them into continuous triangle strips. As particles whip through turbulent vortices, their trajectories form luminous ribbons through space.&lt;/p&gt;

&lt;p&gt;Key controls in &lt;code&gt;Point Trails&lt;/code&gt; include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;trail length&lt;/code&gt;: Determines the historical sample depth (from 4 to 64 steps). Shorter trails produce comet tails; longer trails create intricate calligraphic ribbons.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ribbon width&lt;/code&gt;: Defines the cross-sectional geometry size in world space.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;fade alpha&lt;/code&gt;: Tapers opacity exponentially towards the tail so older segments dissolve smoothly into the background.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Point sprite rendering in &lt;code&gt;Render 3D&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Both raw particles and ribbon meshes connect directly into the &lt;a href="https://infinitedevices.org/nodes/render-3d.html" rel="noopener noreferrer"&gt;&lt;code&gt;Render 3D&lt;/code&gt;&lt;/a&gt; node. For dense point clouds containing tens of thousands of elements, &lt;code&gt;Render 3D&lt;/code&gt; uses hardware-accelerated point sprites. Rather than drawing individual quad polygons, a single vertex shader call computes screen-space point sizes while fragment shaders evaluate circular alpha falloffs and depth fading.&lt;/p&gt;

&lt;p&gt;Adding a &lt;code&gt;Bloom&lt;/code&gt; node downstream extracts specular highlights from high-density particle clusters, wrapping them in a natural optical glow. A subtle &lt;code&gt;Color Adjustments&lt;/code&gt; pass allows fine-tuning contrast and grading the colour palette to match the mood of the performance.&lt;/p&gt;

&lt;p&gt;You can also explore how audio-reactive shaders compare to geometric pipelines in our guide to &lt;a href="https://infinitedevices.org/blog/audio-reactive-glsl-shaders.html" rel="noopener noreferrer"&gt;audio-reactive GLSL shaders&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Complete example patch
&lt;/h2&gt;

&lt;p&gt;Here is a complete, reproducible Infinite patch demonstrating an audio-reactive 3D particle system. It sets up an audio input, transient analysis, a high-capacity particle generator, point trails, a 3D camera renderer, optical bloom, and screen output.&lt;/p&gt;

&lt;p&gt;You can paste this plain text directly into an &lt;code&gt;.inf&lt;/code&gt; file or inspect it to understand the node connections:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;infinite-patch 1
rev 2
# Audio-Reactive 3D Particle System: transient bursts, curl turbulence, and bloom

node 1 Audio Audio In
  id audio_in
  pos 120 280
end

node 2 Audio Audio Analyze
  id analyze
  pos 380 280
end

node 3 Modulator LFO
  id lfo_sway
  pos 380 460
  param shape 0
  param frequency 0.15
end

node 4 3D Particle System
  id particles
  pos 700 280
  param max_particles 30000
  param rate 180
  param shape 1
  param radius 0.25
  param lifetime 3.5
  param speed 1.8
  param spread 0.45
  param dir_y 1.0
  param gravity_y -1.2
  param drag 0.12
  param turbulence 2.2
  param turb_scale 1.4
  param start_size 0.05
  param end_size 0.01
end

node 5 3D Point Trails
  id trails
  pos 1020 280
  param length 18
  param width 0.03
  param fade 0.85
end

node 6 3D Render 3D
  id renderer
  pos 1320 280
  param fov 45.0
  param cam_dist 4.2
  param shading 1
end

node 7 Image Bloom
  id bloom_fx
  pos 1600 280
  param threshold 0.60
  param radius 2.0
  param intensity 1.4
end

node 8 Image Color Adjustments
  id color_grade
  pos 1860 280
  param contrast 1.15
  param saturation 1.25
end

node 9 Utility Output
  id out_screen
  pos 2120 280
end

# Wiring
cable analyze 0 audio_in 0
cable particles 1 analyze 1        # Kick transient envelope -&amp;gt; Particle Emit Rate
cable particles 11 analyze 2       # Spectral flux -&amp;gt; Turbulence intensity
cable particles 9 lfo_sway 0       # Slow LFO -&amp;gt; Gravity Y drift
geo trails 0 particles
geo renderer 0 trails
cable bloom_fx 0 renderer 0
cable color_grade 0 bloom_fx 0
cable out_screen 0 color_grade 0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When live audio plays through &lt;code&gt;Audio In&lt;/code&gt;, kick transients trigger dense bursts of new points while spectral changes continuously alter the curl turbulence, causing the trails to swirl in synchrony with the music.&lt;/p&gt;

&lt;h2&gt;
  
  
  Performance and buffer limits
&lt;/h2&gt;

&lt;p&gt;Running tens of thousands of particles in real time alongside audio DSP requires keeping CPU and GPU overhead predictable:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Particle capacity&lt;/strong&gt;: On modern hardware, &lt;code&gt;Particle System&lt;/code&gt; comfortably simulates 20,000 to 50,000 particles at 120 frames per second. If your project targets portable laptops or high-resolution multi-projector setups, keeping &lt;code&gt;max particles&lt;/code&gt; between 15,000 and 25,000 ensures plenty of GPU headroom for post-processing shaders.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lifetimes and garbage collection&lt;/strong&gt;: Shorter particle lifetimes (between 2.0 and 4.0 seconds) cycle dead particles out of the buffer quickly, preventing memory bloat during prolonged high-tempo sections.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Trails depth&lt;/strong&gt;: &lt;code&gt;Point Trails&lt;/code&gt; creates geometric triangle meshes for each particle. If particle counts exceed 30,000, consider reducing &lt;code&gt;length&lt;/code&gt; to 8 or 12 points to minimise vertex memory bandwidth.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For ready-to-run templates, generative synths, and community visual rigs, visit the &lt;a href="https://infinitedevices.org/library.html" rel="noopener noreferrer"&gt;Infinite library&lt;/a&gt;. You can download Infinite for macOS, Windows, and Linux from the &lt;a href="https://infinitedevices.org/index.html#download" rel="noopener noreferrer"&gt;download page&lt;/a&gt; and begin patching generative audiovisual instruments immediately.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://infinitedevices.org/blog/audio-reactive-particle-systems-in-real-time.html" rel="noopener noreferrer"&gt;https://infinitedevices.org/blog/audio-reactive-particle-systems-in-real-time.html&lt;/a&gt;. Infinite is a free, open-source DAW for visuals, music and code: &lt;a href="https://infinitedevices.org" rel="noopener noreferrer"&gt;infinitedevices.org&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>particles</category>
      <category>creativecoding</category>
      <category>audioreactive</category>
      <category>visuals</category>
    </item>
    <item>
      <title>Wave terrain synthesis: audio from 3D surfaces</title>
      <dc:creator>naman</dc:creator>
      <pubDate>Wed, 11 Nov 2026 13:14:52 +0000</pubDate>
      <link>https://dev.to/n1m21n/wave-terrain-synthesis-audio-from-3d-surfaces-5b90</link>
      <guid>https://dev.to/n1m21n/wave-terrain-synthesis-audio-from-3d-surfaces-5b90</guid>
      <description>&lt;p&gt;Wave terrain synthesis is one of the most expressive, mathematically elegant methods for generating sound from visual geometry. Instead of reading through one-dimensional wavetables or computing traditional trigonometric oscillator formulas, a wave terrain synthesiser treats sound generation as a particle travelling across a three-dimensional topographic landscape.&lt;/p&gt;

&lt;p&gt;As an orbital trajectory scans across the contours, ridges, and valleys of this surface at audio rates, the instantaneous height of the terrain produces an acoustic waveform. When the landscape shifts or the trajectory rotates, the harmonic spectrum morphs continuously, producing organic timbres that range from acoustic woodwinds to evolving crystalline drones.&lt;/p&gt;

&lt;p&gt;Although conceptualised decades ago by researchers including Mitsuhashi and Curtis Roads, real-time wave terrain synthesis remained rare in traditional digital audio workstations. The technique requires simultaneous high-resolution two-dimensional image processing and sample-accurate numerical audio digital signal processing. In &lt;a href="https://infinitedevices.org/" rel="noopener noreferrer"&gt;Infinite&lt;/a&gt;, audio synthesis and computer graphics share a single execution graph, making native wave terrain synthesis available directly on the modular canvas.&lt;/p&gt;

&lt;p&gt;Here is an analysis of how wave terrain synthesis operates, the mathematics of two-dimensional orbital scanning, how discrete Fourier transform mip pyramids eliminate Nyquist aliasing, and how to patch an audio-visual wave terrain instrument using native nodes.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F3rlx2zcaof8z647q26q7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F3rlx2zcaof8z647q26q7.png" alt="Technical architecture diagram of real-time wave terrain synthesis showing 3D surface scanning, orbital trajectories, and FFT anti-aliasing"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What is wave terrain synthesis
&lt;/h2&gt;

&lt;p&gt;Traditional wavetable synthesis reads through a sequence of one-dimensional periodic arrays: $s(t) = W(\phi(t))$, where $\phi(t)$ represents the normalised phase accumulator advancing from zero to one. While wavetable position modulation allows timbral movement, the sound remains constrained to a linear path through pre-recorded cycles.&lt;/p&gt;

&lt;p&gt;Wave terrain synthesis expands this concept into two spatial dimensions. A two-dimensional terrain function $z = T(u, v)$ defines a continuous surface over the normalised coordinate plane $(u, v) \in [0, 1] \times [0, 1]$. An orbital path generator computes a closed two-dimensional trajectory $(u(t), v(t))$ that repeats at the fundamental frequency $f_0$ of the played musical note:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;s(t) = T(u(t), v(t))
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The resulting audio waveform $s(t)$ depends on two independent factors:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;The topography of the terrain&lt;/strong&gt;: The static shape or dynamic motion of the surface $T(u, v)$, including its gradients, crests, and saddle points.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The geometry of the orbit&lt;/strong&gt;: The shape, scale, centre offset, and orientation of the path $(u(t), v(t))$ traced across the surface.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This decoupling gives sound designers two distinct modulation axes. Modulating the orbit changes the harmonic balance and formant character of each note. Modulating the underlying terrain changes the underlying timbre and physical presence of the entire patch.&lt;/p&gt;

&lt;h2&gt;
  
  
  The mathematics of wave terrains: functions and image rasters
&lt;/h2&gt;

&lt;p&gt;In mathematical theory, a wave terrain can be defined by explicit continuous equations, such as polynomials, sums of sine products, or saddle functions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;T(u, v) = cos(2π u) · sin(2π v) + 0.5 · sin(4π (u + v))
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In modular creative coding environments like Infinite, terrains can also be derived directly from dynamic image textures. Video feeds, procedural noise, reaction-diffusion simulations, and generative pixel shaders can all serve as live wave terrains.&lt;/p&gt;

&lt;p&gt;When an image texture supplies the terrain, the continuous coordinate $(u, v)$ must be sampled from a discrete raster of pixels with width $W$ and height $H$. To prevent steppy, noisy distortion when the orbit moves between discrete pixel centres, the synthesiser applies bilinear interpolation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;fx = u · W - 0.5
fy = v · H - 0.5

x0 = floor(fx),  x1 = x0 + 1
y0 = floor(fy),  y1 = y0 + 1

tx = fx - x0
ty = fy - y0

T(u, v) = (1 - tx)(1 - ty)c00 + tx(1 - ty)c10 + (1 - tx)ty c01 + tx ty c11
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, $c_{00}, c_{10}, c_{01}, c_{11}$ represent the scalar values extracted from the four nearest neighbouring pixels. In Infinite's &lt;a href="https://infinitedevices.org/nodes/wave-terrain.html" rel="noopener noreferrer"&gt;&lt;code&gt;Wave Terrain node&lt;/code&gt;&lt;/a&gt;, the &lt;code&gt;wtChan&lt;/code&gt; parameter determines how multi-channel colour data maps to surface elevation:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Luminance&lt;/strong&gt;: Computes perceived brightness using standard colourimetric weighting: $0.299 R + 0.587 G + 0.114 B$. Smooth gradients produce warm, rounded harmonic spectra.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Red, green, blue, and alpha&lt;/strong&gt;: Solos a single colour channel. Useful when complex multi-pass shaders encode distinct mathematical data into separate colour channels.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Edge magnitude&lt;/strong&gt;: Computes the absolute gradient from median luminance: $|Luminance - 0.5| \times 2.0$. This mode isolates high-contrast boundaries in textures, generating bright, metallic overtones with punchy attacks.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Because texture coordinates wrap periodically, orbital paths that exceed the unit boundary seamlessly loop around the terrain edges without clicks or discontinuity.&lt;/p&gt;

&lt;h2&gt;
  
  
  Kinematic scanning: orbital trajectories in two dimensions
&lt;/h2&gt;

&lt;p&gt;The path $(u(t), v(t))$ determines which contours of the terrain are read during each audio cycle. For a note with fundamental frequency $f_0$, the normalised phase $t$ advances across $[0, 1)$ at rate $f_0 / f_s$, where $f_s$ is the audio sampling rate (typically 48,000 Hz).&lt;/p&gt;

&lt;p&gt;Infinite provides five distinct orbital geometries, each offering unique harmonic characteristics:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Elliptical orbits (&lt;code&gt;kOrbitCircle&lt;/code&gt;)
&lt;/h3&gt;

&lt;p&gt;The simplest trajectory is an ellipse centred at $(c_x, c_y)$ with radii $(r_x, r_y)$ and phase offset $\phi$:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;u(t) = cx + rx · cos(2π t)
v(t) = cy + ry · sin(2π t + 2π φ)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When $r_x = r_y$ and $\phi = 0$, the orbit traces a circle. Increasing or decreasing the radii scales the amplitude of modulation across the terrain, acting similarly to the modulation index in frequency modulation synthesis. Small radii inspect local, gentle slopes, yielding warm sine-like tones. Large radii traverse steep peaks and troughs, producing complex spectra rich in high-order harmonics.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Lissajous figures (&lt;code&gt;kOrbitLissajous&lt;/code&gt;)
&lt;/h3&gt;

&lt;p&gt;Lissajous trajectories introduce harmonic ratio multipliers $\text{ratioA}$ and $\text{ratioB}$ on the horizontal and vertical axes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;u(t) = cx + rx · sin(2π t · ratioA + 2π φ)
v(t) = cy + ry · sin(2π t · ratioB)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When $\text{ratioA}$ and $\text{ratioB}$ form integer proportions such as 3:2, 4:3, or 5:4, the orbit loops through intricate figure-eight and braided geometries. Because the path revisits different parts of the terrain at sub-harmonic intervals, Lissajous orbits generate vocal formants and bell-like inharmonic overtones reminiscent of complex wavefolding.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Lemniscate of Bernoulli (&lt;code&gt;kOrbitLemniscate&lt;/code&gt;)
&lt;/h3&gt;

&lt;p&gt;The lemniscate traces a continuous infinity loop across the terrain:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;denom = 1 + sin²(2π t)
u(t) = cx + rx · cos(2π t) / denom
v(t) = cy + ry · sin(2π t) · cos(2π t) / denom
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The lemniscate features an inflection point at the centre of the loop where velocity reaches its maximum. When scanned across a non-linear terrain, this velocity profile creates rich acoustic asymmetry, producing hollow, woody resonances similar to acoustic clarinets and bowed strings.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Archimedean spirals (&lt;code&gt;kOrbitSpiral&lt;/code&gt;)
&lt;/h3&gt;

&lt;p&gt;The spiral trajectory expands outwards over multiple rotations before cycling:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;rFactor = 0.2 + 0.8 · t
u(t) = cx + rx · rFactor · cos(2π t · turns)
v(t) = cy + ry · rFactor · sin(2π t · turns)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Spirals cross concentric contours, generating sweeping spectral motion even on static terrains.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Scanline rasterisation (&lt;code&gt;kOrbitScanline&lt;/code&gt;)
&lt;/h3&gt;

&lt;p&gt;The scanline orbit sweeps linearly across the horizontal axis while stepping the vertical coordinate across discrete frames. This produces biting, digital wavetable-style timbres ideal for aggressive basslines.&lt;/p&gt;

&lt;h2&gt;
  
  
  Eliminating aliasing: discrete Fourier transform mip levels
&lt;/h2&gt;

&lt;p&gt;A major challenge in wave terrain synthesis is digital aliasing. When an orbit traces across sharp cliffs, high-frequency noise, or steep gradients on a terrain, the resulting waveform $s(t)$ contains harmonics that can extend far beyond the Nyquist limit ($f_s / 2 = 24,000\text{ Hz}$). Without band-limiting, these harmonics fold back across the Nyquist threshold, creating unmusical, harsh intermodulation distortion.&lt;/p&gt;

&lt;p&gt;To solve this, Infinite's real-time digital signal processing engine uses a Cooley-Tukey Radix-2 fast Fourier transform (FFT) pipeline with an exact 10-level mip pyramid.&lt;/p&gt;

&lt;h3&gt;
  
  
  The 1024-point Radix-2 FFT pipeline
&lt;/h3&gt;

&lt;p&gt;During preparation, the synthesiser pre-samples the selected orbit across 8 morph frames into 1024-sample wavetable buffers. Each buffer undergoes a forward discrete Fourier transform:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Forward Cooley-Tukey Radix-2 FFT (N = 1024)&lt;/span&gt;
&lt;span class="nc"&gt;Radix2FFT&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nc"&gt;Instance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Forward&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;realBuffer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;imagBuffer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once in the frequency domain, the spectrum consists of 512 discrete harmonic bins. The engine computes 10 band-limited mip levels, where each successive level halves the maximum allowable harmonic index:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Mip 0&lt;/strong&gt;: Contains all 512 harmonics. Used for low bass notes ($20\text{ Hz} - 90\text{ Hz}$) where the 512th harmonic remains below 24,000 Hz.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mip 1&lt;/strong&gt;: Band-limited to 256 harmonics ($90\text{ Hz} - 180\text{ Hz}$).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mip 2&lt;/strong&gt;: Band-limited to 128 harmonics ($180\text{ Hz} - 370\text{ Hz}$).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mip 3&lt;/strong&gt;: Band-limited to 64 harmonics ($370\text{ Hz} - 750\text{ Hz}$).&lt;/li&gt;
&lt;li&gt;...&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mip 9&lt;/strong&gt;: Band-limited to a single fundamental harmonic (pure sine wave) for high soprano registers above 10,000 Hz.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For each mip level, harmonics above the cutoff threshold are zeroed out, and an inverse FFT reconstructs a clean, alias-free time-domain cycle:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="nc"&gt;Radix2FFT&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nc"&gt;Instance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Inverse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;realBuffer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;imagBuffer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;During real-time voice rendering, the audio engine calculates the exact continuous pitch of the note, determines the fractional mip level, and blends between the two adjacent mip tables using cubic Hermite interpolation. This guarantees more than 80 dB of aliasing suppression across all 8 octaves of the keyboard.&lt;/p&gt;

&lt;h2&gt;
  
  
  Polyphony, unison voicing, and filtering
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://infinitedevices.org/nodes/wave-terrain.html" rel="noopener noreferrer"&gt;&lt;code&gt;Wave Terrain node&lt;/code&gt;&lt;/a&gt; in Infinite includes full performance architecture built into the DSP engine:&lt;/p&gt;

&lt;h3&gt;
  
  
  8-voice polyphony
&lt;/h3&gt;

&lt;p&gt;The node maintains eight independent polyphonic voices. Each voice tracks its own MIDI note number, note frequency, phase accumulator, and four-stage ADSR envelope (attack, decay, sustain, release). When a chord is played, each voice samples the terrain at its own independent playback speed, preserving harmonic clarity across complex intervals.&lt;/p&gt;

&lt;h3&gt;
  
  
  Unison detuning and stereo spreading
&lt;/h3&gt;

&lt;p&gt;For thick lead sounds and wide ambient textures, the engine supports up to 8 unison sub-voices per note:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Detune&lt;/strong&gt;: Spreads unison voice frequencies apart by up to 100 cents using calibrated logarithmic detune curves.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stereo width&lt;/strong&gt;: Pans unison voice pairs symmetrically across the stereo field from -1.0 (hard left) to +1.0 (hard right).&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Multi-mode resonant filter
&lt;/h3&gt;

&lt;p&gt;After terrain evaluation and unison summing, the signal passes into an internal state-variable filter. The filter offers 12 dB, 24 dB, and 36 dB slopes in lowpass, highpass, bandpass, and notch modes, controllable via &lt;code&gt;cutoff&lt;/code&gt;, &lt;code&gt;resonance&lt;/code&gt;, and &lt;code&gt;drive&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Patching wave terrain synthesis in Infinite
&lt;/h2&gt;

&lt;p&gt;Connecting a wave terrain synthesiser on Infinite's canvas takes less than a minute. Because image cables, note cables, and audio cables all coexist on the same workspace, visual and acoustic nodes link directly together.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[Reaction-Diffusion] (texture) ──&amp;gt; (texture) [Wave Terrain] ──&amp;gt; [Audio Out]
                                          ▲
[Keyboard / Sequencer] (notes) ───────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 1: Add the terrain source
&lt;/h3&gt;

&lt;p&gt;Add a generative visual node to supply the landscape:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Press &lt;code&gt;Shift+A&lt;/code&gt; and select &lt;strong&gt;Visuals &amp;gt; Reaction-Diffusion&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Set the algorithm parameters to generate organic Turing patterns: &lt;code&gt;feed = 0.054&lt;/code&gt;, &lt;code&gt;kill = 0.062&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Adjust the simulation speed to 0.25 so the visual patterns slowly pulse and drift over time.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Step 2: Add the Wave Terrain synthesiser
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Press &lt;code&gt;Shift+A&lt;/code&gt; and select &lt;strong&gt;Synths &amp;gt; Wave Terrain&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Connect the &lt;code&gt;out&lt;/code&gt; (picture) pin of &lt;strong&gt;Reaction-Diffusion&lt;/strong&gt; to the &lt;code&gt;texture&lt;/code&gt; input of &lt;strong&gt;Wave Terrain&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Set &lt;code&gt;wtOrbit&lt;/code&gt; to &lt;strong&gt;Lemniscate&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Set &lt;code&gt;wtChan&lt;/code&gt; to &lt;strong&gt;Luminance&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Set &lt;code&gt;unison&lt;/code&gt; to &lt;strong&gt;3&lt;/strong&gt; and &lt;code&gt;detune&lt;/code&gt; to &lt;strong&gt;14 cents&lt;/strong&gt; for subtle chorus movement.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Step 3: Trigger notes and monitor output
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Press &lt;code&gt;Shift+A&lt;/code&gt; and select &lt;strong&gt;Notes &amp;gt; Keyboard&lt;/strong&gt; (or &lt;strong&gt;Random Note Generator&lt;/strong&gt; for automated generative playback).&lt;/li&gt;
&lt;li&gt;Connect the &lt;code&gt;note&lt;/code&gt; output to the &lt;code&gt;note&lt;/code&gt; input of &lt;strong&gt;Wave Terrain&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Connect the &lt;code&gt;audio&lt;/code&gt; output of &lt;strong&gt;Wave Terrain&lt;/strong&gt; to an &lt;a href="https://infinitedevices.org/nodes/audio-out.html" rel="noopener noreferrer"&gt;&lt;code&gt;Audio Out&lt;/code&gt;&lt;/a&gt; node.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;When you play notes, you will hear a rich, resonant tone. As the reaction-diffusion pattern morphs on the canvas, the acoustic timbre shifts in tandem.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example patch file
&lt;/h3&gt;

&lt;p&gt;Infinite saves patches in human-readable plain text &lt;code&gt;.inf&lt;/code&gt; files. Here is the starting patch:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;infinite-patch 1
rev 2
node 1 Visuals Reaction-Diffusion
  id rdiff
  pos 120 240
  param feed 0.054
  param kill 0.062
end
node 2 Notes Keyboard
  id keys
  pos 120 440
end
node 3 Synths Wave Terrain
  id wt
  pos 420 300
  param wtOrbit 2
  param wtChan 0
  param radiusX 0.45
  param radiusY 0.45
  param unison 3
  param detune 14
  param cutoff 8500
end
node 4 Audio Audio Out
  id out
  pos 740 300
end
cable rdiff texture -&amp;gt; wt texture
cable keys notes -&amp;gt; wt note
cable wt audio -&amp;gt; out in
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Sound design recipes: evolving drones, aggressive bass, and ambient pads
&lt;/h2&gt;

&lt;p&gt;Here are three practical production recipes using the Wave Terrain engine:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Organic morphing drone
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Terrain source&lt;/strong&gt;: &lt;a href="https://infinitedevices.org/nodes/noise.html" rel="noopener noreferrer"&gt;&lt;code&gt;Noise node&lt;/code&gt;&lt;/a&gt; with simplex noise and slow octaves evolution.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Orbit&lt;/strong&gt;: &lt;code&gt;kOrbitLemniscate&lt;/code&gt; with &lt;code&gt;radiusX = 0.65&lt;/code&gt;, &lt;code&gt;radiusY = 0.40&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Modulation&lt;/strong&gt;: Connect a slow sine &lt;code&gt;LFO&lt;/code&gt; (0.08 Hz) to the &lt;code&gt;rotation&lt;/code&gt; parameter of &lt;strong&gt;Wave Terrain&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Filter&lt;/strong&gt;: 24 dB lowpass with &lt;code&gt;cutoff = 3200 Hz&lt;/code&gt; and subtle resonance.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Character&lt;/strong&gt;: As the rotation rotates the infinity loop across the noise field, the harmonic overtone balance shifts without sudden timbre jumps, creating an evolving drone suitable for film scoring.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. Aggressive industrial Reese bass
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Terrain source&lt;/strong&gt;: High-contrast geometric shapes from a &lt;code&gt;Shape&lt;/code&gt; or &lt;code&gt;Glitch&lt;/code&gt; node.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Orbit&lt;/strong&gt;: &lt;code&gt;kOrbitLissajous&lt;/code&gt; with &lt;code&gt;ratioA = 3.0&lt;/code&gt;, &lt;code&gt;ratioB = 2.0&lt;/code&gt;, and &lt;code&gt;wtChan = Edge Magnitude&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Unison&lt;/strong&gt;: 5 voices, &lt;code&gt;detune = 28 cents&lt;/code&gt;, &lt;code&gt;stereoWidth = 0.85&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Filter&lt;/strong&gt;: 24 dB lowpass with moderate &lt;code&gt;drive&lt;/code&gt; to saturate the summed unison output.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Character&lt;/strong&gt;: The edge detection mode reads hard transitions as intense harmonic spikes. Coupled with the 3:2 Lissajous trajectory and unison detuning, this produces a ferocious, roaring bass sound with distinctive stereophonic movement.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. Shimmering ambient glass pad
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Terrain source&lt;/strong&gt;: Live video feed from a webcam or liquid video loop via &lt;code&gt;Video&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Orbit&lt;/strong&gt;: &lt;code&gt;kOrbitSpiral&lt;/code&gt; with &lt;code&gt;radiusX = 0.85&lt;/code&gt;, &lt;code&gt;radiusY = 0.85&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Envelope&lt;/strong&gt;: &lt;code&gt;attack = 1200 ms&lt;/code&gt;, &lt;code&gt;release = 2400 ms&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Modulation&lt;/strong&gt;: Route the high-frequency band from an &lt;a href="https://infinitedevices.org/nodes/audio-analyze.html" rel="noopener noreferrer"&gt;&lt;code&gt;Audio Analyze node&lt;/code&gt;&lt;/a&gt; back into &lt;code&gt;radiusX&lt;/code&gt;, creating an acoustic feedback loop where brightness opens the spatial scan.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Character&lt;/strong&gt;: Delicate, shimmering, crystalline pads that breathe dynamically in response to room sound and video luminance.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Summary and exploration
&lt;/h2&gt;

&lt;p&gt;Wave terrain synthesis transforms the relationship between visual graphics and electronic sound. By viewing sound synthesis as spatial kinematics across topographic surfaces, artists can design instruments that are visually expressive and sonically complex.&lt;/p&gt;

&lt;p&gt;With built-in 1024-point discrete Fourier transform anti-aliasing, eight-voice polyphony, and unison spreading, Infinite makes wave terrain synthesis reliable for live performance and studio composition.&lt;/p&gt;

&lt;p&gt;Explore ready-to-run wave terrain patches in the &lt;a href="https://infinitedevices.org/library.html" rel="noopener noreferrer"&gt;Infinite Library&lt;/a&gt;, inspect the full control specifications in the &lt;a href="https://infinitedevices.org/nodes/wave-terrain.html" rel="noopener noreferrer"&gt;Wave Terrain node documentation&lt;/a&gt;, or download &lt;a href="https://infinitedevices.org/" rel="noopener noreferrer"&gt;Infinite&lt;/a&gt; to start sculpting sound from two-dimensional landscapes.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://infinitedevices.org/blog/wave-terrain-synthesis-in-real-time.html" rel="noopener noreferrer"&gt;https://infinitedevices.org/blog/wave-terrain-synthesis-in-real-time.html&lt;/a&gt;. Infinite is a free, open-source DAW for visuals, music and code: &lt;a href="https://infinitedevices.org" rel="noopener noreferrer"&gt;infinitedevices.org&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>waveterrain</category>
      <category>synthesis</category>
      <category>sounddesign</category>
      <category>creativecoding</category>
    </item>
    <item>
      <title>Physical modelling string synthesis in real time</title>
      <dc:creator>naman</dc:creator>
      <pubDate>Wed, 11 Nov 2026 13:14:43 +0000</pubDate>
      <link>https://dev.to/n1m21n/physical-modelling-string-synthesis-in-real-time-1m1n</link>
      <guid>https://dev.to/n1m21n/physical-modelling-string-synthesis-in-real-time-1m1n</guid>
      <description>&lt;p&gt;Physical modelling synthesis generates sound by simulating the actual physical mechanics of vibrating matter rather than playing static wavetables or filtering raw geometric waveforms. While traditional subtractive synthesis uses mathematical approximations like saw and square waves, and sample libraries replay pre-recorded audio recordings of instruments, physical modelling calculates the physical wave propagation, boundary reflections, internal material damping, and structural resonance of acoustic objects in code.&lt;/p&gt;

&lt;p&gt;When you pluck, strike, or bow an acoustic string, its sonic timbre evolves dynamically across every note. The attack transient reflects the pick position along the string length, the mechanical stiffness produces subtle inharmonic frequency shifts across higher partials, and the wooden instrument body colours the acoustic radiation through dozens of coupled resonant modes.&lt;/p&gt;

&lt;p&gt;In real-time audiovisual environments like &lt;a href="https://infinitedevices.org/" rel="noopener noreferrer"&gt;Infinite&lt;/a&gt;, physical modelling provides an expressive foundation for both sound design and generative visuals. Because the underlying physical variables (such as string velocity, bridge displacement, and energy dissipation) are evaluated directly on the audio thread, they can be routed seamlessly into 3D geometry deformation and real-time shaders.&lt;/p&gt;

&lt;p&gt;Here is an in-depth examination of how digital waveguide physical modelling operates, how fractional allpass filters maintain pitch accuracy, how dispersion creates natural inharmonicity, how exciter mechanics simulate plucking, striking, and bowing, and how to patch a complete physical modelling instrument using native nodes.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fhp2024qpjhxkwpnuxkop.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fhp2024qpjhxkwpnuxkop.png" alt="Technical architecture diagram of real-time physical modelling string synthesis showing digital waveguide delay loops, dispersion allpass filters, exciter models, and modal acoustic bodies"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What physical modelling solves in computer music
&lt;/h2&gt;

&lt;p&gt;The central challenge with electronic instruments is acoustic realism and continuous expressiveness. A sampled acoustic guitar or cello can capture the timbre of an isolated note, but it struggles with real-time articulation. When a performer alters bow pressure, slides between frets, or alternates between fingerpicking and a sharp plectrum, a sample library must crossfade between distinct recordings. This often creates phase cancellation, unnatural chorusing, or static, repetitive transients known as the machine-gun effect.&lt;/p&gt;

&lt;p&gt;Subtractive synthesis offers continuous modulation through filters and envelopes, but its harmonic structure remains synthetic. An oscillator running through a resonant lowpass filter lacks the complex modal distribution and material losses of real wood and vibrating steel.&lt;/p&gt;

&lt;p&gt;Physical modelling solves this by simulating the physical acoustic system from first principles. When you alter a parameter like string stiffness or bow velocity, you are not adjusting an artificial audio filter: you are modifying the physical differential equation governing wave motion. The resulting acoustic response reacts organically, producing natural transients, sympathetic resonance, and expressive feedback.&lt;/p&gt;

&lt;h2&gt;
  
  
  Digital waveguides: bidirectional delay lines and wave propagation
&lt;/h2&gt;

&lt;p&gt;The foundation of modern string modelling is the digital waveguide, formulated by Julius O. Smith (1992) as an extension of the pioneering Karplus-Strong plucked string algorithm (1983).&lt;/p&gt;

&lt;p&gt;The physical motion of an ideal vibrating string is governed by the one-dimensional acoustic wave equation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;d^2 y / dt^2 = c^2 * (d^2 y / dx^2)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Where &lt;code&gt;y&lt;/code&gt; represents transverse displacement, &lt;code&gt;t&lt;/code&gt; is time, &lt;code&gt;x&lt;/code&gt; is the spatial coordinate along the string, and &lt;code&gt;c&lt;/code&gt; is the wave propagation speed determined by string tension &lt;code&gt;T&lt;/code&gt; and linear mass density &lt;code&gt;mu&lt;/code&gt; (&lt;code&gt;c = sqrt(T / mu)&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;D'Alembert showed that any solution to this differential equation can be decomposed into two independent travelling waves moving in opposite directions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;y(x, t) = y_plus(t - x/c) + y_minus(t + x/c)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, &lt;code&gt;y_plus&lt;/code&gt; represents a wave travelling to the right (towards the bridge), and &lt;code&gt;y_minus&lt;/code&gt; represents a wave travelling to the left (towards the nut).&lt;/p&gt;

&lt;h3&gt;
  
  
  Discretisation into digital delay lines
&lt;/h3&gt;

&lt;p&gt;In a computer simulation, continuous spatial wave propagation is discretised into two tapped delay lines. The total round-trip propagation time corresponds to the period of the fundamental frequency &lt;code&gt;f_0&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Period T = 1.0 / f_0
Delay samples N = f_s / f_0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Where &lt;code&gt;f_s&lt;/code&gt; is the digital sample rate (such as 44,100 Hz or 48,000 Hz).&lt;/p&gt;

&lt;p&gt;At the string boundaries, the travelling waves undergo physical reflections:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;The nut (fret boundary)&lt;/strong&gt;: Assumed to be rigid. The string displacement must be zero at &lt;code&gt;x = 0&lt;/code&gt;, forcing an inverting reflection with reflection coefficient &lt;code&gt;R_0 = -1&lt;/code&gt;. The wave reflects with inverted phase.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The bridge&lt;/strong&gt;: The string terminates at a bridge that transfers energy to the resonant instrument body. The bridge reflection is modelled by an inverting reflection combined with a frequency-dependent loop filter &lt;code&gt;H_loop(z)&lt;/code&gt; that accounts for energy loss and phase delay.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;When a pulse is injected into the bidirectional delay loop, it travels back and forth between the nut and bridge. Each round trip corresponds to one cycle of the fundamental pitch, producing a rich harmonic spectrum.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tuning and fractional delay: solving the phase allpass filter
&lt;/h2&gt;

&lt;p&gt;In a naive digital delay line, the buffer length is constrained to integer sample counts &lt;code&gt;N = floor(f_s / f_0)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This creates a serious musical problem: pitch quantization. For high notes, the integer rounding error causes severe out-of-tune intonation. For instance, at a sample rate of 48 kHz:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A note at 1000 Hz requires &lt;code&gt;48000 / 1000 = 48.0&lt;/code&gt; samples.&lt;/li&gt;
&lt;li&gt;The next semitone up (1059.25 Hz) requires &lt;code&gt;48000 / 1059.25 = 45.315&lt;/code&gt; samples.&lt;/li&gt;
&lt;li&gt;Rounding to 45 samples produces 1066.67 Hz, an unacceptable tuning error of over 12 cents.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To achieve exact microtonal and chromatic intonation, the delay loop must support fractional sample delays.&lt;/p&gt;

&lt;h3&gt;
  
  
  The first-order allpass filter
&lt;/h3&gt;

&lt;p&gt;In the native &lt;a href="https://infinitedevices.org/nodes/string.html" rel="noopener noreferrer"&gt;&lt;code&gt;String&lt;/code&gt;&lt;/a&gt; node in Infinite, fractional delay is implemented using a first-order allpass filter:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;A(z) = (a + z^-1) / (1.0 + a * z^-1)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;An allpass filter has a flat magnitude frequency response of exactly 1.0 across all frequencies, but its phase response introduces a controllable group delay without causing any artificial attenuation or damping in the loop.&lt;/p&gt;

&lt;p&gt;The phase delay &lt;code&gt;D(w)&lt;/code&gt; of the allpass filter at angular frequency &lt;code&gt;w&lt;/code&gt; radians per sample is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;D(w) = - (atan2(-sin(w), a + cos(w)) - atan2(-a * sin(w), 1.0 + a * cos(w))) / w
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Because delay decreases monotonically as coefficient &lt;code&gt;a&lt;/code&gt; rises, the engine solves for the exact coefficient &lt;code&gt;a&lt;/code&gt; using a numerical bisection solver across 40 iterations on every parameter update chunk:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="nc"&gt;SolveAllpass&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;lo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mf"&gt;0.95&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;hi&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.95&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
   &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
   &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;mid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.5&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lo&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;hi&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;AllpassDelay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
         &lt;span class="n"&gt;lo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mid&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="k"&gt;else&lt;/span&gt;
         &lt;span class="n"&gt;hi&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mid&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
   &lt;span class="p"&gt;}&lt;/span&gt;
   &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mf"&gt;0.5&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lo&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;hi&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By subtracting the fractional delay of the allpass filter and loop filter from the total delay requirement, the fundamental pitch &lt;code&gt;f_0&lt;/code&gt; remains mathematically exact, regardless of how other controls like decay, tone, and stiffness are adjusted.&lt;/p&gt;

&lt;h2&gt;
  
  
  Dispersion and stiffness: inharmonicity across higher partials
&lt;/h2&gt;

&lt;p&gt;In a purely flexible, mathematical string, all harmonic partials are exact integer multiples of the fundamental frequency: &lt;code&gt;f_k = k * f_0&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Real physical strings (such as piano wire, bass guitar strings, or harp strings), however, possess inherent bending stiffness. A stiff wire resists bending, introducing an additional restoring force governed by the Euler-Bernoulli beam equation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;d^2 y / dt^2 = c^2 * (d^2 y / dx^2) - kappa^2 * (d^4 y / dx^4)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Where &lt;code&gt;kappa&lt;/code&gt; is the stiffness parameter.&lt;/p&gt;

&lt;p&gt;The consequence of this fourth-order derivative is dispersion: higher-frequency waves travel along the string faster than lower-frequency waves. As a result, the higher partials are displaced upwards in frequency, following the inharmonicity formula:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;f_k = k * f_0 * sqrt(1.0 + B * k^2)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Where &lt;code&gt;B&lt;/code&gt; is the inharmonicity coefficient.&lt;/p&gt;

&lt;h3&gt;
  
  
  Modelling dispersion with allpass cascades
&lt;/h3&gt;

&lt;p&gt;Without stiffness, a plucked digital string sounds sterile and electronic, resembling a simple comb-filtered pulse. When stiffness is introduced, the upper partials ring with the distinct metallic attack and organic complexity heard in real acoustic instruments.&lt;/p&gt;

&lt;p&gt;In Infinite's &lt;code&gt;String&lt;/code&gt; node, dispersion is implemented using a cascade of four first-order allpass filters placed directly in the feedback path of the bridge. Each allpass stage adds frequency-dependent phase delay, slightly advancing the arrival time of higher harmonics relative to the fundamental.&lt;/p&gt;

&lt;p&gt;Modulating the &lt;code&gt;stiffness&lt;/code&gt; parameter shifts the string character from a warm, flexible nylon classical guitar string to a taut, clanging steel piano wire or metallic bass string.&lt;/p&gt;

&lt;h2&gt;
  
  
  Exciter mechanics: pluck, hammer strike, and bow friction
&lt;/h2&gt;

&lt;p&gt;A physical string model requires an excitation source to inject kinetic energy into the delay lines. The nature of this excitation dictates whether the instrument sounds plucked, struck, or bowed.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;String&lt;/code&gt; node features three distinct physical exciter models:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Pluck excitation
&lt;/h3&gt;

&lt;p&gt;A plectrum or finger plucks a string by displacing it at a specific normalised position &lt;code&gt;x_rel&lt;/code&gt; (from 0.0 at the bridge to 1.0 at the nut). When released, the initial triangular displacement splits into two identical half-amplitude pulses propagating in opposite directions towards the nut and bridge.&lt;/p&gt;

&lt;p&gt;The point of excitation introduces comb filtering. Plucking near the bridge (&lt;code&gt;position = 0.1&lt;/code&gt;) suppresses low frequencies and emphasizes sharp, nasal upper harmonics. Plucking near the centre (&lt;code&gt;position = 0.5&lt;/code&gt;) eliminates even harmonics, producing a hollow, clarinet-like tone.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;hardness&lt;/code&gt; parameter controls the pulse duration. A hard pick generates an instantaneous sharp spike, exciting high-frequency energy up to the Nyquist frequency. A soft finger widens the pulse up to tenfold, naturally rounding and softening the transient attack.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Strike excitation
&lt;/h3&gt;

&lt;p&gt;A strike models a piano or dulcimer felt hammer hitting the string. Unlike an instantaneous pluck, a felt hammer has physical mass and compliant elasticity.&lt;/p&gt;

&lt;p&gt;The interaction is non-linear: a soft strike compresses the felt gently, resulting in a prolonged contact duration and a warm, mellow tone. A heavy strike compresses the felt rapidly into its dense wooden core, drastically shortening the contact duration and releasing a burst of bright, forceful upper partials.&lt;/p&gt;

&lt;p&gt;In code, the pulse length scales dynamically with incoming note velocity:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="n"&gt;pulseLen&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;round&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sampleRate&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.004&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mf"&gt;0.003&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;velocity&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Bow excitation (Smith's friction junction)
&lt;/h3&gt;

&lt;p&gt;Bowing a string is a continuous, self-oscillating non-linear process driven by friction between sticky rosin-coated horsehair and the string.&lt;/p&gt;

&lt;p&gt;The bow moves at a constant speed &lt;code&gt;v_bow&lt;/code&gt;. The interaction alternates rapidly between two phases:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Stick phase&lt;/strong&gt;: Static friction holds the string against the bow hair, dragging the string along with the bow until tension forces overcome friction.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Slip phase&lt;/strong&gt;: The string breaks free and snaps backwards towards its resting point under dynamic friction.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This stick-slip mechanism is modelled using a non-linear friction characteristic curve:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;F_friction(v_rel) = sign(v_rel) * (mu_dynamic + (mu_static - mu_dynamic) * exp(-c * |v_rel|)) * F_bow
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Where &lt;code&gt;v_rel = v_bow - v_string&lt;/code&gt; is the relative velocity between bow and string, and &lt;code&gt;F_bow&lt;/code&gt; is normal bow pressure.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;String&lt;/code&gt; node implements bow friction with oversampled integration (up to 8x internal oversampling for high notes) to eliminate digital limit cycles. Modulating the &lt;code&gt;pressure&lt;/code&gt; and &lt;code&gt;noise&lt;/code&gt; parameters allows you to recreate authentic string scrapes, raspy rosin friction, and the smooth transition into pure sustained Helmholtz bowing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Acoustic radiation: mode tables and modal bodies
&lt;/h2&gt;

&lt;p&gt;An isolated vibrating string has very little surface area. In an acoustic instrument, virtually all audible sound radiates from the resonant wooden soundboard and body cavity (the body of a guitar, violin, or cello).&lt;/p&gt;

&lt;p&gt;The instrument body acts as a complex acoustic filter with dozens of closely spaced resonant peaks. Rather than running a static graphic equaliser, Infinite couples the string output to a shared modal resonator bank (&lt;a href="https://infinitedevices.org/nodes/resonator-bank.html" rel="noopener noreferrer"&gt;&lt;code&gt;DenseBody&lt;/code&gt;&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;The body simulation evaluates ten parallel second-order modal bandpass resonators, each configured with an exact centre frequency, bandwidth, and amplitude mode table:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;y_body(t) = sum_{m=1}^{10} A_m * exp(-alpha_m * t) * sin(omega_m * t + phi_m)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Infinite includes five calibrated body profiles fitted from acoustic measurements of real instruments:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Body profile&lt;/th&gt;
&lt;th&gt;Key acoustic resonances&lt;/th&gt;
&lt;th&gt;Sonic character&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Box&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Helmholtz cavity (98 Hz) and primary plate mode (204 Hz)&lt;/td&gt;
&lt;td&gt;Small hollow acoustic box with dry, woody decay&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Guitar&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Air mode A0 (99 Hz), top plate T(1,1) pair (199 Hz, 392 Hz)&lt;/td&gt;
&lt;td&gt;Warm, balanced acoustic dreadnought and classical guitar&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Harp&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Soundboard resonance (211 Hz) and pillar modes (325 Hz)&lt;/td&gt;
&lt;td&gt;Open, airy, resonant decay with singing sustain&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Violin&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Air mode A0 (281 Hz), corpus corpus modes B1-/B1+ (445 Hz, 535 Hz)&lt;/td&gt;
&lt;td&gt;Focused, expressive acoustic projection with bite&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Cello&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Deep cavity mode (105 Hz) and body resonances (199 Hz, 320 Hz)&lt;/td&gt;
&lt;td&gt;Rich, woody, authoritative low-frequency resonance&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Because all active polyphonic voices feed into the same shared body filter, notes interact acoustically, vibrating the simulated soundboard and creating natural sympathetic depth.&lt;/p&gt;

&lt;h2&gt;
  
  
  Building an audiovisual physical modelling patch in Infinite
&lt;/h2&gt;

&lt;p&gt;In Infinite, sound synthesis and visual rendering run on the same unified graph. You can patch an expressive physical modelling instrument and use its internal acoustics to deform 3D meshes in real time.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;+----------------+      note       +------------------+      audio      +------------------+
| Note Sequencer | --------------&amp;gt; | String (Synth)   | --------------&amp;gt; | Resonator Bank   |
+----------------+                 +------------------+                 +------------------+
                                            ^                                    |
                                            | pressure mod                       | audio
+----------------+                          |                                    v
| LFO            | -------------------------+                           +------------------+
+----------------+                                                      | Audio Analyze    |
                                                                        +------------------+
                                                                                 |
                                                                                 | spectral RMS
                                                                                 v
+----------------+      mesh       +--------------------+      mesh     +------------------+
| Cylinder Wire  | --------------&amp;gt; | Audio Displacement | ------------&amp;gt; | Render 3D        |
+----------------+                 +--------------------+               +------------------+
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 1: Create the note driver and exciter
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Add a &lt;a href="https://infinitedevices.org/nodes/note-sequencer.html" rel="noopener noreferrer"&gt;&lt;code&gt;Note Sequencer&lt;/code&gt;&lt;/a&gt; node to the canvas. Set &lt;code&gt;division&lt;/code&gt; to &lt;code&gt;1/16 sync&lt;/code&gt; and program an arpeggiated melodic line.&lt;/li&gt;
&lt;li&gt;Add a &lt;a href="https://infinitedevices.org/nodes/string.html" rel="noopener noreferrer"&gt;&lt;code&gt;String&lt;/code&gt;&lt;/a&gt; node. Connect the green note output of the &lt;code&gt;Note Sequencer&lt;/code&gt; to the &lt;code&gt;notes&lt;/code&gt; input of the &lt;code&gt;String&lt;/code&gt; node.&lt;/li&gt;
&lt;li&gt;On the &lt;code&gt;String&lt;/code&gt; node, select &lt;code&gt;exciter: Bow&lt;/code&gt; and choose &lt;code&gt;bodyType: Cello&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Set &lt;code&gt;decay&lt;/code&gt; to &lt;code&gt;2.4 s&lt;/code&gt;, &lt;code&gt;stiffness&lt;/code&gt; to &lt;code&gt;0.30&lt;/code&gt;, and &lt;code&gt;tone&lt;/code&gt; to &lt;code&gt;0.75&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Step 2: Add dynamic expressive modulation
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Add an &lt;a href="https://infinitedevices.org/nodes/lfo.html" rel="noopener noreferrer"&gt;&lt;code&gt;LFO&lt;/code&gt;&lt;/a&gt; node. Set the shape to &lt;code&gt;Triangle&lt;/code&gt; and tempo-sync the rate to &lt;code&gt;1/2 bar&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Connect the LFO output cable to the &lt;code&gt;pressure&lt;/code&gt; parameter of the &lt;code&gt;String&lt;/code&gt; node. As the LFO oscillates, the simulated bow pressure increases and relaxes, moving naturally between gentle whispers and raspy, full-bodied string sustains.&lt;/li&gt;
&lt;li&gt;Add a second slow LFO (or an envelope follower) routed to &lt;code&gt;position&lt;/code&gt;, moving the bowing point between the bridge (sul ponticello) and the fingerboard (sul tasto).&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Step 3: Route through the modal resonator and analysis
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Connect the audio output of &lt;code&gt;String&lt;/code&gt; to a &lt;a href="https://infinitedevices.org/nodes/resonator-bank.html" rel="noopener noreferrer"&gt;&lt;code&gt;Resonator Bank&lt;/code&gt;&lt;/a&gt; node to introduce room resonance and spatial depth.&lt;/li&gt;
&lt;li&gt;Connect the output to an &lt;a href="https://infinitedevices.org/nodes/audio-analyze.html" rel="noopener noreferrer"&gt;&lt;code&gt;Audio Analyze&lt;/code&gt;&lt;/a&gt; node. This extracts real-time amplitude envelopes, spectral RMS energy, and pitch tracking data on every audio buffer.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Step 4: Deform 3D geometry in Render 3D
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Add a &lt;code&gt;Cylinder&lt;/code&gt; mesh primitive and set it to wireframe mode to represent a vibrating physical string.&lt;/li&gt;
&lt;li&gt;Add an &lt;a href="https://infinitedevices.org/nodes/audio-displacement.html" rel="noopener noreferrer"&gt;&lt;code&gt;Audio Displacement&lt;/code&gt;&lt;/a&gt; node. Connect the mesh output into its geometry input, and connect the &lt;code&gt;spectralRms&lt;/code&gt; output from &lt;code&gt;Audio Analyze&lt;/code&gt; to the displacement amplitude.&lt;/li&gt;
&lt;li&gt;Wire the resulting geometry into &lt;a href="https://infinitedevices.org/nodes/render-3d.html" rel="noopener noreferrer"&gt;&lt;code&gt;Render 3D&lt;/code&gt;&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;When a note is bowed, the 3D string geometry physically vibrates with travelling wave deformations matching the exact frequency, damping, and decay of the acoustic digital waveguide.&lt;/p&gt;

&lt;h2&gt;
  
  
  Performance characteristics and real-time execution
&lt;/h2&gt;

&lt;p&gt;Running complex numerical differential equations and allpass filter cascades in real time requires strict computational discipline:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Eight-voice polyphony&lt;/strong&gt;: The &lt;code&gt;String&lt;/code&gt; node supports up to 8 polyphonic voices. Unused voices are culled instantaneously when their decay envelope drops below -96 dB, conserving CPU cycles.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Chunked parameter updates&lt;/strong&gt;: Heavy mathematical operations (such as the 40-iteration allpass phase solver and modal coefficient recalculations) run once every 32 samples (0.7 ms at 48 kHz). Sample-rate audio buffers interpolate these values using lock-free atomic parameter mailboxes, avoiding audio dropouts or zipper noise.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SIMD vectorisation&lt;/strong&gt;: The modal body filter bank evaluates multiple biquad modes in parallel using AVX2 and ARM Neon vector instructions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Zero dynamic memory allocations&lt;/strong&gt;: All waveguide ring buffers, allpass delay lines, and mode state arrays are statically pre-allocated at startup. The audio thread executes without heap allocations or mutex contention.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By combining the physical mathematics of acoustic wave propagation with real-time modular execution, physical modelling synthesis delivers responsive instruments that feel alive under your fingers and on screen.&lt;/p&gt;

&lt;p&gt;Explore native sound design and modular synthesis in the &lt;a href="https://infinitedevices.org/library.html" rel="noopener noreferrer"&gt;Infinite Library&lt;/a&gt;, inspect the full &lt;a href="https://infinitedevices.org/nodes/" rel="noopener noreferrer"&gt;Node Reference&lt;/a&gt;, or read our deep dive on &lt;a href="https://infinitedevices.org/blog/audio-reactive-glsl-shaders.html" rel="noopener noreferrer"&gt;audio-reactive GLSL shaders&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://infinitedevices.org/blog/physical-modelling-string-synthesis-in-real-time.html" rel="noopener noreferrer"&gt;https://infinitedevices.org/blog/physical-modelling-string-synthesis-in-real-time.html&lt;/a&gt;. Infinite is a free, open-source DAW for visuals, music and code: &lt;a href="https://infinitedevices.org" rel="noopener noreferrer"&gt;infinitedevices.org&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>physicalmodelling</category>
      <category>digitalwaveguides</category>
      <category>sounddesign</category>
      <category>modularsynthesis</category>
    </item>
    <item>
      <title>Delaunay triangulation and Voronoi geometry in real time</title>
      <dc:creator>naman</dc:creator>
      <pubDate>Wed, 11 Nov 2026 13:14:33 +0000</pubDate>
      <link>https://dev.to/n1m21n/delaunay-triangulation-and-voronoi-geometry-in-real-time-1oep</link>
      <guid>https://dev.to/n1m21n/delaunay-triangulation-and-voronoi-geometry-in-real-time-1oep</guid>
      <description>&lt;p&gt;In computational geometry and procedural graphics, &lt;strong&gt;delaunay triangulation real time&lt;/strong&gt; algorithms provide a method to generate clean, dynamic 3D meshes directly from shifting point clouds. While static meshes rely on pre-baked vertex index buffers that remain rigid during performance, dynamic triangulation reconstructs the topological connectivity between vertices on every frame. When combined with its mathematical dual, the Voronoi diagram, artists can transform particle clouds, audio waveforms, and spatial simulations into fluid geometric surfaces, faceted crystalline shells, and organic cellular tessellations.&lt;/p&gt;

&lt;p&gt;In real-time audiovisual environments like &lt;a href="https://infinitedevices.org/" rel="noopener noreferrer"&gt;Infinite&lt;/a&gt;, dynamic triangulation links sound synthesis with procedural 3D form. Because audio signals can displace spatial coordinates at frame rates, recalculating Delaunay triangles and Voronoi cells on the fly allows the topology of a mesh to split, merge, and reform in direct response to acoustic energy.&lt;/p&gt;

&lt;p&gt;Here is an in-depth examination of the mathematical principles behind Delaunay triangulation, the Bowyer-Watson cavity insertion algorithm, dual Voronoi cell generation with polygon insetting, 3D heightfield lifting, and how to patch an audio-reactive mesh using native nodes.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Frcrz7wlw7fe57dz51y7r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Frcrz7wlw7fe57dz51y7r.png" alt="Technical architecture diagram of real-time Delaunay triangulation and Voronoi cells showing circumcircle test, Bowyer-Watson cavity insertion, cell insetting, and 3D audio-reactive mesh lifting" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Dynamic topology versus static meshes in computer graphics
&lt;/h2&gt;

&lt;p&gt;Most 3D models in computer graphics are defined by two arrays: a vertex array containing spatial positions &lt;code&gt;(x, y, z)&lt;/code&gt;, normals, and texture coordinates, and an index array containing triplets of integers that reference those vertices to form triangular faces. In standard rendering pipelines, the index array is static. When a vertex shader or physics engine deforms the model, the vertices move, but the edges between them remain fixed.&lt;/p&gt;

&lt;p&gt;This rigidity works well for character meshes and rigid bodies, but it limits generative and reactive art. If a cloud of particles expands, contracts, or swirls under turbulent forces, stretching static triangles produces long, distorted needles known as slivers. Slivers cause severe rendering artefacts, including rasterisation bottlenecks, pixel flickering, and erratic surface normals under directional lighting.&lt;/p&gt;

&lt;p&gt;Dynamic triangulation solves this by recomputing the triangle index buffer on every cook cycle. As points drift, separate, or enter the scene, the algorithm evaluates spatial proximity and reconfigures the edge connections. When two particles move apart, their connecting edge dissolves, and new edges form between closer neighbours. This produces a continuous, surface-like manifold that adapts to whatever spatial distribution the simulation generates.&lt;/p&gt;

&lt;h2&gt;
  
  
  The empty circumcircle criterion and Bowyer-Watson insertion
&lt;/h2&gt;

&lt;p&gt;A triangulation of a planar point set &lt;code&gt;P&lt;/code&gt; is a collection of non-overlapping triangles whose vertices are in &lt;code&gt;P&lt;/code&gt; and whose union covers the convex hull of &lt;code&gt;P&lt;/code&gt;. For any set of three non-collinear points in the Cartesian plane, there exists a unique circle that passes through all three points: the circumcircle.&lt;/p&gt;

&lt;p&gt;In 1934, Boris Delaunay proved that a triangulation is optimal if and only if the circumcircle of every triangle contains no points of &lt;code&gt;P&lt;/code&gt; in its interior. This condition is the empty circumcircle criterion:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;For every triangle T(a, b, c) in the triangulation:
Distance(p, Centre(T)) &amp;gt;= Radius(T)  for all points p in P
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The empty circumcircle property possesses a critical geometric consequence: it maximises the minimum interior angle of all triangles in the mesh. By avoiding skinny, acute angles, Delaunay triangulation produces the most equiangular, well-proportioned triangles possible for any given distribution of vertices.&lt;/p&gt;

&lt;h3&gt;
  
  
  Computing the circumcircle in double precision
&lt;/h3&gt;

&lt;p&gt;Given three 2D vertices &lt;code&gt;a&lt;/code&gt;, &lt;code&gt;b&lt;/code&gt;, and &lt;code&gt;c&lt;/code&gt;, we can translate vertex &lt;code&gt;a&lt;/code&gt; to the origin:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;bx = b.x - a.x,   by = b.y - a.y
cx = c.x - a.x,   cy = c.y - a.y
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The circumcentre offset &lt;code&gt;(ux, uy)&lt;/code&gt; from &lt;code&gt;a&lt;/code&gt; is found by solving the intersection of the perpendicular bisectors of sides &lt;code&gt;ab&lt;/code&gt; and &lt;code&gt;ac&lt;/code&gt;. The system determinant &lt;code&gt;D&lt;/code&gt; is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;D = 2.0 * (bx * cy - by * cx)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If &lt;code&gt;abs(D)&lt;/code&gt; is close to zero, the three vertices are collinear, and no finite circumcircle exists. Otherwise, using the squared lengths &lt;code&gt;b2 = bx*bx + by*by&lt;/code&gt; and &lt;code&gt;c2 = cx*cx + cy*cy&lt;/code&gt;, the circumcentre &lt;code&gt;(cx_circ, cy_circ)&lt;/code&gt; and radius squared &lt;code&gt;r2&lt;/code&gt; are:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ux = (cy * b2 - by * c2) / D
uy = (bx * c2 - cx * b2) / D

cx_circ = a.x + ux
cy_circ = a.y + uy
r2 = ux * ux + uy * uy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A point &lt;code&gt;(px, py)&lt;/code&gt; violates the Delaunay criterion for this triangle if:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;(px - cx_circ)^2 + (py - cy_circ)^2 &amp;lt; r2 * (1.0 - 1e-12)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The small epsilon tolerance &lt;code&gt;1e-12&lt;/code&gt; prevents numerical instability when points lie almost exactly on the circumcircle boundary.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Bowyer-Watson incremental algorithm
&lt;/h3&gt;

&lt;p&gt;The Bowyer-Watson algorithm (developed independently by Adrian Bowyer and David Watson in 1981) inserts points one by one into an existing Delaunay triangulation:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Initialise with a super-triangle&lt;/strong&gt;: construct an artificial, expansive triangle that completely encloses the bounding box of the point set. This guarantees that all real points fall within at least one valid triangle.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Find bad triangles&lt;/strong&gt;: when inserting point &lt;code&gt;p&lt;/code&gt;, scan the existing triangle list and identify every triangle whose circumcircle encloses &lt;code&gt;p&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Form the cavity&lt;/strong&gt;: delete all bad triangles. The union of these deleted triangles forms a star-shaped polygonal cavity containing &lt;code&gt;p&lt;/code&gt;. The boundary of this cavity consists of all edges that belonged to exactly one bad triangle.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sew new triangles&lt;/strong&gt;: connect each edge of the cavity boundary to the new point &lt;code&gt;p&lt;/code&gt;, creating a set of new triangles that satisfy the empty circumcircle criterion.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Remove super-triangle vertices&lt;/strong&gt;: once all points are inserted, discard every triangle that shares any vertex with the initial super-triangle. The remaining triangles form the Delaunay triangulation of the input points.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;To maintain real-time performance at 60 FPS, the implementation in Infinite sorts points along a grid-snake spatial curve prior to insertion. Because sequentially inserted points are spatially adjacent, the set of invalid triangles remains local, allowing rapid cavity extraction. Furthermore, dead triangles are periodically compacted in memory to prevent the traversal loop from scanning discarded entries.&lt;/p&gt;

&lt;h2&gt;
  
  
  Building the Voronoi dual and polygon insetting
&lt;/h2&gt;

&lt;p&gt;Every Delaunay triangulation has a unique geometric dual: the Voronoi diagram (first studied by Georgy Voronoy in 1908). While Delaunay triangulation partitions space into triangles connecting neighbouring sites, the Voronoi diagram partitions space into convex polygonal cells, where each cell contains all spatial locations closer to its generating site than to any other site.&lt;/p&gt;

&lt;p&gt;The duality between the two structures is exact:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Each circumcentre of a Delaunay triangle becomes a vertex of the Voronoi diagram.&lt;/li&gt;
&lt;li&gt;Each edge in the Delaunay triangulation corresponds to a shared boundary edge in the Voronoi diagram, running perpendicular to the Delaunay edge.&lt;/li&gt;
&lt;li&gt;Each site in the Delaunay triangulation is surrounded by a Voronoi polygon whose vertices are the circumcentres of the Delaunay triangles sharing that site.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Extracting Voronoi cells from triangle fans
&lt;/h3&gt;

&lt;p&gt;To construct Voronoi cells from the triangulated mesh, the &lt;strong&gt;Voronoi Cells&lt;/strong&gt; node in Infinite executes the following steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Count edge usage&lt;/strong&gt;: iterate through all Delaunay triangles and count how many times each undirected edge appears. Edges that appear exactly once form the convex hull of the point cloud.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Prune hull vertices&lt;/strong&gt;: sites that lie on the convex hull have unbounded Voronoi cells that extend to infinity. These are flagged and skipped so that only well-defined, closed interior cells are generated.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Assemble triangle fans&lt;/strong&gt;: for each interior site, collect the indices of all triangles meeting at that site.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sort circumcentres radially&lt;/strong&gt;: calculate the circumcentre of each triangle in the fan and compute its polar angle relative to the site: &lt;code&gt;angle = atan2(cy - site_y, cx - site_x)&lt;/code&gt;. Sorting the circumcentres by angle arranges the vertices of the Voronoi cell in counter-clockwise order.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cap sliver circumcentres&lt;/strong&gt;: triangles near the outer boundary can occasionally have circumcentres that lie far outside the cloud. The engine clamps the distance of any circumcentre to at most twice the maximum radius of the triangle, preventing spikes from rupturing the cell layout.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Polygon insetting for architectural and cellular aesthetics
&lt;/h3&gt;

&lt;p&gt;A flat tessellation where all cells touch edge-to-edge can look monolithic. The &lt;strong&gt;Voronoi Cells&lt;/strong&gt; node includes an &lt;code&gt;inset&lt;/code&gt; parameter (ranging from &lt;code&gt;0.0&lt;/code&gt; to &lt;code&gt;0.95&lt;/code&gt;) that scales each cell towards its generating site:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;inset_vertex = site + (circumcentre - site) * (1.0 - inset)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When &lt;code&gt;inset&lt;/code&gt; is zero, cells share mutual boundaries. As &lt;code&gt;inset&lt;/code&gt; increases, channels open up between adjacent cells, revealing negative space. The node triangulates each inset cell by creating a central vertex at the site position and generating a fan of triangular faces connecting the centre to each pair of adjacent perimeter vertices.&lt;/p&gt;

&lt;p&gt;This insetting mechanism enables diverse creative styles, ranging from stained-glass windows and architectural ceiling cassettes to cracked desert mud and microscopic cellular membranes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Projecting planes and lifting back to three dimensions
&lt;/h2&gt;

&lt;p&gt;While 2D Delaunay algorithms are mathematically robust and computationally tractable in real time, many generative audiovisual scenes require 3D geometry. Calculating true 3D Delaunay tetrahedralisation is substantially more expensive, $O(n^2)$ to $O(n^4)$, and yields solid 3D tetrahedra rather than a hollow, renderable 2D surface manifold.&lt;/p&gt;

&lt;p&gt;To solve this, Infinite uses a 2.5D projection and lifting architecture in &lt;code&gt;DelaunayMeshNode&lt;/code&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Projection&lt;/strong&gt;: the user selects a projection plane via the &lt;code&gt;plane&lt;/code&gt; parameter (&lt;code&gt;0: XY&lt;/code&gt;, &lt;code&gt;1: XZ&lt;/code&gt;, &lt;code&gt;2: YZ&lt;/code&gt;). The 3D coordinates &lt;code&gt;(px, py, pz)&lt;/code&gt; of each site are projected onto the selected 2D plane:

&lt;ul&gt;
&lt;li&gt;For &lt;code&gt;XY&lt;/code&gt;, the projected coordinates are &lt;code&gt;(u = px, v = py)&lt;/code&gt;, facing normal &lt;code&gt;(0, 0, 1)&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;For &lt;code&gt;XZ&lt;/code&gt;, the projected coordinates are &lt;code&gt;(u = pz, v = px)&lt;/code&gt;, facing normal &lt;code&gt;(0, 1, 0)&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;For &lt;code&gt;YZ&lt;/code&gt;, the projected coordinates are &lt;code&gt;(u = py, v = pz)&lt;/code&gt;, facing normal &lt;code&gt;(1, 0, 0)&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Planar triangulation&lt;/strong&gt;: the 2D projected coordinates are triangulated using the Bowyer-Watson engine. Texture coordinates &lt;code&gt;(u, v)&lt;/code&gt; are normalised across the bounding box of the cloud to enable texture mapping.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Elevation lifting&lt;/strong&gt;: once the triangle topology is established, the original third unprojected coordinate is restored for each vertex.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;When a point cloud has elevation, such as an audio-displaced particle grid or terrain heights, the 2D triangulation acts as a surface mesh lifted into 3D space. The resulting surface bends, folds, and undulates with the underlying simulation, creating an expressive terrain that never tears or overlaps unnaturally.&lt;/p&gt;

&lt;h2&gt;
  
  
  Patching an audio-reactive mesh in Infinite
&lt;/h2&gt;

&lt;p&gt;Building a complete real-time audiovisual patch using Delaunay and Voronoi nodes involves connecting audio analysis, procedural point generation, geometry operations, and 3D rendering.&lt;/p&gt;

&lt;p&gt;Here is a recommended node graph layout:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[Audio Input] -&amp;gt; [Audio Analyze]
                       |
               (FFT low / mid / high)
                       |
                       v
[Point Distribution] -&amp;gt; [Audio Displacement] -&amp;gt; [Delaunay Mesh] -&amp;gt; [Material] -&amp;gt; [Render 3D]
                                                     |
                                            (or [Voronoi Cells])
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  1. Generating the point cloud
&lt;/h3&gt;

&lt;p&gt;Add a &lt;strong&gt;Point Distribution&lt;/strong&gt; node to spawn the initial site positions. You can set the distribution mode to a 2D Poisson disc distribution or a random planar scatter. Alternatively, a &lt;strong&gt;Particle System&lt;/strong&gt; node can be used to simulate floating particles driven by curl noise and velocity damping.&lt;/p&gt;

&lt;p&gt;Set the point count to approximately 800 to 1,500 points. This provides high geometric detail while leaving headroom for other synthesis and graphics nodes on the canvas.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Audio displacement
&lt;/h3&gt;

&lt;p&gt;Wire the audio output from a synth, sampler, or live audio track into an &lt;strong&gt;Audio Analyze&lt;/strong&gt; node. The node extracts an 8-band FFT spectrum and transient onset detectors.&lt;/p&gt;

&lt;p&gt;Patch the point cloud from &lt;strong&gt;Point Distribution&lt;/strong&gt; into the geometry input of an &lt;strong&gt;Audio Displacement&lt;/strong&gt; node. Map the low-frequency bass band to the vertical displacement axis. When a kick drum hits, the points push upward in world space.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Mesh construction with Delaunay Mesh
&lt;/h3&gt;

&lt;p&gt;Connect the displaced points into a &lt;strong&gt;Delaunay Mesh&lt;/strong&gt; node. Configure its parameters:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;plane&lt;/code&gt;: select &lt;code&gt;XZ&lt;/code&gt; so the triangulation occurs across the horizontal ground plane while the audio displacement lifts vertices along the &lt;code&gt;Y&lt;/code&gt; axis.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;aliveOnly&lt;/code&gt;: enable this toggle when using particles so that dead particles are excluded before triangulation.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;maxPoints&lt;/code&gt;: set to &lt;code&gt;2000&lt;/code&gt; to protect the rendering loop against unexpected particle bursts.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As the points move under the influence of the audio signal, the Delaunay engine dynamically recalculates the triangle indices. If you switch the node to &lt;strong&gt;Voronoi Cells&lt;/strong&gt; and set &lt;code&gt;inset&lt;/code&gt; to &lt;code&gt;0.20&lt;/code&gt;, the mesh transforms into an array of floating, isolated tiles that pulse and tilt with the sound.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Shading and rendering
&lt;/h3&gt;

&lt;p&gt;Wire the mesh output into a &lt;strong&gt;Material&lt;/strong&gt; node. Set the roughness to &lt;code&gt;0.3&lt;/code&gt; and metallic to &lt;code&gt;0.8&lt;/code&gt; to give the facets a reflective, polished finish.&lt;/p&gt;

&lt;p&gt;Connect the material into a &lt;strong&gt;Render 3D&lt;/strong&gt; node alongside a &lt;strong&gt;Directional Light&lt;/strong&gt; and a &lt;strong&gt;Camera 3D&lt;/strong&gt;. As the facets shift their orientation each frame, specular highlights glint across the changing edges, producing a visual response synchronized to the music.&lt;/p&gt;

&lt;p&gt;For further exploration of shader uniforms and procedural deformation techniques, refer to our guide on &lt;a href="https://infinitedevices.org/blog/procedural-3d-geometry-nodes-and-audio-deformation.html" rel="noopener noreferrer"&gt;procedural 3D geometry nodes and audio deformation&lt;/a&gt; and our walkthrough of &lt;a href="https://infinitedevices.org/blog/audio-reactive-particle-systems-in-real-time.html" rel="noopener noreferrer"&gt;audio-reactive particle systems in real time&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Computational complexity, spatial sorting, and point budgets
&lt;/h2&gt;

&lt;p&gt;Understanding the computational performance of dynamic triangulation is essential for maintaining a stable 60 FPS frame rate in live performances.&lt;/p&gt;

&lt;h3&gt;
  
  
  Time complexity and memory compaction
&lt;/h3&gt;

&lt;p&gt;A naive implementation of the Bowyer-Watson algorithm tests every inserted point against all existing triangles, resulting in an $O(n^2)$ worst-case time complexity. For 1,000 points, this requires approximately 1,000,000 circumcircle checks.&lt;/p&gt;

&lt;p&gt;To optimise this for real-time operation, Infinite uses a grid-snake spatial sort. By sorting points into a 2D spatial grid prior to insertion, each point is placed into the mesh immediately adjacent to the triangles created by its spatial predecessor. This keeps the cavity search local and reduces average-case execution time towards $O(n \log n)$.&lt;/p&gt;

&lt;p&gt;Furthermore, during cavity deletion, bad triangles are marked dead. In a long insertion loop, dead triangles can clutter memory and slow down linear scans. Infinite's core Delaunay implementation checks when the triangle array exceeds 4,096 entries and automatically compacts the array by copying live triangles into contiguous memory.&lt;/p&gt;

&lt;h3&gt;
  
  
  Practical point budgeting
&lt;/h3&gt;

&lt;p&gt;For real-time graphics at 60 FPS, a frame budget is roughly 16.6 milliseconds. In a combined audiovisual patch, audio processing typically takes 1 to 2 ms, GPU shader passes take 4 to 8 ms, leaving approximately 3 to 5 ms for CPU geometry calculations.&lt;/p&gt;

&lt;p&gt;Based on benchmark tests across Apple Silicon and x86_64 architectures:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;300 to 600 points&lt;/strong&gt;: cook time is under 0.6 ms. This is ideal when multiple meshes are active simultaneously or when running complex GLSL post-processing effects.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;1,000 to 1,800 points&lt;/strong&gt;: cook time is 1.2 to 2.4 ms. This produces dense, intricate geometric surfaces with crisp silhouette details.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;2,500 to 5,000 points&lt;/strong&gt;: cook time reaches 4.5 to 9.0 ms. While viable on dedicated desktop machines, it approaches the limit of real-time responsiveness and should be used cautiously in live VJ contexts.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Infinite enforces a configurable &lt;code&gt;maxPoints&lt;/code&gt; cap (defaulting to 2,000 points) on both &lt;strong&gt;Delaunay Mesh&lt;/strong&gt; and &lt;strong&gt;Voronoi Cells&lt;/strong&gt;. If an upstream particle emitter exceeds this threshold, the node systematically subsamples the sites to maintain real-time stability rather than dropping frames.&lt;/p&gt;

&lt;h2&gt;
  
  
  Practical creative workflows and aesthetic applications
&lt;/h2&gt;

&lt;p&gt;Dynamic Delaunay and Voronoi geometry opens up distinct visual aesthetics that are difficult to achieve with standard polygonal modeling:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Low-poly crystalline landscapes&lt;/strong&gt;: by displacing an XZ particle grid with Perlin noise and audio low-end, Delaunay triangulation forms a faceted, low-poly mountain range where polygons continuously adapt to the contours.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Shattered glass and Voronoi fracture&lt;/strong&gt;: mapping an audio onset trigger to the &lt;code&gt;inset&lt;/code&gt; control creates the illusion of an impact crater, where a smooth surface abruptly fractures into hundreds of receding tiles when a snare drum fires.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cellular lifeforms and organic membranes&lt;/strong&gt;: pairing &lt;strong&gt;Voronoi Cells&lt;/strong&gt; with curl-noise particle flow simulates the movement of microscopic cells drifting under fluid currents.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dynamic wireframe webs&lt;/strong&gt;: extracting the edges of the Delaunay mesh and rendering them as geometric lines yields a retro-futuristic radar web that connects points when they approach each other and severs links when they diverge.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can inspect ready-to-run audiovisual patches and templates in the &lt;a href="https://infinitedevices.org/library.html" rel="noopener noreferrer"&gt;Infinite Library&lt;/a&gt;, or explore the core architecture on the &lt;a href="https://infinitedevices.org/" rel="noopener noreferrer"&gt;Infinite home page&lt;/a&gt;. Dynamic triangulation bridges the gap between chaotic point distributions and ordered 3D surfaces, turning raw mathematical coordinates into living generative visuals.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://infinitedevices.org/blog/delaunay-triangulation-and-voronoi-geometry-in-real-time.html" rel="noopener noreferrer"&gt;https://infinitedevices.org/blog/delaunay-triangulation-and-voronoi-geometry-in-real-time.html&lt;/a&gt;. Infinite is a free, open-source DAW for visuals, music and code: &lt;a href="https://infinitedevices.org" rel="noopener noreferrer"&gt;infinitedevices.org&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>delaunaytriangulation</category>
      <category>voronoicells</category>
      <category>generative3d</category>
      <category>creativecoding</category>
    </item>
    <item>
      <title>Reaction-diffusion simulation in real-time GLSL</title>
      <dc:creator>naman</dc:creator>
      <pubDate>Thu, 29 Oct 2026 09:13:07 +0000</pubDate>
      <link>https://dev.to/n1m21n/reaction-diffusion-simulation-in-real-time-glsl-3cak</link>
      <guid>https://dev.to/n1m21n/reaction-diffusion-simulation-in-real-time-glsl-3cak</guid>
      <description>&lt;p&gt;A reaction-diffusion simulation in real-time GLSL brings the organic complexity of natural morphogenesis directly into creative coding and live visual performance. From the spots on a leopard and the stripes on a zebrafish to coral formations and cellular colonies, biological patterns are rarely drawn with static geometry. Instead, they grow out of non-linear chemical interactions where substances spread, react, and compete across space.&lt;/p&gt;

&lt;p&gt;In audiovisual environments like &lt;a href="https://infinitedevices.org/" rel="noopener noreferrer"&gt;Infinite&lt;/a&gt;, reaction-diffusion simulations can run entirely on the GPU, updating at high frame rates while reacting to incoming sound. By coupling partial differential equations to real-time audio analysis, artists can guide chemical morphogenesis with musical rhythm, using bass frequencies to seed new matter and high frequencies to trigger cell division.&lt;/p&gt;

&lt;p&gt;Here is how the underlying chemistry works, how to discretise the equations for GLSL execution, and how to patch an audio-reactive reaction-diffusion pipeline using both native nodes and custom Field kernels.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fdgpe41seicwydcrc781c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fdgpe41seicwydcrc781c.png" alt="Reaction-diffusion simulation diagram showing chemical morphogenesis equations, 9-point Laplacian convolution stencil, and node graph" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The morphogenesis equations of Alan Turing and &lt;code&gt;Gray-Scott&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;The mathematical foundation of biological pattern formation was introduced in 1952 by Alan Turing in his paper &lt;em&gt;The Chemical Basis of Morphogenesis&lt;/em&gt;. Turing demonstrated that a system of two reacting chemicals with different diffusion rates, initially distributed almost uniformly, can spontaneously break symmetry and produce stable spatial patterns: spots, stripes, and whorls.&lt;/p&gt;

&lt;p&gt;The most widely adopted model in computer graphics and creative coding is the &lt;code&gt;Gray-Scott&lt;/code&gt; reaction-diffusion formulation, developed in 1983. In this model, two hypothetical chemical substances, chemical A and chemical B, diffuse across a two-dimensional grid while undergoing an autocatalytic reaction.&lt;/p&gt;

&lt;p&gt;Chemical A represents a nourishing substrate that is constantly replenished at a feed rate &lt;code&gt;F&lt;/code&gt;. Chemical B represents an active catalyst that consumes chemical A to duplicate itself through the reaction:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;2B + A -&amp;gt; 3B
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As chemical B reproduces, it also decays and is removed from the system at a kill rate &lt;code&gt;k&lt;/code&gt;. The continuous system is governed by two coupled partial differential equations:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dA / dt = D_a * ∇²A - A * B² + F * (1.0 - A)
dB / dt = D_b * ∇²B + A * B² - (F + k) * B
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;D_a&lt;/code&gt; and &lt;code&gt;D_b&lt;/code&gt; are the spatial diffusion rates of substances A and B. For pattern formation to occur, substance A must diffuse significantly faster than substance B, typically with &lt;code&gt;D_a = 1.0&lt;/code&gt; and &lt;code&gt;D_b = 0.5&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;∇²&lt;/code&gt; is the Laplacian operator, which computes the second spatial derivative of chemical concentration: measuring whether a point has a higher or lower concentration than its surrounding neighbourhood.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;A * B²&lt;/code&gt; is the non-linear reaction term representing the conversion of substrate A into catalyst B in the presence of two units of B.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;F * (1.0 - A)&lt;/code&gt; represents the replenishment of chemical A toward its maximum saturation level of &lt;code&gt;1.0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;(F + k) * B&lt;/code&gt; represents the depletion of chemical B through natural decay and dilution.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The delicate balance between the feed rate &lt;code&gt;F&lt;/code&gt; and the kill rate &lt;code&gt;k&lt;/code&gt; determines the resulting morphological pattern. Small changes in these two numbers move the simulation between distinct visual regimes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Coral growth (&lt;code&gt;F = 0.054&lt;/code&gt;, &lt;code&gt;k = 0.062&lt;/code&gt;): slender dendritic branches that expand outward and weave together.&lt;/li&gt;
&lt;li&gt;Mitosis and dividing cells (&lt;code&gt;F = 0.036&lt;/code&gt;, &lt;code&gt;k = 0.065&lt;/code&gt;): individual circular spots that grow, deform into dumbbells, and divide into autonomous pairs.&lt;/li&gt;
&lt;li&gt;Soliton waves (&lt;code&gt;F = 0.030&lt;/code&gt;, &lt;code&gt;k = 0.062&lt;/code&gt;): pulsating spots and traveling ripples that interact elastically.&lt;/li&gt;
&lt;li&gt;Labyrinthine maze (&lt;code&gt;F = 0.029&lt;/code&gt;, &lt;code&gt;k = 0.057&lt;/code&gt;): dense fingerprint-like ridges and interconnected loops that fill the canvas.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Discretising the continuous Laplacian on a GPU pixel grid
&lt;/h2&gt;

&lt;p&gt;To execute the &lt;code&gt;Gray-Scott&lt;/code&gt; model on modern graphics hardware in real time, the continuous spatial derivatives must be discretised onto a discrete two-dimensional grid of texels.&lt;/p&gt;

&lt;p&gt;The Laplacian operator &lt;code&gt;∇²&lt;/code&gt; measures the divergence of the gradient: the net flow of chemical into or out of a local area. On a discrete square grid with texel spacing &lt;code&gt;Δx = 1.0&lt;/code&gt;, we compute the Laplacian using a two-dimensional convolution kernel evaluated over each pixel and its eight immediate neighbours:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;∇²U(x, y) ≈ 
    0.05 * U(x - 1, y - 1) + 0.20 * U(x, y - 1) + 0.05 * U(x + 1, y - 1) +
    0.20 * U(x - 1, y)     - 1.00 * U(x, y)     + 0.20 * U(x + 1, y) +
    0.05 * U(x - 1, y + 1) + 0.20 * U(x, y + 1) + 0.05 * U(x + 1, y + 1)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice the arithmetic structure of this 9-point stencil:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The orthogonal direct neighbours (top, bottom, left, right) each receive a weight of &lt;code&gt;+0.20&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The diagonal corner neighbours receive a weight of &lt;code&gt;+0.05&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The central pixel receives a weight of &lt;code&gt;-1.00&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The sum of all nine weights equals exactly &lt;code&gt;0.0&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This zero-sum constraint guarantees that in an area of uniform concentration where all neighbouring pixels have identical values, the Laplacian evaluates to zero: no spurious chemical diffusion is created out of nothing.&lt;/p&gt;

&lt;p&gt;Because the numerical simulation must feed its own output back into its input on subsequent time steps, real-time GPU implementations allocate two 32-bit floating-point textures (an RG32F ping-pong framebuffer pair). Channel R stores the concentration of chemical A, while channel G stores the concentration of chemical B.&lt;/p&gt;

&lt;p&gt;In each rendering pass, the fragment shader samples the current state texture, computes the discrete Laplacian, evaluates the reaction equations, and writes the updated &lt;code&gt;(A, B)&lt;/code&gt; values to the secondary texture. On the next step, the roles of the two textures are swapped.&lt;/p&gt;

&lt;p&gt;To maintain temporal stability while avoiding spatial aliasing, multiple integration substeps are evaluated per displayed video frame: typically between 4 and 16 iterations per frame with a time step &lt;code&gt;dt = 1.0&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Simulating reaction-diffusion with the native node
&lt;/h2&gt;

&lt;p&gt;Infinite provides a native GPU-accelerated compositing node designed specifically for this physical process: the &lt;a href="https://infinitedevices.org/nodes/reaction-diffusion.html" rel="noopener noreferrer"&gt;Reaction Diffusion node&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The node runs an optimised multi-pass fragment shader pipeline on the graphics card, giving access to the full &lt;code&gt;Gray-Scott&lt;/code&gt; parameter space without requiring manual framebuffer setup or ping-pong buffer management.&lt;/p&gt;

&lt;p&gt;The node exposes several key controls:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;preset&lt;/code&gt;: quick access to canonical Morphogenesis regimes including Coral, Mitosis, Maze, Spots, Worms, and Holes.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;feed&lt;/code&gt;: the replenishment rate of substrate A (ranging from &lt;code&gt;0.01&lt;/code&gt; to &lt;code&gt;0.09&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;kill&lt;/code&gt;: the decay rate of catalyst B (ranging from &lt;code&gt;0.03&lt;/code&gt; to &lt;code&gt;0.08&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;diffuse A&lt;/code&gt;: spatial propagation speed of substrate A (default &lt;code&gt;1.0&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;diffuse B&lt;/code&gt;: spatial propagation speed of catalyst B (default &lt;code&gt;0.5&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;steps / frame&lt;/code&gt;: number of numerical substeps executed per video frame (ranging from &lt;code&gt;1&lt;/code&gt; to &lt;code&gt;32&lt;/code&gt;, defaulting to &lt;code&gt;8&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;source influence&lt;/code&gt;: blends incoming image or video frames directly into chemical concentrations, allowing live cameras or video clips to deposit catalyst B onto the grid.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When wired into an output chain, the scalar concentration of chemical B represents the biological pattern. By connecting the output of &lt;code&gt;Reaction Diffusion&lt;/code&gt; to a &lt;code&gt;Color Ramp&lt;/code&gt; node, artists can map the continuous chemical gradients onto rich palettes, from iridescent oceanic hues to high-contrast monochrome prints.&lt;/p&gt;

&lt;h2&gt;
  
  
  Writing custom reaction-diffusion in Field Pixel
&lt;/h2&gt;

&lt;p&gt;For artists and developers who require complete control over the mathematical formulation, Infinite includes &lt;strong&gt;Field&lt;/strong&gt;, a domain-specific kernel language that compiles directly to GLSL.&lt;/p&gt;

&lt;p&gt;Using a &lt;code&gt;Field Pixel&lt;/code&gt; node, you can write the full reaction-diffusion kernel in concise code. The &lt;code&gt;state&lt;/code&gt; keyword declares persistent frame-to-frame memory cells that automatically allocate ping-pong GPU textures under the hood.&lt;/p&gt;

&lt;p&gt;Here is a complete, self-contained &lt;code&gt;Gray-Scott&lt;/code&gt; reaction-diffusion kernel written in Field:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Field Pixel: Gray-Scott Reaction-Diffusion Kernel&lt;/span&gt;
&lt;span class="n"&gt;param&lt;/span&gt; &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;feed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mo"&gt;037&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mo"&gt;01&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;08&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;param&lt;/span&gt; &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;kill&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mo"&gt;060&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mo"&gt;03&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;08&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;param&lt;/span&gt; &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;diffA&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;  &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;param&lt;/span&gt; &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;diffB&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;  &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="c1"&gt;// Declare persistent chemical concentration buffers&lt;/span&gt;
&lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="n"&gt;vec2&lt;/span&gt; &lt;span class="n"&gt;chem&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;vec2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;// 1. Initialise small central seed perturbations&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;frame&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;vec2&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;uv&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;vec2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mo"&gt;002&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;chem&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;vec2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;chem&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;vec2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// 2. Sample 9-point Laplacian from previous frame state&lt;/span&gt;
    &lt;span class="n"&gt;vec2&lt;/span&gt; &lt;span class="n"&gt;texel&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;resolution&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="n"&gt;vec2&lt;/span&gt; &lt;span class="n"&gt;lap&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;chem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;lap&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;chem_prev&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uv&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;vec2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;texel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="n"&gt;lap&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;chem_prev&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uv&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;vec2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;texel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="n"&gt;lap&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;chem_prev&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uv&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;vec2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;texel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="n"&gt;lap&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;chem_prev&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uv&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;vec2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="n"&gt;texel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="n"&gt;lap&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mo"&gt;05&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;chem_prev&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uv&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;vec2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;texel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;texel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="n"&gt;lap&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mo"&gt;05&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;chem_prev&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uv&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;vec2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;texel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;texel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="n"&gt;lap&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mo"&gt;05&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;chem_prev&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uv&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;vec2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;texel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="n"&gt;texel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="n"&gt;lap&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mo"&gt;05&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;chem_prev&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uv&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;vec2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;texel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="n"&gt;texel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

    &lt;span class="c1"&gt;// 3. Evaluate non-linear reaction terms&lt;/span&gt;
    &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;chem&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;chem&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;reaction&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;da&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;diffA&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;lap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;reaction&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;feed&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;diffB&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;lap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;reaction&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;feed&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;kill&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// 4. Update concentrations and clamp within physical bounds&lt;/span&gt;
    &lt;span class="n"&gt;chem&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;clamp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;vec2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;da&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;vec2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;vec2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// 5. Output chemical B mapped to visual colour&lt;/span&gt;
&lt;span class="n"&gt;col&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;vec3&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;chem&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;chem&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;chem&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To explore more examples of shader development in Field, refer to the guide on &lt;a href="https://infinitedevices.org/blog/audio-reactive-glsl-shaders.html" rel="noopener noreferrer"&gt;audio-reactive GLSL shaders&lt;/a&gt; and the comprehensive &lt;a href="https://infinitedevices.org/assets/Field_Language_Manual.pdf" rel="noopener noreferrer"&gt;Field language manual&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Modulating feed and kill rates with live audio spectrum bins
&lt;/h2&gt;

&lt;p&gt;The most compelling aspect of running physical simulations in a unified audiovisual workstation is modulation. In Infinite, modulation is not an afterthought handled over slow network bridges: audio analysis, visual synthesis, and parameter controls share one lock-free evaluation graph.&lt;/p&gt;

&lt;p&gt;To build an audio-reactive reaction-diffusion system:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Insert an audio source, such as an &lt;code&gt;Oscillator&lt;/code&gt;, &lt;code&gt;Analog&lt;/code&gt; synth, or &lt;code&gt;Audio File&lt;/code&gt; node.&lt;/li&gt;
&lt;li&gt;Connect the audio signal to an &lt;code&gt;Audio Analyze&lt;/code&gt; node. The node splits the incoming sound into eight isolated frequency bands: sub-bass, bass, low-mid, mid, high-mid, presence, brilliance, and air.&lt;/li&gt;
&lt;li&gt;Patch the &lt;code&gt;sub-bass&lt;/code&gt; pin directly into the &lt;code&gt;feed&lt;/code&gt; parameter of the &lt;code&gt;Reaction Diffusion&lt;/code&gt; node. As heavy kick drums or bass notes trigger, the feed rate temporarily spikes upward. This floods the grid with fresh substrate A, stimulating aggressive outward branch growth and pattern expansion.&lt;/li&gt;
&lt;li&gt;Patch the &lt;code&gt;high-mid&lt;/code&gt; or &lt;code&gt;presence&lt;/code&gt; pin into the &lt;code&gt;kill&lt;/code&gt; parameter with an inverted modulation amount. When sharp snare hits or hi-hats land, the kill rate momentarily drops, allowing catalyst B to survive in regions where it would normally decay. This causes solid labyrinth ridges to fracture into clusters of dividing mitotic cells in step with the beat.&lt;/li&gt;
&lt;li&gt;Alternatively, patch the &lt;code&gt;Audio Analyze&lt;/code&gt; output into a &lt;code&gt;Noise&lt;/code&gt; node, and connect the resulting texture to the &lt;code&gt;input&lt;/code&gt; pin of &lt;code&gt;Reaction Diffusion&lt;/code&gt;. By setting &lt;code&gt;source influence&lt;/code&gt; to &lt;code&gt;0.2&lt;/code&gt;, transient acoustic energy injects localized bursts of catalyst directly onto the canvas, nucleating new self-replicating organisms at the sound of each musical event.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Mapping chemical concentrations to 3D surfaces and shaders
&lt;/h2&gt;

&lt;p&gt;Reaction-diffusion is not restricted to flat two-dimensional video planes. The chemical density field can serve as a procedural displacement map, roughness texture, or volumetric density function for three-dimensional geometry.&lt;/p&gt;

&lt;p&gt;In Infinite, you can wire the output of &lt;code&gt;Reaction Diffusion&lt;/code&gt; directly into the input of a &lt;code&gt;Displacement&lt;/code&gt; node. When applied to a high-density primitive such as a &lt;code&gt;Sphere&lt;/code&gt;, &lt;code&gt;Torus Knot&lt;/code&gt;, or subdivided &lt;code&gt;Plane&lt;/code&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The scalar concentration of chemical B drives vertex displacement along the surface normal vectors. Labyrinthine ridges rise out of the geometry like organic coral reefs or carved bone.&lt;/li&gt;
&lt;li&gt;The same texture is routed into a &lt;code&gt;Material&lt;/code&gt; node to control roughness and metallic sheen. Valleys where catalyst B is depleted remain glossy and smooth, while displaced ridges take on tactile matte finishes.&lt;/li&gt;
&lt;li&gt;Placing directional and point lights with subtle ambient occlusion transforms the abstract mathematical output into realistic, physical sculptures that appear to breathe and morph in real time.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;A selection of ready-to-use procedural patches and generative templates is available in the free &lt;a href="https://infinitedevices.org/library.html" rel="noopener noreferrer"&gt;Infinite Library&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Headless validation and batch rendering
&lt;/h2&gt;

&lt;p&gt;Because Infinite features a robust headless command-line interface, reaction-diffusion patches can be verified, inspected, and rendered to lossless ProRes or MP4 video without ever opening a graphical window.&lt;/p&gt;

&lt;p&gt;Here is a minimal, complete patch file defining an audio-reactive reaction-diffusion network. Save this plain text as &lt;code&gt;reaction_diffusion.inf&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;infinite-patch 1
rev 2
node 1 Source Audio File
  id audio
  s path "drums.wav"
end
node 2 DSP Audio Analyze
  id analyze
end
node 3 Compositing Reaction Diffusion
  id rd
  i preset 2
  f feed 0.037
  f kill 0.060
  i stepsPerFrame 8
end
node 4 Compositing Color Ramp
  id ramp
end
node 5 Utility Output
  id out
end
cable analyze 0 audio
cable rd 0 analyze
cable ramp 0 rd
cable out 0 ramp
mod rd feed analyze 0 0.01 0.08 0.4
mod rd kill analyze 4 0.04 0.07 -0.3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can validate the patch syntax and ensure all cable connections are strictly legal using the command line:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;Infinite &lt;span class="nt"&gt;--validate&lt;/span&gt; reaction_diffusion.inf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To render stills at specific time stamps and inspect the organic pattern evolution:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;Infinite &lt;span class="nt"&gt;--frame&lt;/span&gt; reaction_diffusion.inf 1.0,2.5,5.0 output/ &lt;span class="nt"&gt;--contact-sheet&lt;/span&gt; sheet.png
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To render the finished audiovisual composition to a video file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;Infinite &lt;span class="nt"&gt;--render&lt;/span&gt; reaction_diffusion.inf render.mp4 &lt;span class="nt"&gt;--duration&lt;/span&gt; 15.0 &lt;span class="nt"&gt;--fps&lt;/span&gt; 60
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Detailed instructions on command-line flags, render automation, and CI integration can be found in the &lt;a href="https://infinitedevices.org/assets/Infinite_Headless_User_Guide.pdf" rel="noopener noreferrer"&gt;Headless User Guide&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;By uniting non-linear differential equations, GPU fragment pipelines, and zero-latency audio modulation, reaction-diffusion in Infinite turns abstract biochemical morphogenesis into an expressive, interactive instrument for generative art.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://infinitedevices.org/blog/reaction-diffusion-simulation-in-real-time-glsl.html" rel="noopener noreferrer"&gt;https://infinitedevices.org/blog/reaction-diffusion-simulation-in-real-time-glsl.html&lt;/a&gt;. Infinite is a free, open-source DAW for visuals, music and code: &lt;a href="https://infinitedevices.org" rel="noopener noreferrer"&gt;infinitedevices.org&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>reactiondiffusion</category>
      <category>glslshaders</category>
      <category>creativecoding</category>
      <category>generativeart</category>
    </item>
    <item>
      <title>Real-time fluid simulation in GLSL: Navier-Stokes and dye advection</title>
      <dc:creator>naman</dc:creator>
      <pubDate>Thu, 29 Oct 2026 09:12:52 +0000</pubDate>
      <link>https://dev.to/n1m21n/real-time-fluid-simulation-in-glsl-navier-stokes-and-dye-advection-2agp</link>
      <guid>https://dev.to/n1m21n/real-time-fluid-simulation-in-glsl-navier-stokes-and-dye-advection-2agp</guid>
      <description>&lt;p&gt;Implementing real-time fluid simulation in GLSL provides creative coders and visual artists with an organic medium for live performance, interactive installations, and audiovisual synthesis. Unlike particle-based systems or static procedural distortions, a Navier-Stokes fluid solver models the conservation of mass and momentum across a continuous vector field. When applied to visual media, live video feeds and generative graphics become dynamic dyes that swirl, fold, and disperse according to physical laws.&lt;/p&gt;

&lt;p&gt;In real-time audiovisual software such as &lt;a href="https://infinitedevices.org/" rel="noopener noreferrer"&gt;Infinite&lt;/a&gt;, fluid dynamics can be driven directly by incoming sound and camera motion. Because audio frequency bands and optical flow vectors can be mapped to velocity injection points, the fluid reacts with zero perceptible delay to live musical performance.&lt;/p&gt;

&lt;p&gt;This guide walks through the complete mathematical and architectural implementation of an Eulerian fluid solver on the GPU: the staggered Marker-and-Cell (MAC) grid layout, unconditionally stable semi-Lagrangian advection, geometric multigrid Poisson solvers for incompressibility, vorticity confinement for preserving turbulence, and live audio-reactive modulation.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fone086u1c50m8c4un7lk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fone086u1c50m8c4un7lk.png" alt="Real-time fluid simulation in GLSL diagram showing velocity advection, pressure Poisson solve, vorticity confinement, and audio-reactive dye mixing" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What is real-time fluid simulation in GLSL
&lt;/h2&gt;

&lt;p&gt;Computer graphics divides fluid simulation into two primary paradigms: Lagrangian and Eulerian.&lt;/p&gt;

&lt;p&gt;The Lagrangian approach treats the fluid as a discrete collection of moving particles, commonly implemented via Smoothed Particle Hydrodynamics (SPH). Each particle carries its own position, velocity, and mass. While intuitive, particle methods require expensive spatial hashing and neighbour search routines on the GPU, making high-resolution simulations computationally heavy.&lt;/p&gt;

&lt;p&gt;The Eulerian approach fixes the coordinate frame in space and observes fluid quantities flowing through a stationary grid of cells. Each cell tracks local velocity, pressure, and passive dye concentration. Because GPU fragment shaders and framebuffers operate natively on two-dimensional pixel grids, the Eulerian formulation maps directly to hardware textures:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Velocity field: a two-component floating-point texture storing horizontal velocity &lt;code&gt;u&lt;/code&gt; and vertical velocity &lt;code&gt;v&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Pressure field: a single-component scalar texture storing local hydrostatic pressure &lt;code&gt;p&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Dye field: an RGBA colour texture storing graphic media, video, or synthetic pigmentation carried passively by the flow.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;By executing successive rendering passes across offscreen framebuffer objects (FBOs), the graphics card computes each phase of the fluid equations in parallel for millions of cells at sixty frames per second.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Navier-Stokes equations and grid discretisation
&lt;/h2&gt;

&lt;p&gt;Incompressible fluid flow is governed by the Navier-Stokes equations:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;∂u/∂t = -(u · ∇)u - (1/ρ)∇p + ν∇²u + f
∇ · u = 0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;u&lt;/code&gt; is the velocity vector field &lt;code&gt;(u, v)&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-(u · ∇)u&lt;/code&gt; represents advection, the transport of velocity along itself.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-(1/ρ)∇p&lt;/code&gt; is the pressure gradient force that accelerates fluid from high to low pressure regions.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ν∇²u&lt;/code&gt; accounts for kinematic viscosity, causing momentum to diffuse across adjacent layers.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;f&lt;/code&gt; denotes external body forces, such as gravity, user mouse stirrers, or audio impulses.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;∇ · u = 0&lt;/code&gt; enforces incompressibility, meaning the volume of any parcel of fluid remains strictly constant over time.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Solving these partial differential equations on a discrete grid requires careful cell alignment. In a naive collocated grid, both velocity components &lt;code&gt;(u, v)&lt;/code&gt; and pressure &lt;code&gt;p&lt;/code&gt; are stored at the exact centre of each cell. When central differences are computed to evaluate pressure gradients and velocity divergence, adjacent cells skip their immediate neighbours:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;∂p/∂x ≈ (p[i+1, j] - p[i-1, j]) / (2 * Δx)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This causes an odd-even decoupling known as the checkerboard instability, where high-frequency oscillatory pressure fields register a false divergence of zero.&lt;/p&gt;

&lt;p&gt;To eliminate this artifact without artificial damping, production solvers employ a staggered Marker-and-Cell (MAC) grid layout:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The horizontal velocity component &lt;code&gt;u&lt;/code&gt; is stored on the vertical cell faces between cell &lt;code&gt;(i-1, j)&lt;/code&gt; and &lt;code&gt;(i, j)&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The vertical velocity component &lt;code&gt;v&lt;/code&gt; is stored on the horizontal cell faces between cell &lt;code&gt;(i, j-1)&lt;/code&gt; and &lt;code&gt;(i, j)&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The pressure &lt;code&gt;p&lt;/code&gt; and passive dye &lt;code&gt;c&lt;/code&gt; are stored at the geometric centre of cell &lt;code&gt;(i, j)&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;On a staggered grid, divergence is evaluated across immediate face values:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;div[i, j] = (u_face[i+1, j] - u_face[i, j]) / Δx + (v_face[i, j+1] - v_face[i, j]) / Δy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Every face velocity couples directly to the pressure of the two cells sharing that face. The resulting discretisation guarantees that when the pressure Poisson equation converges, the velocity field leaves zero divergence behind.&lt;/p&gt;

&lt;h2&gt;
  
  
  Semi-Lagrangian advection and velocity transport
&lt;/h2&gt;

&lt;p&gt;Advection describes how moving fluid transports both external properties (such as colour and temperature) and its own velocity. Standard explicit finite-difference schemes suffer from the Courant-Friedrichs-Lewy (CFL) stability condition: if the fluid velocity multiplied by the time step exceeds the cell width (&lt;code&gt;|u| * Δt &amp;gt; Δx&lt;/code&gt;), the numerical scheme explodes into floating-point infinities.&lt;/p&gt;

&lt;p&gt;In 1999, Jos Stam introduced unconditionally stable semi-Lagrangian advection to computer graphics. Rather than asking where a parcel of fluid will travel in the future, semi-Lagrangian advection looks backward in time.&lt;/p&gt;

&lt;p&gt;For every grid cell &lt;code&gt;x&lt;/code&gt;, the solver traces a virtual particle backward along the current velocity field to determine its origin point &lt;code&gt;x_prev&lt;/code&gt; at the previous time step:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;x_prev = x - u(x) * Δt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The new value at cell &lt;code&gt;x&lt;/code&gt; is then sampled from the previous state at position &lt;code&gt;x_prev&lt;/code&gt; using bilinear interpolation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight glsl"&gt;&lt;code&gt;&lt;span class="c1"&gt;// GLSL fragment shader for semi-Lagrangian advection&lt;/span&gt;
&lt;span class="cp"&gt;#version 150
&lt;/span&gt;
&lt;span class="k"&gt;uniform&lt;/span&gt; &lt;span class="kt"&gt;sampler2D&lt;/span&gt; &lt;span class="n"&gt;uVelocity&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;uniform&lt;/span&gt; &lt;span class="kt"&gt;sampler2D&lt;/span&gt; &lt;span class="n"&gt;uSource&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;uniform&lt;/span&gt; &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;uDeltaTime&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;uniform&lt;/span&gt; &lt;span class="kt"&gt;vec2&lt;/span&gt; &lt;span class="n"&gt;uTexelSize&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="kt"&gt;vec2&lt;/span&gt; &lt;span class="n"&gt;vUv&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;out&lt;/span&gt; &lt;span class="kt"&gt;vec4&lt;/span&gt; &lt;span class="n"&gt;fragColor&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Sample the current velocity at this location&lt;/span&gt;
    &lt;span class="kt"&gt;vec2&lt;/span&gt; &lt;span class="n"&gt;vel&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;texture&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uVelocity&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;vUv&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;xy&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// Backtrack along the velocity vector&lt;/span&gt;
    &lt;span class="kt"&gt;vec2&lt;/span&gt; &lt;span class="n"&gt;prevPos&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;vUv&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;vel&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;uDeltaTime&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;uTexelSize&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// Sample the transported quantity with bilinear hardware filtering&lt;/span&gt;
    &lt;span class="n"&gt;fragColor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;texture&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uSource&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;prevPos&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Because bilinear texture sampling on modern graphics hardware is executed directly inside fixed-function texture units, semi-Lagrangian advection runs with minimal shader cost. Even under extreme velocities and large time steps, the algorithm cannot diverge, as the interpolated value is always bounded by the minimum and maximum values of the surrounding texels.&lt;/p&gt;

&lt;p&gt;The inherent trade-off of semi-Lagrangian advection is numerical dissipation. Repeated bilinear interpolation acts as an unintended low-pass filter, gradually smoothing out sharp velocity gradients and subtle eddies over time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Making the flow divergence-free with pressure projection
&lt;/h2&gt;

&lt;p&gt;After advection and the application of external forces, the provisional velocity field &lt;code&gt;w&lt;/code&gt; is generally divergent (&lt;code&gt;∇ · w ≠ 0&lt;/code&gt;). Compressible fluid would bunch up or create vacuums; an incompressible liquid must satisfy &lt;code&gt;∇ · u = 0&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The Helmholtz-Hodge decomposition theorem states that any smooth vector field &lt;code&gt;w&lt;/code&gt; can be uniquely resolved into the sum of a divergence-free vector field &lt;code&gt;u&lt;/code&gt; and the gradient of a scalar potential &lt;code&gt;p&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;w = u + ∇p
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Taking the divergence of both sides yields the Poisson equation for pressure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;∇ · w = ∇ · u + ∇²p
∇²p = ∇ · w    (since ∇ · u = 0)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once the scalar pressure field &lt;code&gt;p&lt;/code&gt; is obtained by solving this Poisson system, the final divergence-free velocity field is calculated by subtracting the pressure gradient:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;u = w - ∇p
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Multigrid V-cycles versus standard Jacobi relaxation
&lt;/h3&gt;

&lt;p&gt;On a discrete two-dimensional grid, the Laplacian operator &lt;code&gt;∇²p&lt;/code&gt; is approximated by a five-point stencil:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;(p[i+1, j] + p[i-1, j] + p[i, j+1] + p[i, j-1] - 4 * p[i, j]) / (Δx²) = div[i, j]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Rearranging this formula yields the standard Jacobi relaxation step:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;p_new[i, j] = 0.25 * (p[i+1, j] + p[i-1, j] + p[i, j+1] + p[i, j-1] - Δx² * div[i, j])
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Simple Jacobi iteration dampens high-frequency error quickly, but eliminates low-frequency, long-wavelength pressure differences very slowly. Resolving pressure across a 1920x1080 grid using Jacobi relaxation alone requires between 80 and 150 render passes per frame, which places severe strain on GPU memory bandwidth.&lt;/p&gt;

&lt;p&gt;Infinite solves this bottleneck using a geometric multigrid V-cycle solver across five hierarchical grid levels (&lt;code&gt;kMaxLevels = 5&lt;/code&gt;):&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Pre-smoothing: two Jacobi relaxation passes are performed on the finest simulation grid (Level 0).&lt;/li&gt;
&lt;li&gt;Residual calculation: the remaining error &lt;code&gt;r = div - ∇²p&lt;/code&gt; is computed.&lt;/li&gt;
&lt;li&gt;Restriction: the residual and obstacle masks are downsampled to a half-resolution grid (Level 1).&lt;/li&gt;
&lt;li&gt;Recursive descent: this restriction repeats down through Level 4, where the entire screen is represented by a coarse 120x68 grid.&lt;/li&gt;
&lt;li&gt;Coarse solve: at the lowest level, long-wavelength pressure modes span only a handful of pixels, allowing ten Jacobi iterations to propagate pressure across the entire domain.&lt;/li&gt;
&lt;li&gt;Prolongation: the coarse correction is bilinearly upsampled, added back to the finer level, and followed by two post-smoothing Jacobi passes.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;A single five-level multigrid V-cycle with twenty total iterations achieves tighter divergence-free convergence than 120 brute-force Jacobi iterations, leaving ample GPU headroom for real-time video compositing and audio DSP.&lt;/p&gt;

&lt;h2&gt;
  
  
  Preserving turbulence with vorticity confinement
&lt;/h2&gt;

&lt;p&gt;Because semi-Lagrangian advection introduces numerical dissipation, fine vortices and turbulent swirls tend to decay quickly. In creative coding and visual effects, this loss of rotational energy makes fluids look like thick syrup rather than water or air.&lt;/p&gt;

&lt;p&gt;To restore this lost turbulence without destabilising the solver, Infinite employs vorticity confinement, originally formulated by Steinhoff and Underhill and adapted for graphics by Ronald Fedkiw.&lt;/p&gt;

&lt;p&gt;Vorticity measures the local rotation or spin of the fluid:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ω = ∇ × u = (∂v/∂x - ∂u/∂y)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In two dimensions, vorticity is a scalar quantity. The gradient of the absolute vorticity points toward the centre of local vortices:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;η = ∇|ω| / (|∇|ω| + 1e-5)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The normal vector &lt;code&gt;η&lt;/code&gt; is perpendicular to the vortex axis. The confinement force is calculated as the cross product of &lt;code&gt;η&lt;/code&gt; and the vorticity vector:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;f_vort = ε * (η × ω) * Δx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In GLSL, this evaluates to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight glsl"&gt;&lt;code&gt;&lt;span class="c1"&gt;// GLSL fragment shader for vorticity confinement&lt;/span&gt;
&lt;span class="cp"&gt;#version 150
&lt;/span&gt;
&lt;span class="k"&gt;uniform&lt;/span&gt; &lt;span class="kt"&gt;sampler2D&lt;/span&gt; &lt;span class="n"&gt;uVelocity&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;uniform&lt;/span&gt; &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;uVorticityStrength&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;uniform&lt;/span&gt; &lt;span class="kt"&gt;vec2&lt;/span&gt; &lt;span class="n"&gt;uTexelSize&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="kt"&gt;vec2&lt;/span&gt; &lt;span class="n"&gt;vUv&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;out&lt;/span&gt; &lt;span class="kt"&gt;vec4&lt;/span&gt; &lt;span class="n"&gt;fragColor&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Compute local curl (vorticity)&lt;/span&gt;
    &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;uT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;texture&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uVelocity&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;vUv&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="kt"&gt;vec2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;uTexelSize&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;uB&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;texture&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uVelocity&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;vUv&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="kt"&gt;vec2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;uTexelSize&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;vR&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;texture&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uVelocity&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;vUv&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="kt"&gt;vec2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uTexelSize&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;vL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;texture&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uVelocity&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;vUv&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="kt"&gt;vec2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uTexelSize&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;curl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;vR&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;vL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uT&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;uB&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

    &lt;span class="c1"&gt;// Sample curl magnitude in neighbouring cells&lt;/span&gt;
    &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;cT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;abs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;texture&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uVelocity&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;vUv&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="kt"&gt;vec2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;uTexelSize&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="n"&gt;z&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;cB&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;abs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;texture&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uVelocity&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;vUv&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="kt"&gt;vec2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;uTexelSize&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="n"&gt;z&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;cR&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;abs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;texture&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uVelocity&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;vUv&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="kt"&gt;vec2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uTexelSize&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="n"&gt;z&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;cL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;abs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;texture&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uVelocity&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;vUv&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="kt"&gt;vec2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uTexelSize&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="n"&gt;z&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Find the gradient of curl magnitude&lt;/span&gt;
    &lt;span class="kt"&gt;vec2&lt;/span&gt; &lt;span class="n"&gt;eta&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="kt"&gt;vec2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cR&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;cL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cT&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;cB&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;len&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;eta&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;len&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mf"&gt;1e-5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;fragColor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;vec4&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;eta&lt;/span&gt; &lt;span class="o"&gt;/=&lt;/span&gt; &lt;span class="n"&gt;len&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// Confinement force: F = epsilon * (eta_y, -eta_x) * curl&lt;/span&gt;
    &lt;span class="kt"&gt;vec2&lt;/span&gt; &lt;span class="n"&gt;force&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;uVorticityStrength&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="kt"&gt;vec2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;eta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;eta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;curl&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;fragColor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;vec4&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;force&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;curl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Applying this corrective force before the pressure projection step injects angular momentum back into emerging eddies. Fine rotational details remain crisp and swirling indefinitely without causing instability.&lt;/p&gt;

&lt;h2&gt;
  
  
  Solid boundaries and obstacle interaction
&lt;/h2&gt;

&lt;p&gt;To allow fluid to flow naturally around visual elements, text, or logos, the solver must handle solid obstacles.&lt;/p&gt;

&lt;p&gt;In Infinite, obstacles are provided as a single-channel luminance texture where bright pixels represent solid barriers. Two physical boundary conditions must be satisfied at obstacle surfaces:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;No-penetration condition: fluid cannot flow through a solid wall. The velocity normal to the wall must be zero (&lt;code&gt;u · n = 0&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Free-slip or no-slip tangential condition: for low-viscosity aesthetic fluids, free-slip boundaries (where tangential velocity slides unhindered) produce clean, non-sticky circulation.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In the staggered MAC grid, wall boundaries are enforced during the divergence and pressure solve passes. When evaluating the divergence of cell &lt;code&gt;(i, j)&lt;/code&gt;, any face touching a solid cell or the outer boundary of the texture is flagged as a wall:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight glsl"&gt;&lt;code&gt;&lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="nf"&gt;solidAt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;sampler2D&lt;/span&gt; &lt;span class="n"&gt;obs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;ivec2&lt;/span&gt; &lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;ivec2&lt;/span&gt; &lt;span class="n"&gt;sz&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="n"&gt;sz&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="n"&gt;sz&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;texelFetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;obs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="nf"&gt;faceU&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;sampler2D&lt;/span&gt; &lt;span class="n"&gt;vt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;sampler2D&lt;/span&gt; &lt;span class="n"&gt;obs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;ivec2&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;ivec2&lt;/span&gt; &lt;span class="n"&gt;sz&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;wall&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;solidAt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;obs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sz&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="n"&gt;solidAt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;obs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="kt"&gt;ivec2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;sz&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;wall&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;texelFetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;vt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the pressure solve, the pressure gradient across a solid face is set to zero (&lt;code&gt;∂p/∂n = 0&lt;/code&gt;), ensuring that the projection pass does not reintroduce flow into solid barriers. The fluid cleanly wraps around obstacle contours, creating realistic wake patterns and stagnation points.&lt;/p&gt;

&lt;h2&gt;
  
  
  Audio-reactive forces and optical flow injection in Infinite
&lt;/h2&gt;

&lt;p&gt;A fluid simulation becomes truly compelling in creative performance when connected to sound and real-time motion.&lt;/p&gt;

&lt;p&gt;In Infinite, the node canvas combines audio synthesis, DSP analysis, 3D graphics, and 2D GLSL compositing within a single executable timeline. The &lt;code&gt;Fluid&lt;/code&gt; node exposes three primary inputs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;image&lt;/code&gt;: the passive dye carried by the flow. Video clips, generative &lt;a href="https://infinitedevices.org/blog/audio-reactive-glsl-shaders.html" rel="noopener noreferrer"&gt;Shader&lt;/a&gt; nodes, or live webcam streams can be cabled here.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;force&lt;/code&gt;: a two-component velocity vector field that stirs the fluid each frame.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;obstacles&lt;/code&gt;: an image mask defining impenetrable solid surfaces.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Coupling with the Optical Flow node
&lt;/h3&gt;

&lt;p&gt;One of the most expressive ways to drive the fluid is through the &lt;code&gt;Optical Flow&lt;/code&gt; node. Based on pyramidal Lucas-Kanade feature tracking (Bouguet 2001), &lt;code&gt;Optical Flow&lt;/code&gt; computes the instantaneous motion between consecutive video frames across multiple resolution levels.&lt;/p&gt;

&lt;p&gt;When set to raw output mode, &lt;code&gt;Optical Flow&lt;/code&gt; writes horizontal motion into the red channel and vertical motion into the green channel as floating-point pixels per frame. Cabled into the &lt;code&gt;force&lt;/code&gt; pin of the &lt;code&gt;Fluid&lt;/code&gt; node, dancer movements, camera gestures, or animated geometric shapes physically push and stir the fluid dye with zero manual calibration.&lt;/p&gt;

&lt;h3&gt;
  
  
  Modulating fluid physics with audio analysis
&lt;/h3&gt;

&lt;p&gt;To synchronise fluid dynamics with electronic music, audio frequency content is extracted via the &lt;code&gt;Audio Analyze&lt;/code&gt; node:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[Audio In / Synth] ---&amp;gt; [Audio Analyze (8-Band FFT)]
                             |
                             +---&amp;gt; band 0 (sub-bass) ---&amp;gt; [Fluid].forceGain
                             |
                             +---&amp;gt; band 3 (snare/mid) ---&amp;gt; [Fluid].vorticity
                             |
                             +---&amp;gt; band 7 (high hat)  ---&amp;gt; [Fluid].stirrerStrength
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Sub-bass punch: cabling the lowest FFT band into &lt;code&gt;forceGain&lt;/code&gt; amplifies the velocity response on kick drum transients, causing sudden outward explosive bursts.&lt;/li&gt;
&lt;li&gt;Vorticity modulation: connecting the snare or mid-frequency transient band to &lt;code&gt;vorticity&lt;/code&gt; triggers intricate curling smoke patterns on snare hits, which relax back into smooth laminar flow during quiet passages.&lt;/li&gt;
&lt;li&gt;Built-in stirrer automation: the &lt;code&gt;Fluid&lt;/code&gt; node includes built-in rotational stirrers (&lt;code&gt;Orbit&lt;/code&gt;, &lt;code&gt;Pulse&lt;/code&gt;, &lt;code&gt;Spin&lt;/code&gt;). By modulating &lt;code&gt;stirrerStrength&lt;/code&gt; with a tempo-synced &lt;code&gt;LFO&lt;/code&gt; or &lt;code&gt;Envelope&lt;/code&gt; node, the entire fluid volume sustains an organic ambient circulation even when external forces pause.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Because Infinite computes parameter modulation, audio DSP, and GPU frame rendering synchronously within the same tick loop, there is zero buffer latency between audio peaks and graphical reaction.&lt;/p&gt;

&lt;h2&gt;
  
  
  Building the real-time node network in Infinite
&lt;/h2&gt;

&lt;p&gt;Setting up this audiovisual pipeline in Infinite requires five nodes cabled together on the canvas:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Add a &lt;code&gt;Video&lt;/code&gt; or &lt;code&gt;Shape&lt;/code&gt; node to provide visual content. Connect its output to the &lt;code&gt;image&lt;/code&gt; pin of a &lt;code&gt;Fluid&lt;/code&gt; node.&lt;/li&gt;
&lt;li&gt;Add a &lt;code&gt;Video In&lt;/code&gt; node receiving a live camera stream. Cable its output into an &lt;code&gt;Optical Flow&lt;/code&gt; node.&lt;/li&gt;
&lt;li&gt;Set &lt;code&gt;Optical Flow&lt;/code&gt; parameter &lt;code&gt;view&lt;/code&gt; to &lt;code&gt;0&lt;/code&gt; (Raw motion vectors) and cable its output into the &lt;code&gt;force&lt;/code&gt; pin of &lt;code&gt;Fluid&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Add an &lt;code&gt;Audio In&lt;/code&gt; node patched into an &lt;code&gt;Audio Analyze&lt;/code&gt; node.&lt;/li&gt;
&lt;li&gt;In the modulation matrix or by dragging modulation cables:

&lt;ul&gt;
&lt;li&gt;Map FFT Band 0 (sub-bass) to &lt;code&gt;Fluid&lt;/code&gt; parameter &lt;code&gt;forceGain&lt;/code&gt; (range &lt;code&gt;0.5&lt;/code&gt; to &lt;code&gt;3.0&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Map FFT Band 2 (low-mids) to &lt;code&gt;Fluid&lt;/code&gt; parameter &lt;code&gt;vorticity&lt;/code&gt; (range &lt;code&gt;0.1&lt;/code&gt; to &lt;code&gt;0.6&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Map an &lt;code&gt;LFO&lt;/code&gt; node running at a 1/2-bar division to &lt;code&gt;Fluid&lt;/code&gt; parameter &lt;code&gt;stirrerStrength&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Add an &lt;code&gt;Output&lt;/code&gt; node and connect &lt;code&gt;Fluid&lt;/code&gt;'s output to project the final rendered artwork.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;To view alternative internal states during rehearsal, the &lt;code&gt;Fluid&lt;/code&gt; node's &lt;code&gt;view&lt;/code&gt; parameter allows switching the display from &lt;code&gt;Dye&lt;/code&gt; to &lt;code&gt;Velocity&lt;/code&gt; (visualised as colour hue and brightness), &lt;code&gt;Pressure&lt;/code&gt; gradients, or &lt;code&gt;Obstacles&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The resulting patch and dozens of related creative coding templates are available to explore in the &lt;a href="https://infinitedevices.org/library.html" rel="noopener noreferrer"&gt;Infinite patch library&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Honest technical limits and GPU performance
&lt;/h2&gt;

&lt;p&gt;While real-time Eulerian fluid simulation in GLSL produces striking visuals, practical production environments have distinct constraints:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Memory bandwidth and fillrate: Eulerian simulations are memory-bandwidth bound. A full-resolution 4K (3840x2160) grid requires reading and writing tens of gigabytes per second across multiple FBO passes. In practice, setting the &lt;code&gt;resolution&lt;/code&gt; parameter to &lt;code&gt;1&lt;/code&gt; (half-resolution simulation grid) allows the velocity and pressure solves to run at 960x540 while the passive dye advection pass remains at full 1080p, preserving sharp visual edges while cutting GPU compute cost by 75 percent.&lt;/li&gt;
&lt;li&gt;Two-dimensional planar flow: A 2D simulation does not account for vortex stretching, a three-dimensional physical phenomenon responsible for the energy cascade from large eddies down to microscopic scales. While 2D fluids produce convincing swirling sheets and marbling effects, they cannot simulate three-dimensional smoke plumes or tumbling spherical vortices.&lt;/li&gt;
&lt;li&gt;Incompressible assumption: The solver assumes the medium has uniform, constant density. Sound waves (acoustic compression waves) do not propagate through the simulated fluid itself. The audio reactivity described here is achieved by external parametric coupling rather than physical acoustic simulation.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Summary and patch architecture
&lt;/h2&gt;

&lt;p&gt;Real-time fluid simulation in GLSL transforms standard video feeds and generative graphics into dynamic, physics-based audiovisual instruments.&lt;/p&gt;

&lt;p&gt;By combining the staggered MAC grid layout with unconditionally stable semi-Lagrangian advection, geometric multigrid Poisson projection, and vorticity confinement, high-resolution fluid dynamics can run smoothly at sixty frames per second on modern hardware. When modulated by live optical flow vectors and audio frequency analysis, the fluid responds organically to music and motion with zero latency.&lt;/p&gt;

&lt;p&gt;To experiment with native fluid dynamics, real-time shaders, and modular sound design, download &lt;a href="https://infinitedevices.org/" rel="noopener noreferrer"&gt;Infinite&lt;/a&gt; and explore our detailed guides on &lt;a href="https://infinitedevices.org/blog/raymarching-signed-distance-fields-in-real-time-glsl.html" rel="noopener noreferrer"&gt;raymarching signed distance fields&lt;/a&gt; and &lt;a href="https://infinitedevices.org/blog/audio-reactive-glsl-shaders.html" rel="noopener noreferrer"&gt;audio-reactive GLSL shaders&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://infinitedevices.org/blog/real-time-fluid-simulation-in-glsl.html" rel="noopener noreferrer"&gt;https://infinitedevices.org/blog/real-time-fluid-simulation-in-glsl.html&lt;/a&gt;. Infinite is a free, open-source DAW for visuals, music and code: &lt;a href="https://infinitedevices.org" rel="noopener noreferrer"&gt;infinitedevices.org&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>fluidsimulation</category>
      <category>glslshaders</category>
      <category>navierstokes</category>
      <category>creativecoding</category>
    </item>
    <item>
      <title>Raymarching signed distance fields in real-time GLSL</title>
      <dc:creator>naman</dc:creator>
      <pubDate>Thu, 29 Oct 2026 09:12:45 +0000</pubDate>
      <link>https://dev.to/n1m21n/raymarching-signed-distance-fields-in-real-time-glsl-5jc</link>
      <guid>https://dev.to/n1m21n/raymarching-signed-distance-fields-in-real-time-glsl-5jc</guid>
      <description>&lt;p&gt;Building a system for raymarching signed distance fields in real-time GLSL provides a powerful alternative to traditional polygonal rasterisation. While standard 3D rendering pipelines rely on vertex buffers, index arrays, and triangle meshes, raymarching computes three-dimensional surfaces procedurally inside a fragment shader. Every geometric volume, smooth Boolean blend, and fractal surface is evaluated mathematically for every individual pixel on the screen.&lt;/p&gt;

&lt;p&gt;In modern audiovisual software such as &lt;a href="https://infinitedevices.org/" rel="noopener noreferrer"&gt;Infinite&lt;/a&gt;, raymarching allows visual artists and audio producers to bridge the gap between mathematical graphics and low-latency audio synthesis. Because signed distance fields are defined purely through mathematical equations, parameters such as scale, repetition, twisting, and morphing can be cabled directly to live audio frequency bands, envelope followers, and LFO modulators without regenerating vertex buffers or stalling the graphics pipeline.&lt;/p&gt;

&lt;p&gt;Here is an architectural walkthrough of how sphere tracing works, how to construct signed distance functions (SDFs) for common 3D primitives, how to blend geometry organically with polynomial smooth minimums, and how to wire a complete audio-reactive raymarching pipeline inside Infinite.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9s7awdqdfehd7au4tr57.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9s7awdqdfehd7au4tr57.png" alt="Raymarching signed distance fields diagram showing sphere tracing steps, primitive distance functions, polynomial smooth min blending, and lighting normals" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What is sphere tracing and how the ray steps
&lt;/h2&gt;

&lt;p&gt;Traditional raymarching steps through 3D space along a view ray using small, uniform increments. While simple to implement, uniform stepping suffers from severe trade-offs: if the step size is too large, the ray can skip thin geometry entirely, producing visual holes and aliasing artifacts; if the step size is too small, performance drops precipitously.&lt;/p&gt;

&lt;p&gt;Sphere tracing, introduced by John C. Hart in 1996, solves this inefficiency by exploiting the fundamental mathematical property of a signed distance field.&lt;/p&gt;

&lt;p&gt;A signed distance function &lt;code&gt;f(p)&lt;/code&gt; takes any point &lt;code&gt;p&lt;/code&gt; in three-dimensional space and returns the shortest Euclidean distance from that point to the nearest surface in the scene:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;f(p) &amp;gt; 0  : The point p is located outside the object.
f(p) = 0  : The point p lies exactly on the boundary surface.
f(p) &amp;lt; 0  : The point p is located inside the object.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Because &lt;code&gt;f(p)&lt;/code&gt; yields the absolute minimum distance to the closest boundary, a sphere of radius &lt;code&gt;R = f(p)&lt;/code&gt; centred at &lt;code&gt;p&lt;/code&gt; is guaranteed to be completely empty of any geometry. Therefore, a view ray starting at &lt;code&gt;p&lt;/code&gt; can safely advance along its direction vector by the full distance &lt;code&gt;R&lt;/code&gt; in a single step without any risk of overshooting or penetrating a surface.&lt;/p&gt;

&lt;p&gt;To construct the view ray for each pixel, we map normalised screen coordinates &lt;code&gt;uv&lt;/code&gt; into a camera origin &lt;code&gt;ro&lt;/code&gt; and a normalised direction vector &lt;code&gt;rd&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight glsl"&gt;&lt;code&gt;&lt;span class="kt"&gt;vec3&lt;/span&gt; &lt;span class="nf"&gt;rayDirection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;vec2&lt;/span&gt; &lt;span class="n"&gt;uv&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;vec3&lt;/span&gt; &lt;span class="n"&gt;eye&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;vec3&lt;/span&gt; &lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;fov&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;vec3&lt;/span&gt; &lt;span class="n"&gt;forward&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;normalize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;target&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;eye&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kt"&gt;vec3&lt;/span&gt; &lt;span class="n"&gt;right&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;normalize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cross&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;forward&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;vec3&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)));&lt;/span&gt;
    &lt;span class="kt"&gt;vec3&lt;/span&gt; &lt;span class="n"&gt;up&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cross&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;forward&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;normalize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;right&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;uv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;up&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;forward&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;fov&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With the ray direction established, the sphere tracing loop evaluates the scene's signed distance function iteratively:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight glsl"&gt;&lt;code&gt;&lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="nf"&gt;raymarch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;vec3&lt;/span&gt; &lt;span class="n"&gt;ro&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;vec3&lt;/span&gt; &lt;span class="n"&gt;rd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;minDistance&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;maxDistance&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;distanceTravelled&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;minDistance&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;step&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;step&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;128&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;step&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;vec3&lt;/span&gt; &lt;span class="n"&gt;currentPosition&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ro&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;rd&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;distanceTravelled&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;distanceToSurface&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;currentPosition&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="c1"&gt;// Surface hit detected within threshold epsilon&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;distanceToSurface&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mo"&gt;001&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;distanceTravelled&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="n"&gt;distanceTravelled&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;distanceToSurface&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="c1"&gt;// Ray escaped into empty background&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;distanceTravelled&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="n"&gt;maxDistance&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Miss&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice how this algorithm naturally adapts to the spatial complexity of the scene: in vast regions of open space, the distance to the nearest surface is large, allowing the ray to take massive strides across thousands of units in a handful of steps. Near surfaces and delicate geometric silhouettes, the steps automatically shrink to sub-millimetre precision, capturing razor-sharp edges.&lt;/p&gt;

&lt;h2&gt;
  
  
  Primary SDF geometric primitives
&lt;/h2&gt;

&lt;p&gt;Every scene evaluated in a raymarcher is described by an overall distance function, typically named &lt;code&gt;map(vec3 p)&lt;/code&gt;. Complex scenes are constructed by combining simple mathematical primitives.&lt;/p&gt;

&lt;p&gt;Here are the canonical signed distance functions for fundamental 3D solids:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Sphere
&lt;/h3&gt;

&lt;p&gt;The sphere is the simplest primitive in distance field mathematics. The distance from point &lt;code&gt;p&lt;/code&gt; to the surface of a sphere centred at the origin with radius &lt;code&gt;r&lt;/code&gt; equals the Euclidean length of &lt;code&gt;p&lt;/code&gt; minus &lt;code&gt;r&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight glsl"&gt;&lt;code&gt;&lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="nf"&gt;sdSphere&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;vec3&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Box
&lt;/h3&gt;

&lt;p&gt;An axis-aligned box with half-dimensions &lt;code&gt;b&lt;/code&gt; requires computing the component-wise distance outside the boundary and combining it with the internal signed distance:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight glsl"&gt;&lt;code&gt;&lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="nf"&gt;sdBox&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;vec3&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;vec3&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;vec3&lt;/span&gt; &lt;span class="n"&gt;q&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;abs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;z&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Torus
&lt;/h3&gt;

&lt;p&gt;A torus lying on the XZ plane with major radius &lt;code&gt;t.x&lt;/code&gt; and minor tube radius &lt;code&gt;t.y&lt;/code&gt; is derived by projecting &lt;code&gt;p&lt;/code&gt; onto the circular core:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight glsl"&gt;&lt;code&gt;&lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="nf"&gt;sdTorus&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;vec3&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;vec2&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;vec2&lt;/span&gt; &lt;span class="n"&gt;q&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;vec2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;xz&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4. Cylinder
&lt;/h3&gt;

&lt;p&gt;A vertical cylinder centred along the Y axis with radius &lt;code&gt;h.x&lt;/code&gt; and half-height &lt;code&gt;h.y&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight glsl"&gt;&lt;code&gt;&lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="nf"&gt;sdCylinder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;vec3&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;vec2&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;vec2&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;abs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;vec2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;xz&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Spatial domain operations
&lt;/h3&gt;

&lt;p&gt;One of the great advantages of signed distance fields over triangle meshes is that geometric transformations are performed by transforming the input coordinate space &lt;code&gt;p&lt;/code&gt; before evaluating the primitive, rather than modifying millions of stored vertices:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Translation&lt;/strong&gt;: Evaluating &lt;code&gt;sdSphere(p - offset, r)&lt;/code&gt; moves the sphere to position &lt;code&gt;offset&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rotation&lt;/strong&gt;: Multiplying &lt;code&gt;p&lt;/code&gt; by a rotation matrix rotates the geometry. For example, rotating around the Y axis by angle &lt;code&gt;theta&lt;/code&gt;:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight glsl"&gt;&lt;code&gt;  &lt;span class="kt"&gt;vec3&lt;/span&gt; &lt;span class="nf"&gt;rotateY&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;vec3&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;theta&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cos&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;theta&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;theta&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kt"&gt;vec3&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;z&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;z&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Infinite domain repetition&lt;/strong&gt;: By wrapping coordinates with modulo arithmetic, an artist can duplicate an object infinitely across 3D space with zero memory cost:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight glsl"&gt;&lt;code&gt;  &lt;span class="kt"&gt;vec3&lt;/span&gt; &lt;span class="nf"&gt;repeatDomain&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;vec3&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;vec3&lt;/span&gt; &lt;span class="n"&gt;cellSpacing&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;mod&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;cellSpacing&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cellSpacing&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;cellSpacing&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Constructive solid geometry and polynomial smooth blending
&lt;/h2&gt;

&lt;p&gt;Constructive Solid Geometry (CSG) combines multiple primitive distance fields using Boolean logic. In signed distance fields, Boolean operations map directly to basic arithmetic functions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight glsl"&gt;&lt;code&gt;&lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="nf"&gt;opUnion&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;d1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;d2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;        &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;d1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;d2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="nf"&gt;opIntersection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;d1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;d2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;d1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;d2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="nf"&gt;opSubtraction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;d1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;d2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;d1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;d2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;While standard CSG produces hard, sharp seams where surfaces intersect, creative coding and natural forms frequently demand organic, continuous transitions.&lt;/p&gt;

&lt;p&gt;The polynomial smooth minimum, formulated by Inigo Quilez, creates an organic fillet between two distance fields. The smoothing factor &lt;code&gt;k&lt;/code&gt; controls the radius of the organic bridge:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight glsl"&gt;&lt;code&gt;&lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="nf"&gt;opSmoothUnion&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;d1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;d2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;clamp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;d2&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;d1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;mix&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;d2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;d1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="nf"&gt;opSmoothSubtraction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;d1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;d2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;clamp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;d2&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;d1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;mix&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;d2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;d1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When two spheres or geometric shapes pass through one another with &lt;code&gt;opSmoothUnion&lt;/code&gt;, they blend seamlessly like drops of liquid mercury or metaballs. In live audiovisual performance, modulating the parameter &lt;code&gt;k&lt;/code&gt; with audio amplitude causes sharp geometric structures to dissolve into fluid organic masses on heavy musical accents.&lt;/p&gt;

&lt;h2&gt;
  
  
  Surface normals and Blinn-Phong lighting
&lt;/h2&gt;

&lt;p&gt;Because signed distance fields do not carry pre-computed vertex normals, we estimate the surface normal vector directly from the spatial gradient of the distance field.&lt;/p&gt;

&lt;p&gt;The gradient &lt;code&gt;∇f(p)&lt;/code&gt; points in the direction where the distance increases most rapidly. On a surface boundary where &lt;code&gt;f(p) = 0&lt;/code&gt;, this gradient vector points directly perpendicular to the surface. We approximate the gradient using finite differences with a tiny offset &lt;code&gt;e&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight glsl"&gt;&lt;code&gt;&lt;span class="kt"&gt;vec3&lt;/span&gt; &lt;span class="nf"&gt;calculateNormal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;vec3&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;vec2&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;vec2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mo"&gt;001&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;normalize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;vec3&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;xyy&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;xyy&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;yxy&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;yxy&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;yyx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;yyx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This central differences technique samples the scene six times around point &lt;code&gt;p&lt;/code&gt; and yields a smooth, accurate unit normal.&lt;/p&gt;

&lt;h3&gt;
  
  
  Shading and illumination
&lt;/h3&gt;

&lt;p&gt;With the surface normal &lt;code&gt;normal&lt;/code&gt; and view direction &lt;code&gt;viewDir&lt;/code&gt; calculated, we compute standard Blinn-Phong shading:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight glsl"&gt;&lt;code&gt;&lt;span class="kt"&gt;vec3&lt;/span&gt; &lt;span class="nf"&gt;computeLighting&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;vec3&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;vec3&lt;/span&gt; &lt;span class="n"&gt;normal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;vec3&lt;/span&gt; &lt;span class="n"&gt;viewDir&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;vec3&lt;/span&gt; &lt;span class="n"&gt;lightPos&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;vec3&lt;/span&gt; &lt;span class="n"&gt;baseColour&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;vec3&lt;/span&gt; &lt;span class="n"&gt;lightDir&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;normalize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lightPos&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kt"&gt;vec3&lt;/span&gt; &lt;span class="n"&gt;halfwayDir&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;normalize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lightDir&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;viewDir&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Ambient illumination&lt;/span&gt;
    &lt;span class="kt"&gt;vec3&lt;/span&gt; &lt;span class="n"&gt;ambient&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;15&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;baseColour&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// Diffuse Lambertian reflection&lt;/span&gt;
    &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;diff&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;normal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lightDir&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kt"&gt;vec3&lt;/span&gt; &lt;span class="n"&gt;diffuse&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;diff&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;baseColour&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// Specular highlight&lt;/span&gt;
    &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;spec&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;normal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;halfwayDir&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kt"&gt;vec3&lt;/span&gt; &lt;span class="n"&gt;specular&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;vec3&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// Soft shadow attenuation&lt;/span&gt;
    &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;shadow&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;computeSoftShadow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;normal&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mo"&gt;002&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lightDir&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mo"&gt;02&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;ambient&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;diffuse&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;specular&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;shadow&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Raymarched soft shadows
&lt;/h3&gt;

&lt;p&gt;Raymarching offers an elegant way to compute realistic penumbra soft shadows with zero shadow maps. As a secondary shadow ray travels from surface point &lt;code&gt;p&lt;/code&gt; toward the light source, we record the minimum ratio of distance to travel distance:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight glsl"&gt;&lt;code&gt;&lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="nf"&gt;computeSoftShadow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;vec3&lt;/span&gt; &lt;span class="n"&gt;ro&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;vec3&lt;/span&gt; &lt;span class="n"&gt;rd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;mint&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;maxt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mint&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;48&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ro&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;rd&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;h&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mo"&gt;0005&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// In full shadow&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="n"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;clamp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mo"&gt;02&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="n"&gt;maxt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;clamp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The parameter &lt;code&gt;k&lt;/code&gt; controls shadow softness: smaller values yield wide, blurry penumbras resembling diffuse studio lighting, while larger values produce crisp direct sunlight.&lt;/p&gt;

&lt;h2&gt;
  
  
  Building an audio-reactive raymarcher in Infinite
&lt;/h2&gt;

&lt;p&gt;To run this pipeline inside Infinite, we write our complete GLSL kernel inside a &lt;strong&gt;Field Pixel&lt;/strong&gt; node. Infinite's built-in &lt;a href="https://infinitedevices.org/blog/field-language-write-what-a-node-does.html" rel="noopener noreferrer"&gt;Field language&lt;/a&gt; compiles short text kernels into native GPU fragment shaders without extra wrapper boilerplate.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Declaring modulatable parameters
&lt;/h3&gt;

&lt;p&gt;In Field, parameters are declared directly at the top of the kernel script. Each parameter automatically turns into an interactive knob on the node and exposes an input pin on the canvas:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight glsl"&gt;&lt;code&gt;&lt;span class="n"&gt;param&lt;/span&gt; &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;u_bass&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;param&lt;/span&gt; &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;u_morph&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;param&lt;/span&gt; &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;u_twist&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;param&lt;/span&gt; &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;u_smooth&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mo"&gt;05&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Defining the scene distance map
&lt;/h3&gt;

&lt;p&gt;We define a dynamic scene combining a central sphere, a rotating torus, and an organic twist distortion:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight glsl"&gt;&lt;code&gt;&lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;vec3&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Audio-reactive spatial twist&lt;/span&gt;
    &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;angle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;u_twist&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;cosA&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cos&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;angle&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;sinA&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;angle&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;xz&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;mat2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cosA&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;sinA&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sinA&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cosA&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;xz&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// Primitive 1: Central pulsing sphere driven by bass&lt;/span&gt;
    &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;sphereRadius&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;u_bass&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;45&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;dSphere&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sdSphere&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sphereRadius&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Primitive 2: Outer torus morphed by midrange frequencies&lt;/span&gt;
    &lt;span class="kt"&gt;vec2&lt;/span&gt; &lt;span class="n"&gt;torusDims&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mix&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;vec2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;35&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="kt"&gt;vec2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;u_morph&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;dTorus&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sdTorus&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;torusDims&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Smooth organic blend&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;opSmoothUnion&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dSphere&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dTorus&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;u_smooth&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Assembling the canvas patch
&lt;/h3&gt;

&lt;p&gt;The visual half of the patch connects as follows:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Add a &lt;strong&gt;Field Pixel&lt;/strong&gt; node and paste the raymarching kernel.&lt;/li&gt;
&lt;li&gt;Cable the image output pin of &lt;strong&gt;Field Pixel&lt;/strong&gt; into a &lt;strong&gt;Bloom&lt;/strong&gt; node to introduce subtle optical glow on high specular reflections.&lt;/li&gt;
&lt;li&gt;Cable the output of &lt;strong&gt;Bloom&lt;/strong&gt; into the &lt;strong&gt;Output&lt;/strong&gt; node to send the rendered picture to your display or projector.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The audio half of the patch provides the real-time modulation streams:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Add an &lt;strong&gt;Analog&lt;/strong&gt; or &lt;strong&gt;Wavetable&lt;/strong&gt; synth node, or connect live audio through an &lt;strong&gt;Audio In&lt;/strong&gt; node.&lt;/li&gt;
&lt;li&gt;Route the audio signal to an &lt;strong&gt;Audio Out&lt;/strong&gt; node for playback and into an &lt;strong&gt;Audio Analyze&lt;/strong&gt; node.&lt;/li&gt;
&lt;li&gt;The &lt;strong&gt;Audio Analyze&lt;/strong&gt; node decomposes the audio stream into frequency bands: &lt;code&gt;low&lt;/code&gt;, &lt;code&gt;mid&lt;/code&gt;, and &lt;code&gt;high&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Cable the &lt;code&gt;low&lt;/code&gt; pin of &lt;strong&gt;Audio Analyze&lt;/strong&gt; to the &lt;code&gt;u_bass&lt;/code&gt; input pin of &lt;strong&gt;Field Pixel&lt;/strong&gt;. When a kick drum hits, the central sphere expands dynamically.&lt;/li&gt;
&lt;li&gt;Cable the &lt;code&gt;mid&lt;/code&gt; pin of &lt;strong&gt;Audio Analyze&lt;/strong&gt; to &lt;code&gt;u_morph&lt;/code&gt;. Snare hits and synth melodies cause the torus geometry to morph in radius and thickness.&lt;/li&gt;
&lt;li&gt;Add an &lt;strong&gt;LFO&lt;/strong&gt; node configured to a slow sine wave and cable its output into &lt;code&gt;u_twist&lt;/code&gt;. This guarantees that the geometric lattice continually drifts and rotates even during quiet musical breakdowns.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For ready-to-use patch setups, browse the &lt;a href="https://infinitedevices.org/library.html" rel="noopener noreferrer"&gt;free templates in the Library&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Performance optimisation for real-time framerates
&lt;/h2&gt;

&lt;p&gt;Evaluating up to 128 distance queries for every pixel at 1080p or 4K resolution requires careful attention to GPU execution:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Bounding volume tests&lt;/strong&gt;: Before evaluating an expensive geometric calculation or infinite repetition array, wrap the object in a simple bounding sphere. If the ray step indicates that the distance to the bounding sphere is positive, return that distance immediately, bypassing complex inner math.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Step budget constraints&lt;/strong&gt;: In a live performance setting running at 60 FPS, cap ray iterations between 64 and 96 steps. This prevents GPU thermal throttling while maintaining clean visual results.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Avoid branch divergence&lt;/strong&gt;: Avoid placing conditional branching statements (&lt;code&gt;if/else&lt;/code&gt;) inside distance functions. Instead, prefer arithmetic blending functions like &lt;code&gt;mix()&lt;/code&gt;, &lt;code&gt;step()&lt;/code&gt;, and &lt;code&gt;clamp()&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Over-relaxation&lt;/strong&gt;: Standard sphere tracing steps by exactly &lt;code&gt;f(p)&lt;/code&gt;. Over-relaxation techniques scale each step by a relaxation factor &lt;code&gt;omega&lt;/code&gt; (typically around &lt;code&gt;1.2&lt;/code&gt; to &lt;code&gt;1.5&lt;/code&gt;), speeding up ray travel through long open corridors without skipping boundaries.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;To explore further techniques in real-time shader authoring, read our &lt;a href="https://infinitedevices.org/blog/audio-reactive-glsl-shaders.html" rel="noopener noreferrer"&gt;audio-reactive GLSL shaders guide&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary and where to experiment next
&lt;/h2&gt;

&lt;p&gt;Raymarching signed distance fields transforms the fragment shader into a full 3D geometric engine. By replacing stored polygon meshes with analytic distance functions, artists gain complete procedural control over form, repetition, lighting, and soft shadows.&lt;/p&gt;

&lt;p&gt;When integrated into Infinite's unified audiovisual node canvas, these distance fields become reactive physical instruments. Kick drums displace space, melodies morph geometric topology, and LFOs twist coordinate domains in real time, all running on the GPU with zero audio-thread latency.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://infinitedevices.org/blog/raymarching-signed-distance-fields-in-real-time-glsl.html" rel="noopener noreferrer"&gt;https://infinitedevices.org/blog/raymarching-signed-distance-fields-in-real-time-glsl.html&lt;/a&gt;. Infinite is a free, open-source DAW for visuals, music and code: &lt;a href="https://infinitedevices.org" rel="noopener noreferrer"&gt;infinitedevices.org&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>raymarching</category>
      <category>signeddistancefields</category>
      <category>glslshaders</category>
      <category>creativecoding</category>
    </item>
  </channel>
</rss>
