https://hydra.ojack.xyz                                                Cortland Mahoney / Data Dancers

                                                                cortland.mahoney@gmail.com

Artistic Infinity Mirrors with Hydra

Hydra is a livecode visuals framework using JavaScript in your browser.

You can use it to draw abstract shapes and colors; or import media; and even use a live cam!

We’ll focus on a camera source today to create an infinity mirror.

Sources & Outputs

Sources are things that contain visual objects. Like a triangle, or an image, or a camera.

Out of the box, Hydra comes with four empty sources (s0, s1, s2, and s3) for you to assign.

It also comes with four outputs. And output is like a canvas: It’s what lets you actually view the object! It is important to recognize that you can’t see the source until you send it out to an output. Like sources, hydra offers four empty outputs as well (o0, o1, o2, and o3).

To prepare a camera as a source, tell hydra that you want to use a camera by evaluating this code:

s0.initCam()

Your browser will pop up a dialogue asking which camera to use. Pick the one you want to stream. Now hydra is loading the data from your camera! But where is it?

We can’t see it yet. Let’s fix that by assigning it to an output. Write this code and evaluate it:

src(s0).out(o0)

Now your camera stream is visible on your screen!
To really use
hydra to its full potential, we should start modulating the camera’s input signal.

One way to do this is by mixing copies of the signal back into itself, but with some offset. We will also update the color of one of the signals to make the total view more interesting.

The blending mode describes how the two signals get mixed together. My favorite is diff, but there are a few options to pick from!

Blending modes. The examples on the back use “diff”. Try swapping that word with any of these for a fast and easy way to change it up!

add, sub, layer, mult, diff, blend, mask

Here is the complete code to produce a mixed camera feed signal:

s0.initCam()

src(s0)

  .diff(

      src(s0).color(0).scrollX(() => Math.sin(time/10))

  )

.out(o0)

Line by line explanation:

  1. Initialize the camera feed onto source 0 (s0)
  2. Get the signal s0 as an object source
  3. Mix it with some other source using the diff function
  1. Set s0 as the source
  2. Change the color to greyscale using color(0)
  3. Offset its position with scrollX() function using a function of time.
  1. Send the mixed (diff’d) signal to output 0 so you can see it!

Infinity Mirror

Now let’s kick it up a notch.
To turn this into an
infinity mirror, all you have to do is point your camera to the screen! This creates an infinite feedback loop. You don’t need to add any code because this is a natural phenomenon that works with both analog and digital video mixers.

Turn your camera towards the screen and watch the chaos beautifully unfold!


If you want to capture a
subject (like yourself, a friend, a pet, etc) in the infinity mirror you might have to reposition the camera setup a little bit.

Now that you have a basic understanding, let’s add another slightly more complex example.

This time we are going to put some content onto an “offscreen” output (o1) where we can’t see it yet. Using this technique lets us do complicated effects on o1, and simple blending on o0.  

You could technically do it all on one output. Using more than one output helps us keep the code easier to read and understand.

s0.initCam()

src(s0)

  .diff(

      src(s0).color(0).scrollX(() => Math.sin(time/10)).repeat(5,3)

  )

  .out(o1)

src(o1)

  .contrast()

  .diff(src(s0))

  .add(src(s0).scrollY(() => Math.sin(time/50)))

  .out(o0)

Line by line explanation:

  1. Initialize the camera feed onto source 0 (s0)
  2. Get the signal s0 as an object source
  3. Mix it with some other source using the diff function
  1. Set s0 as the source.
  2. Change the color to greyscale using color(0).
  3. Offset its horizontal position with scrollX() 
  1. Use a function of time to produce the offset value.
  1. Send the mixed (diff’d) signal to output 1 for further processing.
  2. Get the signal o1 as a source object.
  3. Change the contrast with the contrast() function
  4. Blend using the diff() function
  1. Get the signal s0 to use in the blend
  1. Blend using the add() function
  1. Get the signal s0 (again) to use (separately) in this blend
  1. Offset its vertical position with scrollY()
  1. Apply a function of time to get the offset value
  1. Send the final result to the visible output o0

https://data-dancers.github.io