Hydra Visual Livecoding Workshop

Duration: 2 hours + 1 hour bonus
Format: :

  • 5 lessons (30min each)
  • 10min teaching
  • 15-20min workshop

Cheat Sheet: Companion PDF (source)

Workshop Philosophy:

  • Experimentation over perfection
  • Happy accidents are learning opportunities
  • Community and sharing enhances creativity
  • Start simple, build complexity gradually

Lesson 1: Hydra 101 (10min + 20min)

Teaching (10min)

  • Objective: Get familiar with Hydra interface and basic workflow
  • Navigate to https://hydra.ojack.xyz
  • Interface tour (2min):
    • Play/Stop button
    • Clear button
    • Examples dropdown
    • Settings gear
  • Documentation overview: Quick look at built-in help
  • Basic workflow demonstration:
    osc(40, 0.1, 1.2).out()
    
  • Show simple texture → output chain

Workshop 1 (20min)

Goal: Get your first visual output working

  • Navigate to https://hydra.ojack.xyz
  • Try these basic generators:
    • osc().out()
    • noise().out()
    • solid(1,0,0).out()
  • Experiment with changing numbers
  • Bookmark useful resources page (see cheatsheet)

Lesson 2: Experimenting with Hydra (10min + 20min)

Teaching (10min)

  • Core principle: “You always get a result, no matter what numbers you use”
  • Dynamism: Array and arrow function add fun
  • Math.PI exploration:
    • osc(40, 0.1, Math.PI).out()
    • Show how Math.PI affects colors and scaling
  • Number ranges: Demonstrate different parameter ranges
  • Happy accidents: Show how random experimentation leads to discoveries

Workshop 2 (20min)

Goal: Understand parameter experimentation

  • Navigate to https://hydra.ojack.xyz/functions
  • Use this as reference while experimenting
  • Try:
    • Different frequency values: osc(10).out() vs osc(100).out()
    • Color experiments with Math.PI
    • Scaling with various numbers

Lesson 3: Mastering the Chain “.” (10min + 20min)

Teaching (10min)

  • The power of chaining: Everything connects with “.”
  • Write slowly and deliberately
  • Basic chain structure: source().transform().output()
  • Example progression:
    osc()           // just a source
    osc().rotate()  // add transformation
    osc().rotate(0.1).out() // complete chain
    
  • Keep function reference page open

Workshop 3 (20min)

Goal: Practice chaining functions confidently

  • Navigate to blank canvas https://hydra.ojack.xyz
  • Build chains step by step:
    • Start simple: noise().out()
    • Add transforms: noise().color(1,0,0).out()
    • Try combinations: osc().rotate().scale().out()
  • Keep it simple, focus on the flow

Lesson 4: Hyper-Hydra Modules (10min + 20min)

Teaching (10min)

  • Introduction to external modules
  • Modules icon: Show how to add modules easily
  • Hyper-Hydra: A collection of advanced modules
  • ShaderPark (glsl) integration demo:
  • Extensibility of Hydra
  • JavaScript tricks:
  c=0;f = new Array(3).fill().reduce(
  (acc, e) =>
    acc.add(
      shape(3,0.1)
        .scroll((c += 0.1), 0.1)
    ),
  solid()
  )
  f.out()

Workshop 4 (20min)

Goal: Explore advanced modules and understand performance

  • Reference: Hyper-Hydra GitHub
  • Try the ShaderPark example
  • Experiment with:
    • Image loading functions
    • Canvas size modifications
    • CPU-intensive operations
  • Notice performance differences and how it affects visuals

Lesson 5: Hydra-MIDI Integration (10min + 20min)

Teaching (10min)

  • Real-time control with MIDI
  • Music visualization possibilities
  • Demo setup:
    await loadScript("https://h.6120.eu/midi.js")
    await midi.start({ channel: '*', input: '*' })
    midi.show()
    
  • Show how MIDI values can control visual parameters

Workshop 5 (20min)

Goal: Connect MIDI to visuals

  • Navigate to: MIDI Example
  • Set up MIDI connection (virtual MIDI if no hardware)
  • Try: solid(note('*'), 0, 1).out()
  • Link different MIDI controls to visual parameters
  • Create responsive audio-visual performances

BONUS CONTENT (1 hour)

Lesson 6: Collaborative Coding with Flok (10min + 20min)

Teaching (10min)

  • Collaborative live coding concept
  • Flok platform introduction
  • Sharing sessions and real-time collaboration
  • Community aspect of live coding

Workshop 6 (20min)

Goal: Experience collaborative visual coding

  • Set up shared Flok session
  • Practice collaborative etiquette
  • Create group visual performances
  • Share and iterate on each other’s code

Key Resources to Keep Handy:

Hydra Cheat Sheet

Sources

osc(frequency, sync, offset)

Description: Generates an oscillating wave pattern.

osc(60, 0.1, 0).out()

noise(scale, offset)

Description: Creates a noise texture.

noise(10, 0.1).out()

voronoi(scale, speed, blending)

Description: Generates a Voronoi pattern.

voronoi(5, 0.3, 0.3).out()

shape(sides, radius, smoothing)

Description: Renders a geometric shape.

shape(3, 0.3, 0.01).out()

gradient(speed)

Description: Creates a gradient pattern.

gradient(0).out()

solid(r, g, b, a)

Description: Generates a solid color.

solid(0, 0, 0, 1).out()

Modulation

modulate(amount)

Description: Modulates the source using another texture.

osc(60, 0.1, 0).modulate(noise(10, 0.1), 0.1).out()

modulateScale(multiple, offset)

Description: Modulates the scale of the source.

osc(60, 0.1, 0).modulateScale(noise(10, 0.1), 1, 1).out()

modulateRotate(multiple, offset)

Description: Modulates the rotation of the source.

osc(60, 0.1, 0).modulateRotate(noise(10, 0.1), 1, 0).out()

modulatePixelate(multiple, offset)

Description: Modulates the pixelation of the source.

osc(60, 0.1, 0).modulatePixelate(noise(10, 0.1), 10, 3).out()

modulateRepeat(repeatX, repeatY, offsetX, offsetY)

Description: Modulates the repetition of the source.

osc(60, 0.1, 0).modulateRepeat(noise(10, 0.1), 3, 3, 0.5, 0.5).out()

modulateScrollX(scrollX, speed)

Description: Modulates horizontal scrolling.

osc(60, 0.1, 0).modulateScrollX(noise(10, 0.1), 0.5, 0).out()

modulateScrollY(scrollY, speed)

Description: Modulates vertical scrolling.

osc(60, 0.1, 0).modulateScrollY(noise(10, 0.1), 0.5, 0).out()

modulateHue(amount)

Description: Modulates the hue of the source.

osc(60, 0.1, 0).modulateHue(noise(10, 0.1), 1).out()

Color

color(r, g, b, a)

Description: Applies color to the source.

osc(60, 0.1, 0).color(1, 1, 1, 1).out()

colorama(amount)

Description: Applies a colorama effect.

osc(60, 0.1, 0).colorama(0.005).out()

saturate(amount)

Description: Adjusts the saturation.

osc(60, 0.1, 0).saturate(2).out()

contrast(amount)

Description: Adjusts the contrast.

osc(60, 0.1, 0).contrast(1.6).out()

brightness(amount)

Description: Adjusts the brightness.

osc(60, 0.1, 0).brightness(0.4).out()

invert(amount)

Description: Inverts the colors.

osc(60, 0.1, 0).invert(1).out()

luma(threshold, tolerance)

Description: Applies a luma key.

osc(60, 0.1, 0).luma(0.5, 0.1).out()

posterize(bins, gamma)

Description: Applies a posterization effect.

osc(60, 0.1, 0).posterize(3, 0.6).out()

Geometry

rotate(angle, speed)

Description: Rotates the source.

osc(60, 0.1, 0).rotate(10, 0).out()

scale(amount, xMult, yMult, offsetX, offsetY)

Description: Scales the source.

osc(60, 0.1, 0).scale(1.5, 1, 1, 0.5, 0.5).out()

pixelate(pixelX, pixelY)

Description: Applies a pixelation effect.

osc(60, 0.1, 0).pixelate(20, 20).out()

repeat(repeatX, repeatY, offsetX, offsetY)

Description: Repeats the source.

osc(60, 0.1, 0).repeat(3, 3, 0, 0).out()

repeatX(reps, offset)

Description: Repeats the source horizontally.

osc(60, 0.1, 0).repeatX(3, 0).out()

repeatY(reps, offset)

Description: Repeats the source vertically.

osc(60, 0.1, 0).repeatY(3, 0).out()

scroll(scrollX, scrollY, speedX, speedY)

Description: Scrolls the source.

osc(60, 0.1, 0).scroll(0.5, 0.5, 0, 0).out()

scrollX(scrollX, speed)

Description: Scrolls the source horizontally.

osc(60, 0.1, 0).scrollX(0.5, 0).out()

scrollY(scrollY, speed)

Description: Scrolls the source vertically.

osc(60, 0.1, 0).scrollY(0.5, 0).out()

kaleid(nSides)

Description: Applies a kaleidoscope effect.

osc(60, 0.1, 0).kaleid(4).out()

Blending

add(amount)

Description: Adds two sources.

osc(60, 0.1, 0).add(noise(10, 0.1), 1).out()

sub(amount)

Description: Subtracts one source from another.

osc(60, 0.1, 0).sub(noise(10, 0.1), 1).out()

layer()

Description: Overlays one source on another.

osc(60, 0.1, 0).layer(noise(10, 0.1)).out()

blend(amount)

Description: Blends two sources.

osc(60, 0.1, 0).blend(noise(10, 0.1), 0.5).out()

mult(amount)

Description: Multiplies two sources.

osc(60, 0.1, 0).mult(noise(10, 0.1), 1).out()

diff()

Description: Calculates the difference between two sources.

osc(60, 0.1, 0).diff(noise(10, 0.1)).out()

mask()

Description: Applies a mask to the source.

osc(60, 0.1, 0).mask(shape(3, 0.3, 0.01)).out()

Utilities

out()

Description: Outputs the current buffer.

osc(60, 0.1, 0).out()

render()

Description: Renders the specified buffer.

render(o0)

initCam(cameraNumber)

Description: Initializes the webcam.

s0.initCam(0)
src(s0).out()

initVideo()

Description: Initializes a video source.

s0.initVideo("https://6120.eu/public/storm.mp4")
src(s0).out()

initImage()

Description: Initializes an image source.

s0.initImage("file:///path/to/image.jpg")
src(s0).out()

src(texture)

Description: Sets the source for the pipeline.

src(o0).out()

time

Description: Global variable representing elapsed time.

osc(60, 0.1, 0).rotate(() => time).out()

speed

Description: Global variable controlling playback speed.

speed = 0.5

mouse

Description: Global variable representing mouse position.

osc(60, 0.1, 0).rotate(() => mouse.x * 0.01).out()

a.show

Description: Show FFT volume meter.

a.show()

a.fft

Description: Array representing audio frequency data.

osc(60, 0.1, 0).modulate(noise(() => a.fft[0] * 10, 0.1), 0.1).out()

a.setSmooth()

Description: Sets the smoothing for audio analysis.

a.setSmooth(0.8)

a.setBins()

Description: Sets the number of frequency bins for audio analysis.

a.setBins(4)

a.setCutoff()

Description: Sets the cutoff frequency for audio analysis.

a.setCutoff(2)

a.setScale()

Description: Sets the scale for audio analysis.

a.setScale(2)

MIDI

await midi.start().show()

Description: Start MIDI connection and display interface.

await midi.start().show()

note('*')

Description: Get MIDI note value from any channel.

solid(note('*'), 0, 1).out()

cc(channel, controller)

Description: Get MIDI CC (Continuous Controller) value.

osc(cc(0, 1) * 100).out()

aft('*')

Description: Get MIDI aftertouch value from any channel.

solid(aft('*'), 0, 1).out()