On this page:
7.3.1 effect-stack
7.3.2 transition-stack
7.3.3 layers
7.3.3.1 An example
7.3.3.2 Explicit inputs
7.3.4 remap-time

7.3 Combining effects

The effect framework offers a few expressive ways to combine effects to create new types of effects. The primitive effects can be kept simple only if the means to combine them exists. This section is about how to combine simple effects to create more sophisticated ones. It is worth familiarizing yourself with effect-stack and layers because you’ll be using them a lot.

All these functions which transform one or a collection of effects into an effect are collectively referred to as effect combinators and fall into the category of higher order functions.

7.3.1 effect-stack

Say you want to create a “photo on the wall” look for the pictures in the muvee. You’ll need to shrink down the picture a bit so the whole thing fits into the screen and rotate it a bit to give the appearance of casual placement on the wall. To create this look, you’ll need to combine the Scale and Rotate effects as follows -
(effect-stack
    (effect "Rotate" (A)
        (param "degrees" 15.0))
    (effect "Scale" (A)
        (param "x" 0.7)
        (param "y" 0.7)))

You can read an effect-stack expression from top to bottom.
(effect-stack
    (effect "Rotate" (A)
        (param "degrees" 15.0))
    rest-of-the-stuff)
should be read as

The rest-of-the-stuff is rotated by 15 degrees.

Here is another way to write the same effect combination -
(effect-stack
    (effect "Rotate" (A)
        (param "degrees" 15.0))
    (effect-stack
        (effect "Scale" (A)
            (param "x" 0.7)
            (param "y" 0.7))))

i.e. the rest-of-the-stuff can itself be seen as an effect stack.

7.3.2 transition-stack

Similar to effect-stack except that the last entry in the stack must be a transition - i.e. a two-input effect and the other must be one-input effects.

7.3.3 layers

The layers primitive combinator is the way to put together a scene in parts. For example, you might want to present a single picture with four different colorations, Andy Warhol style. layers will help you compose such compound scenes.

A layers composition has the following form -
(layers input-pattern
        effect1
        effect2
        ....
        effectN)

The input-pattern has the same form and purpose as the input pattern specification for effects. The most important point to note here is that effect1, effect2 etc. must be zero-input effects. We will use the term layer to refer to zero-input effects hereafter.

7.3.3.1 An example

Say we want to place four space-shifted copies of a picture or video with decreasing transparencies to create a motion-blurred appearance.

We can write down our intention like this -
(layers (A)
  ;                     input x-shift opacity
  (shifted-translucent   A      0.0     0.6)
  (shifted-translucent   A      0.2     0.4)
  (shifted-translucent   A      0.4     0.2)
  (shifted-translucent   A      0.6     0.1))
where we expect the shifted-translucent function to somehow compute a zero-input effect specification that operates on the layer’s single input A. Knowing what we expect this function to do, we can proceed to elaborate it -
(define (shifted-translucent A x-shift opacity)
  (effect-stack
    (effect "Alpha" (Shifted)
      (param "Alpha" opacity))
    (effect "Translate" (Scaled)
      (param "x" x-shift))
    (effect "Scale" ()
      (input 0 A)        ; A comes from function parameter
      (param "x" 0.4)
      (param "y" 0.4))))

Here is what the composition looks like -

7.3.3.2 Explicit inputs

(input index the-input)

Knowing that the shifted-translucent function should compute a zero-input effect tells us that the last entry of the effect-stack that we use must be a zero-input effect as well.

The Scale effect is normally a one-input effect. We therefore turn it into a layer for the above example by explicitly specifying its input as what was given to the make-shifted-translucent function as its A parameter. We do that using the input form which has the following general structure -

The inputs to an effect are numbered from 0. Therefore 0 for index means the first input, 1 means the second input, etc.

The ability to explicitly specify inputs is essential to many kinds of layer compositions such as what we did above.

7.3.4 remap-time

(remap-time fstart fstop fx)  effect
  fstart : fraction
  fstop : fraction
  fx : effect
remap-time doesn’t combine effects, but it transforms one effect into another that operates for only a part of the full span of an effect. For example, you might want to author a segment effect, but want it to operate only for the middle 1/3 of the segment. You can restrict the time interval for such purposes using remap-time. For example -

(define muvee-segment-effect
  (remap-time 1/3 2/3 (effect "Sepia" (A))))

- gives you a segment effect that operates for only the middle 1/3 of a segment.

fstart and fstop are fractional values indicating the fraction of the full interval [start, stop) for which the effect should apply.

fstart is in the range [0.0, fstop) and

fstop is in the range (fstart, 1.0].

remap-time doesn’t combine two or more effects, but is useful when combining two or more effects using, say, layers.