Specimen / generative

Reaction-Diffusion (Gray-Scott)

A living Gray-Scott reaction-diffusion field. Two chemicals diffuse and react in a GPU feedback loop, growing organic maze and coral patterns that evolve continuously. Usable as a texture, displacement, or mask source.

intermediate 14 operators

Node graph preview

Reaction-Diffusion (Gray-Scott) graph

inert preview
Show raw TDN YAML

Paste in TouchDesigner with Embody running.

format: tdn
version: '2.0'
build: null
generator: Embody/6.0.15
td_build: 099.2025.32820
source_file: Embody-6.15.toe
exported_at: '2026-06-11T03:24:07Z'
network_path: /specimen_lab/reaction_diffusion
options:
  include_dat_content: true
  include_storage: true
type_defaults:
  annotateCOMP:
    parameters:
      order: =me.digits or 0
      layerzone: =0 if hasattr(me, 'EncloseOPs') and me.EncloseOPs else 1
    flags:
    - display
    color: [0.45, 0.45, 0.45]
  glslTOP:
    flags:
    - viewer
    size: [130, 90]
    color: [0.67, 0.67, 0.67]
  infoDAT:
    flags:
    - viewer
    size: [130, 90]
    color: [0.67, 0.67, 0.67]
  textDAT:
    parameters:
      language: glsl
    flags:
    - viewer
    size: [130, 90]
    color: [0.67, 0.67, 0.67]
par_templates:
  about:
  - default: '1.0'
    help: Annotate COMP default setup version.
    name: Version
    readOnly: true
    startSection: true
    style: Str
  - help: Click to open help page.
    name: Help
    style: Pulse
  text:
  - default: Annotate
    help: Text in the title bar.
    label: Title Text
    name: Titletext
    startSection: true
    style: Str
  - clampMin: true
    default: 30
    help: Height of the title bar. Title font height adjusts automatically to fill.
    label: Title Height
    name: Titleheight
    normMax: 100.0
    normMin: 5.0
    style: Int
  - default: left
    help: Alignment of title text.
    label: Title Align
    menuLabels:
    - Left
    - Center
    - Right
    menuNames:
    - left
    - center
    - right
    name: Titlealign
    style: Menu
  - help: Text in the body area. Use an expression for newlines etc.
    label: Body Text
    name: Bodytext
    startSection: true
    style: Str
  - clampMin: true
    default: 10
    help: Size of text in the body area.
    label: Body Font Size
    name: Bodyfontsize
    normMax: 100.0
    normMin: 8.0
    style: Int
  - help: Limit the width of the text area.
    label: Limit Body Text Width
    name: Bodylimitwidth
    style: Toggle
  - clampMin: true
    default: 1000
    help: Width limit that will cause wraparound or cut-off. Measured in Panel units.
    label: Max Body Text Width
    name: Bodymaxwidth
    normMax: 2000.0
    normMin: 100.0
    style: Int
  settings:
  - default: comment
    help: 'Switch between Comment, Network Box, and Annotate Modes. '
    menuLabels:
    - Comment
    - Network Box
    - Annotate
    menuNames:
    - comment
    - networkbox
    - annotate
    name: Mode
    style: Menu
  - help: Converts quotes, ellipsis, and dashes to more typographically nice unicode versions.
    label: Smart Quote
    name: Smartquote
    startSection: true
    style: Toggle
  - default: true
    help: Wrap body text when it extends past right bound.
    label: Body Word Wrap
    name: Bodywordwrap
    style: Toggle
  - default: 1
    help: Background color base.
    label: Back Color
    name: Backcolorr
    startSection: true
    style: RGBA
  - clampMax: true
    clampMin: true
    default: 1
    help: Back color alpha.
    label: Back Color Alpha
    name: Backcoloralpha
    style: Float
  - clampMax: true
    clampMin: true
    default: 1
    help: Opacity of the entire Annotate.
    label: Annotate Opacity
    name: Opacity
    style: Float
  op_viewer:
  - help: Turn the visibility of the viewer specified in the OP parameter below on or off.
    label: Viewer Display
    name: Opviewerdisplay
    style: Toggle
  - help: The operator whose viewer is displayed in the Annotate.
    label: OP
    name: Opviewer
    style: OP
  - help: Allow interaction with the OP viewer.
    label: OP Viewer Interactive
    name: Opviewerinteractive
    style: Toggle
  - default: 'False'
    help: Use the Size/Aspect Override to control viewer's size in the background.
    label: Size/Aspect Override
    menuLabels:
    - Natural
    - Specify
    - Auto-Fit
    menuNames:
    - natural
    - specify
    - autofit
    name: Opvieweroversize
    startSection: true
    style: Menu
  - clampMin: true
    default: 800
    help: Diplay viewer as-if it were being displayed at this resolution. This is particularly useful for zooming into operators that don't have a built-in resolution, like CHOPs, SOPs, and DATs.
    label: Size/Aspect
    name: Opviewersize
    normMax: 1000.0
    normMin: 1.0
    style: WH
  - default: 1
    help: Scale the viewer by this factor.
    label: Scale
    name: Opviewerscale
    normMax: 2.0
    startSection: true
    style: Float
  - help: Move the border of the viewer towards left edge of Annotate when negative or towards right edge when positive.
    label: Justify X
    name: Opviewerjustifyx
    normMin: -1.0
    style: Float
  - label: Justify Y
    name: Opviewerjustifyy
    normMin: -1.0
    style: Float
  - help: When True, allow viewer to display in the Annotate title area as well as body.
    label: Cover Body and Title
    name: Opviewerfillbodytitle
    style: Toggle
  - clampMin: true
    default: 1
    help: Zoom the viewer by this scale factor without increasing the size of its display area in the Annotate.
    label: OP Viewer Zoom
    min: 0.001
    name: Opviewerzoom
    normMax: 5.0
    normMin: 1.0
    startSection: true
    style: Float
  - help: Offsets the displayed area within the viewer. Combined with OP Viewer Zoom, this lets you display a specific area of a viewer, such as a CHOP channel or table cell.
    label: OP Viewer Offset
    name: Opvieweroffsetx
    style: XYZW
  - clampMax: true
    clampMin: true
    default: 1
    help: Alpha value of the background area in the OP Viewer.
    label: Fill Alpha
    name: Opviewerfillalpha
    startSection: true
    style: Float
type: baseCOMP
color: [0.67, 0.67, 0.67]
operators:
- name: out1
  type: outTOP
  parameters:
    label: =me.name
  position: [2750, 0]
  size: [130, 90]
  color: [0.67, 0.67, 0.67]
  inputs:
  - glsl_colorize
- name: annotate1
  type: annotateCOMP
  sequences:
    ext:
    - object: op.TDAnnotate.mod.AnnotateExt.AnnotateExt(me)
      promote: true
  custom_pars:
    Text:
      $t: text
      Titletext: Seed
      Bodytext: Initial conditions. A=1 everywhere; B=1 in a jittered grid of spots, setting where the reaction begins.
    Settings:
      $t: settings
      Mode: annotate
      Backcolorr: [0.12, 0.19, 0.16]
      Opacity: 0.3
    OP Viewer:
      $t: op_viewer
      Opvieweroversize: natural
    About:
      $t: about
  position: [-220, -190]
  size: [570, 450]
  palette_clone: true
- name: annotate2
  type: annotateCOMP
  sequences:
    ext:
    - object: op.TDAnnotate.mod.AnnotateExt.AnnotateExt(me)
      promote: true
  custom_pars:
    Text:
      $t: text
      Titletext: Reaction-Diffusion Loop
      Bodytext: 'The Gray-Scott core: chemical state is held between frames and updated by diffusion + reaction each frame. Feed/kill rates choose the pattern regime. Cooks every frame when the output is demanded.'
    Settings:
      $t: settings
      Mode: annotate
      Backcolorr: [0.1, 0.18, 0.26]
      Opacity: 0.3
    OP Viewer:
      $t: op_viewer
      Opvieweroversize: natural
    About:
      $t: about
  position: [830, -190]
  size: [720, 450]
  palette_clone: true
- name: annotate3
  type: annotateCOMP
  sequences:
    ext:
    - object: op.TDAnnotate.mod.AnnotateExt.AnnotateExt(me)
      promote: true
  custom_pars:
    Text:
      $t: text
      Titletext: Colorize & Output
      Bodytext: Maps B concentration to a deep-navy -> teal -> cream palette with a soft vignette, terminating in the output Null.
    Settings:
      $t: settings
      Mode: annotate
      Backcolorr: [0.2, 0.16, 0.21]
      Opacity: 0.3
    OP Viewer:
      $t: op_viewer
      Opvieweroversize: natural
    About:
      $t: about
  position: [2030, -190]
  size: [920, 450]
  palette_clone: true
- name: glsl_seed
  type: glslTOP
  parameters:
    pixeldat: glsl_seed_pixel
    computedat: seed_compute
    outputresolution: custom
    resolutionw: 512
    resolutionh: 512
    format: rgba32float
- name: glsl_rd_step
  type: glslTOP
  parameters:
    pixeldat: glsl_rd_step_pixel
    computedat: rd_step_compute
    outputresolution: custom
    resolutionw: 512
    resolutionh: 512
    format: rgba32float
  position: [1200, 0]
  inputs:
  - feedback_state
- name: glsl_colorize
  type: glslTOP
  parameters:
    pixeldat: glsl_colorize_pixel
    computedat: colorize_compute
  position: [2250, 0]
  inputs:
  - glsl_rd_step
- name: feedback_state
  type: feedbackTOP
  parameters:
    top: glsl_rd_step
    format: rgba32float
  flags:
  - viewer
  position: [900, 0]
  size: [130, 90]
  color: [0.67, 0.67, 0.67]
  inputs:
  - glsl_seed
- name: glsl_seed_info
  type: infoDAT
  parameters:
    op: glsl_seed
  position: [0, -120]
  dock: glsl_seed
  dat_read_only: true
- name: glsl_seed_pixel
  type: textDAT
  parameters:
    extension: frag
  position: [150, -120]
  dock: glsl_seed
  dat_content: |-
    out vec4 fragColor;
    float h(vec2 p){ return fract(sin(dot(p, vec2(127.1,311.7)))*43758.5453); }
    void main(){
        vec2 uv = vUV.st;
        float a = 1.0; float b = 0.0;
        vec2 g = uv * 7.0;
        vec2 cell = floor(g);
        vec2 f = fract(g);
        vec2 jit = vec2(h(cell), h(cell+3.7))*0.6 + 0.2;
        if(distance(f, jit) < 0.13) b = 1.0;
        fragColor = vec4(a, b, 0.0, 1.0);
    }
  dat_content_format: text
- name: glsl_rd_step_info
  type: infoDAT
  parameters:
    op: glsl_rd_step
  position: [1200, -120]
  dock: glsl_rd_step
  dat_read_only: true
- name: glsl_seed_compute
  type: textDAT
  position: [-150, -120]
  dock: glsl_seed
- name: glsl_colorize_info
  type: infoDAT
  parameters:
    op: glsl_colorize
  position: [2250, -120]
  dock: glsl_colorize
  dat_read_only: true
- name: glsl_rd_step_pixel
  type: textDAT
  parameters:
    extension: frag
  position: [1350, -120]
  dock: glsl_rd_step
  dat_content: |-
    out vec4 fragColor;
    const float feed = 0.055;
    const float kill = 0.062;
    const float da = 1.0;
    const float db = 0.5;
    void main(){
        vec2 texel = uTD2DInfos[0].res.xy;
        vec2 uv = vUV.st;
        vec2 s = texture(sTD2DInputs[0], uv).rg;
        float a = s.r; float b = s.g;
        vec2 lap = vec2(0.0);
        lap += texture(sTD2DInputs[0], uv + texel*vec2(-1.0,-1.0)).rg * 0.05;
        lap += texture(sTD2DInputs[0], uv + texel*vec2( 0.0,-1.0)).rg * 0.20;
        lap += texture(sTD2DInputs[0], uv + texel*vec2( 1.0,-1.0)).rg * 0.05;
        lap += texture(sTD2DInputs[0], uv + texel*vec2(-1.0, 0.0)).rg * 0.20;
        lap += s * -1.0;
        lap += texture(sTD2DInputs[0], uv + texel*vec2( 1.0, 0.0)).rg * 0.20;
        lap += texture(sTD2DInputs[0], uv + texel*vec2(-1.0, 1.0)).rg * 0.05;
        lap += texture(sTD2DInputs[0], uv + texel*vec2( 0.0, 1.0)).rg * 0.20;
        lap += texture(sTD2DInputs[0], uv + texel*vec2( 1.0, 1.0)).rg * 0.05;
        float reaction = a*b*b;
        float na = a + (da*lap.r - reaction + feed*(1.0-a));
        float nb = b + (db*lap.g + reaction - (kill+feed)*b);
        fragColor = vec4(clamp(na,0.0,1.0), clamp(nb,0.0,1.0), 0.0, 1.0);
    }
  dat_content_format: text
- name: glsl_colorize_pixel
  type: textDAT
  parameters:
    extension: frag
  position: [2400, -120]
  dock: glsl_colorize
  dat_content: |-
    out vec4 fragColor;
    void main(){
        vec2 uv = vUV.st;
        vec2 s = texture(sTD2DInputs[0], uv).rg;
        float b = s.g;
        vec3 c0 = vec3(0.03, 0.04, 0.09);
        vec3 c1 = vec3(0.10, 0.42, 0.55);
        vec3 c2 = vec3(0.98, 0.90, 0.70);
        vec3 col = mix(c0, c1, smoothstep(0.0, 0.35, b));
        col = mix(col, c2, smoothstep(0.35, 0.55, b));
        float d = distance(uv, vec2(0.5));
        col *= mix(1.0, 0.55, smoothstep(0.40, 0.95, d));
        fragColor = vec4(col, 1.0);
    }
  dat_content_format: text
- name: glsl_rd_step_compute
  type: textDAT
  position: [1050, -120]
  dock: glsl_rd_step
- name: glsl_colorize_compute
  type: textDAT
  position: [2100, -120]
  dock: glsl_colorize
annotations:
- name: annotate1
  mode: annotate
  title: Seed
  text: Initial conditions. A=1 everywhere; B=1 in a jittered grid of spots, setting where the reaction begins.
  position: [-220, -190]
  size: [570, 450]
  color: [0.12, 0.19, 0.16]
  opacity: 0.3
- name: annotate2
  mode: annotate
  title: Reaction-Diffusion Loop
  text: 'The Gray-Scott core: chemical state is held between frames and updated by diffusion + reaction each frame. Feed/kill rates choose the pattern regime. Cooks every frame when the output is demanded.'
  position: [830, -190]
  size: [720, 450]
  color: [0.1, 0.18, 0.26]
  opacity: 0.3
- name: annotate3
  mode: annotate
  title: Colorize & Output
  text: Maps B concentration to a deep-navy -> teal -> cream palette with a soft vignette, terminating in the output Null.
  position: [2030, -190]
  size: [920, 450]
  color: [0.2, 0.16, 0.21]
  opacity: 0.3