Specimen / generative

Plasma (Sine Interference)

A flowing GPU plasma. Two sine-wave fields at slightly detuned scales beat against each other into shimmering moire fringes, a slow rotating domain warp bends the coordinates into liquid motion, and the result is mapped through a cyclic cosine palette. Self-contained and stateless - one GLSL TOP, no input, no feedback - so it drops in anywhere as a VJ loop, texture, or displacement source.

intermediate 5 operators

Node graph preview

Plasma (Sine Interference) graph

inert preview
Show raw TDN YAML

Paste in TouchDesigner with Embody running.

format: tdn
version: '2.0'
build: null
generator: Embody/6.0.26
td_build: 099.2025.32820
source_file: Embody-6.26.toe
exported_at: '2026-06-13T15:59:04Z'
network_path: /specimen_lab/plasma_interference
options:
  include_dat_content: true
  include_storage: true
type_defaults:
  textDAT:
    parameters:
      language: glsl
    flags:
    - viewer
    size: [130, 90]
    color: [0.67, 0.67, 0.67]
type: baseCOMP
custom_pars:
  Plasma:
  - name: Scale
    style: Float
    startSection: true
    default: 6
    min: 1.0
    max: 20.0
    clampMin: true
    clampMax: true
    normMin: 1.0
    normMax: 20.0
    help: Spatial frequency of the sine fields. Low = broad lava-lamp blobs; high = dense fine plasma.
  - name: Speed
    style: Float
    default: 1
    max: 4.0
    clampMin: true
    clampMax: true
    normMax: 4.0
    help: Animation speed. 1 = gentle flow; 0 freezes a still (the TOP keeps cooking, frame is identical).
  - name: Warp
    style: Float
    default: 1.2
    max: 3.0
    clampMin: true
    clampMax: true
    normMax: 3.0
    help: Domain-warp amount. 0 = flat sliding stripes; higher bends the coords into a flowing liquid swirl.
  - name: Complexity
    style: Float
    label: Interference
    default: 1
    max: 2.0
    clampMin: true
    clampMax: true
    normMax: 2.0
    help: Detune between the two sine fields. 0 = one clean plasma; higher beats them into shimmering moire.
  - name: Palette
    style: Float
    label: Palette Hue
    startSection: true
    clampMin: true
    clampMax: true
    help: Rotates the cyclic cosine palette through the full hue ring. Loops seamlessly 1.0 -> 0.0.
  - name: Contrast
    style: Float
    default: 0.4
    clampMin: true
    clampMax: true
    help: Palette saturation/contrast (onto a 0.6 base in the shader). Low = pastel; high = punchy neon.
color: [0.67, 0.67, 0.67]
operators:
- name: out1
  type: outTOP
  parameters:
    label: =me.name
  flags:
  - viewer
  position: [800, 0]
  size: [130, 90]
  color: [0.67, 0.67, 0.67]
  inputs:
  - glsl_plasma
- name: annotate1
  type: annotateCOMP
  parameters:
    order: =me.digits or 0
    layerzone: =0 if hasattr(me, 'EncloseOPs') and me.EncloseOPs else 1
  sequences:
    ext:
    - object: op.TDAnnotate.mod.AnnotateExt.AnnotateExt(me)
      promote: true
  custom_pars:
    Text:
    - name: Titletext
      style: Str
      label: Title Text
      startSection: true
      default: Annotate
      help: Text in the title bar.
      value: Plasma - interfering sine fields + domain warp
    - name: Titleheight
      style: Int
      label: Title Height
      default: 30
      clampMin: true
      normMin: 5.0
      normMax: 100.0
      help: Height of the title bar. Title font height adjusts automatically to fill.
    - name: Titlealign
      style: Menu
      label: Title Align
      default: left
      menuNames:
      - left
      - center
      - right
      menuLabels:
      - Left
      - Center
      - Right
      help: Alignment of title text.
    - name: Bodytext
      style: Str
      label: Body Text
      startSection: true
      help: Text in the body area. Use an expression for newlines etc.
      value: 'Two sine-wave fields at slightly detuned scales BEAT against each other -> moire fringes (the shimmer). A slow rotating domain warp bends the sample coords -> liquid flow. The summed field is folded cyclically into 0..1 and mapped through an Inigo-Quilez cosine palette (smooth hue cycling, never bands); a vignette frames it as a loop. All on the GPU in one glslTOP -- no input, no feedback, stateless and cheap. Params: Scale, Speed, Warp, Complexity (detune), Palette (hue), Contrast.'
    - name: Bodyfontsize
      style: Int
      label: Body Font Size
      default: 10
      clampMin: true
      normMin: 8.0
      normMax: 100.0
      help: Size of text in the body area.
    - name: Bodylimitwidth
      style: Toggle
      label: Limit Body Text Width
      help: Limit the width of the text area.
    - name: Bodymaxwidth
      style: Int
      label: Max Body Text Width
      default: 1000
      clampMin: true
      normMin: 100.0
      normMax: 2000.0
      help: Width limit that will cause wraparound or cut-off. Measured in Panel units.
    Settings:
    - name: Mode
      style: Menu
      default: comment
      menuNames:
      - comment
      - networkbox
      - annotate
      menuLabels:
      - Comment
      - Network Box
      - Annotate
      help: 'Switch between Comment, Network Box, and Annotate Modes. '
      value: annotate
    - name: Smartquote
      style: Toggle
      label: Smart Quote
      startSection: true
      help: Converts quotes, ellipsis, and dashes to more typographically nice unicode versions.
    - name: Bodywordwrap
      style: Toggle
      label: Body Word Wrap
      default: true
      help: Wrap body text when it extends past right bound.
    - name: Backcolorr
      style: RGBA
      label: Back Color
      startSection: true
      default: 1
      help: Background color base.
      values: [0.13, 0.28, 0.32]
    - name: Backcoloralpha
      style: Float
      label: Back Color Alpha
      default: 1
      clampMin: true
      clampMax: true
      help: Back color alpha.
    - name: Opacity
      style: Float
      label: Annotate Opacity
      default: 1
      clampMin: true
      clampMax: true
      help: Opacity of the entire Annotate.
      value: 0.25
    OP Viewer:
    - name: Opviewerdisplay
      style: Toggle
      label: Viewer Display
      help: Turn the visibility of the viewer specified in the OP parameter below on or off.
    - name: Opviewer
      style: OP
      label: OP
      help: The operator whose viewer is displayed in the Annotate.
    - name: Opviewerinteractive
      style: Toggle
      label: OP Viewer Interactive
      help: Allow interaction with the OP viewer.
    - name: Opvieweroversize
      style: Menu
      label: Size/Aspect Override
      startSection: true
      default: 'False'
      menuNames:
      - natural
      - specify
      - autofit
      menuLabels:
      - Natural
      - Specify
      - Auto-Fit
      help: Use the Size/Aspect Override to control viewer's size in the background.
      value: natural
    - name: Opviewersize
      style: WH
      label: Size/Aspect
      default: 800
      clampMin: true
      normMin: 1.0
      normMax: 1000.0
      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.
    - name: Opviewerscale
      style: Float
      label: Scale
      startSection: true
      default: 1
      normMax: 2.0
      help: Scale the viewer by this factor.
    - name: Opviewerjustifyx
      style: Float
      label: Justify X
      normMin: -1.0
      help: Move the border of the viewer towards left edge of Annotate when negative or towards right edge when positive.
    - name: Opviewerjustifyy
      style: Float
      label: Justify Y
      normMin: -1.0
    - name: Opviewerfillbodytitle
      style: Toggle
      label: Cover Body and Title
      help: When True, allow viewer to display in the Annotate title area as well as body.
    - name: Opviewerzoom
      style: Float
      label: OP Viewer Zoom
      startSection: true
      default: 1
      min: 0.001
      clampMin: true
      normMin: 1.0
      normMax: 5.0
      help: Zoom the viewer by this scale factor without increasing the size of its display area in the Annotate.
    - name: Opvieweroffsetx
      style: XYZW
      label: OP Viewer Offset
      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.
    - name: Opviewerfillalpha
      style: Float
      label: Fill Alpha
      startSection: true
      default: 1
      clampMin: true
      clampMax: true
      help: Alpha value of the background area in the OP Viewer.
    About:
    - name: Version
      style: Str
      startSection: true
      default: '1.0'
      readOnly: true
      help: Annotate COMP default setup version.
    - name: Help
      style: Pulse
      help: Click to open help page.
  flags:
  - display
  position: [180, -220]
  size: [820, 480]
  color: [0.45, 0.45, 0.45]
  palette_clone: true
- name: glsl_plasma
  type: glslTOP
  parameters:
    pixeldat: glsl_plasma_pixel
    computedat: glsl_plasma_compute
    outputresolution: custom
    resolutionw: 1280
    resolutionh: 720
  sequences:
    vec:
    - name: uParams
      valuex: =parent().par.Scale.eval()
      valuey: =parent().par.Warp.eval()
      valuez: =parent().par.Complexity.eval()
      valuew: =absTime.seconds*parent().par.Speed.eval()
    - name: uPalette
      valuex: =parent().par.Palette.eval()
      valuey: =parent().par.Contrast.eval()
      valuez: 0
      valuew: 0
  position: [400, 0]
  size: [130, 90]
  color: [0.67, 0.67, 0.67]
- name: glsl_plasma_info
  type: infoDAT
  parameters:
    op: glsl_plasma
  flags:
  - viewer
  position: [550, -150]
  size: [130, 90]
  color: [0.67, 0.67, 0.67]
  dock: glsl_plasma
  dat_read_only: true
- name: glsl_plasma_pixel
  type: textDAT
  parameters:
    extension: frag
  position: [400, -150]
  dock: glsl_plasma
  dat_content: |-
    uniform vec4 uParams;   // x=scale, y=warp, z=complexity(detune), w=time(=absTime*Speed)
    uniform vec4 uPalette;  // x=hue 0..1, y=contrast
    out vec4 fragColor;
    const float PI = 3.14159265;

    // Inigo-Quilez cyclic cosine palette: smooth, loops in hue, never bands.
    vec3 palette(float t, float hue, float contrast){
        vec3 a = vec3(0.5);
        vec3 b = vec3(0.5) * contrast;
        vec3 c = vec3(1.0, 1.0, 1.0);
        vec3 d = vec3(0.00, 0.33, 0.67) + hue;   // hue rotates the phase offsets
        return a + b * cos(6.28318 * (c * t + d));
    }

    // One animated sine field: a handful of moving plane-waves summed.
    float field(vec2 p, float time, float freq){
        float v = 0.0;
        v += sin(p.x * freq + time);
        v += sin(p.y * freq * 1.3 + time * 1.1);
        v += sin((p.x + p.y) * freq * 0.7 + time * 0.9);
        float cx = p.x + 0.5 * sin(time * 0.4);
        float cy = p.y + 0.5 * cos(time * 0.35);
        v += sin(sqrt(cx * cx + cy * cy) * freq * 1.6 + time * 1.3);  // radial ripple, moving center
        return v;
    }

    void main(){
        float aspect = uTDOutputInfo.res.z / uTDOutputInfo.res.w;  // output res = (1/w,1/h,w,h); zw = pixel dims
        vec2 uv = vUV.st;
        vec2 p  = (uv - 0.5);
        p.x *= aspect;                               // keep the plasma square on wide formats

        float t      = uParams.w;
        float scale  = max(0.5, uParams.x);
        float warp   = uParams.y;
        float detune = uParams.z;

        p *= scale;

        // Domain warp: a slow rotating swirl bends the sample coords -> liquid flow.
        vec2 w = vec2(
            sin(p.y * 1.7 + t * 0.5),
            cos(p.x * 1.5 - t * 0.45)
        );
        vec2 pw = p + warp * w;

        // Two fields at slightly detuned scales BEAT against each other -> fringes.
        float f1 = field(pw, t, 1.0);
        float f2 = field(pw, t * 1.05, 1.0 + 0.25 * detune);
        float v  = (f1 + f2) * 0.25;                 // ~[-2,2]; folded cyclically into 0..1 below
        v += 0.30 * detune * sin((f1 - f2) * PI);    // explicit beat term -> visible moire shimmer

        float tone = 0.5 + 0.5 * sin(v * PI);        // fold into 0..1, smooth + cyclic

        vec3 col = palette(tone, uPalette.x, 0.6 + uPalette.y);

        float d = length(uv - 0.5);                  // gentle vignette: reads as a framed loop
        col *= mix(1.0, 0.55, smoothstep(0.45, 0.95, d));

        fragColor = vec4(clamp(col, 0.0, 1.0), 1.0);
    }
  dat_content_format: text
- name: glsl_plasma_compute
  type: textDAT
  position: [250, -150]
  dock: glsl_plasma
annotations:
- name: annotate1
  mode: annotate
  title: Plasma - interfering sine fields + domain warp
  text: 'Two sine-wave fields at slightly detuned scales BEAT against each other -> moire fringes (the shimmer). A slow rotating domain warp bends the sample coords -> liquid flow. The summed field is folded cyclically into 0..1 and mapped through an Inigo-Quilez cosine palette (smooth hue cycling, never bands); a vignette frames it as a loop. All on the GPU in one glslTOP -- no input, no feedback, stateless and cheap. Params: Scale, Speed, Warp, Complexity (detune), Palette (hue), Contrast.'
  position: [180, -220]
  size: [820, 480]
  color: [0.13, 0.28, 0.32]
  opacity: 0.25