Particle wipe generator

by eevee

What is this?

This is a tool for generating particle wipes, which you might have seen as transitions between parts of video games. I don't know if that's what they're actually called; I've never seen them referred to by name!

It's faster to try it out than to read an explanation. Click "Generate", then hit the play button at the bottom!

How do I use it?

When confronted by a bunch of buttons and knobs, my preferred approach is to start hitting them and see what happens. But if you're not like me:

First, choose a particle to use.

Note: A particle can be nearly any shape, but any hollow part on the inside will be ignored. A good rule of thumb is that if you start from the center and draw a line to the outside edge, it should never cross the edge of the shape more than once. So a star is fine, but a crescent moon will come out goofy.

Next, choose the size of the grid. All of the patterns are based on chopping the screen into a grid and having a particle grow from the center of each cell; the only difference is in the order of the cells.

A smaller grid will give you a pretty chunky transition, but a larger grid may make it harder to tell what the particle is. You can also make the grid a different aspect ratio from the screen, which can have interesting effects, especially with patterns like spiral. (The particle's aspect ratio is always preserved.)

At this point you can also set the delay, which controls how long a cell can grow before the next cell can start appearing. It's measured as a fraction of the time a particle takes to grow and cover its entire cell, so setting it to 0 will drop the pattern entirely and make every particle grow at the same time, whereas setting it to 1 will wait for a cell to fill completely before even starting the next one. Leaving this at a small but nonzero value is a good idea.

Next, choose the pattern you want and fiddle with the settings. The preview on the right gives you a rough idea of how the transition plays out: it'll start with the black cells and finish with the white cells. Several patterns are available:

In addition, there are several modifiers you can use with any pattern:

Finally, check that the preview looks good, and click Generate! It might take a few seconds; please be patient. Then play back your transition to see if it's to your liking.

You can change the colors the example transition uses, or even provide your own before/after images!

How do I put this in a game?

The important thing this tool generates is the mask, which you can find to the right of the player. Right-click it to save it somewhere.

If you're using Ren'Py, you can feed the mask to ImageDissolve and then use it like any other named transition. Done!

If you're using anything else, you may need to write your own shader. It's pretty easy! Here's a trimmed-down and commented-up version of the shader used on this very page:

    precision mediump float;

    uniform sampler2D mask;
    uniform sampler2D before;
    uniform sampler2D after;
    // This is the progress through the transition, from 0 to 1
    uniform float t;
    // This is the "ramp" slider from under the player
    uniform float ramp;

    // These are the texture coordinates from the vertex shader.  Depending on
    // the exact effect you want, you might want to use screen coordinates, or
    // something else entirely.
    varying vec2 tex_coords;

    // I suppose this wouldn't be necessary if you had premultiplied alpha, but
    // who does that, right?
    vec4 alpha_composite(vec4 top, vec4 bottom) {
        float alpha = top.a + bottom.a * (1.0 - top.a);
        return vec4((top.rgb * top.a + bottom.rgb * (bottom.a * (1.0 - top.a))) / alpha, alpha);
    }

    void main() {
        // Sample the same spot in before, after, and the mask itself...
        vec4 before_pixel = texture2D(before, tex_coords);
        vec4 after_pixel = texture2D(after, tex_coords);
        vec4 mask_pixel = texture2D(mask, tex_coords);
        // Collect all the mask channels together into a single value
        float discriminator = mask_pixel.r + mask_pixel.g / 256.0 + mask_pixel.b / 65536.0;
        // The ramp adds a little fuzz around the current value.  This scales t
        // so that 0 means just before the first hint of the ramp appears;
        // otherwise, half a ramp would abruptly appear when the effect starts.
        float scaled_t = t * (1.0 + ramp * 2.0) - ramp;
        // This is the alpha of the "after" image.
        float alpha = clamp((scaled_t - discriminator) / ramp + 0.5, 0.0, 1.0);
        // Multiply, in case it already has its own alpha.
        after_pixel.a *= alpha;
        // Finally, composite!
        // You might also want to draw the "after" image on top of some
        // existing scene, rather than combining before/after in a single
        // shader.  In that case, just use after_pixel directly here, and
        // delete all the "before" stuff.
        gl_FragColor = alpha_composite(after_pixel, before_pixel);
    }

Note: The above example shader doesn't support a halo. It's not hard to add; peek at my source code!

How does it work?

The generated mask defines the order in which pixels appear. That's all.

Hmm, I should explain this more, sometime.

FAQ

That means "frequently apprehended questions".

Why does the mask look so weird?
Usually masks like this are grayscale, but that limits them to only 256 values. I've used all three color channels here, which increases that range to 16,777,216 values! Don't worry, it should still work with Ren'Py or a shader that expects a grayscale image — they'll just read the red channel and ignore the extra precision, which is like rounding off extra decimal places.

Particle (256×256)
Preview

Result in action

Total playback time: 0.25 seconds / 15 frames

Ramp (length of gradient between before/after): 4/256

Before
Generated mask
After