Jitter Recipes: Book 4, Recipes 44-49

Recipe 48: PartyLights

General Principles

  • Creating an awesome particle physics generator with jit.gen
  • Using jit.gl.node and jit.gl.slab/pix for post-render effects on a scene
  • Creating a simple bloom filter

Commentary

Like anyone who spends a lot of time making visuals, I have a soft spot for particle effects. It’s so easy to make something dynamic and pretty with fairly economical means, and if you know where to connect an LFO or two, you can spend more time pounding your fist than twiddling knobs. In the back of my head, I’m always thinking about new ways to work with particles, and when jit.gen came along, I was ready to try. This recipe is an appeal to the most self-indulgent sort of particle effects, complete with feedback trails and a bloom effect. This is a crowd-pleaser, so turn on your projector, turn up the DJ, and get ready.

Ingredients

  • jit.gen
  • jit.gl.pix
  • jit.matrix
  • jit.gl.node
  • jit.gl.mesh
  • jit.gl.slab

Technique

First, to see what the patch can do, try some of the presets. Once you’ve had some fun, let’s switch into patching mode. The core of the patch is the jit.gen object that handles the particle generation and physics. Since particle physics relies on repeated transformation of points from frame to frame, we need some way to store the results of each calculation. Because jit.gen doesn’t have its own memory, we have to use an external jit.matrix object to feedback the results as input. To change the number of particles we can just change the size of the storage matrix.

Here’s a quick breeze through what’s happening in jit.gen. The first input contains a matrix of position and “life” values (x,y,z,life). For each frame, we add a velocity amount (second input) to the position of each particle to animate them. Each frame we also apply a friction calculation to the velocity values for more realistic motion. For “force” we just apply a uniform addition across the whole matrix. We could stop with just the position and velocity values, but to really push this into a more luscious effect, we also store a color value for each particle (third input). The great thing about using jit.gen is that we can keep adding other features to our particle system just by adding more inputs and outputs and deciding how they should change with each frame.

The really tricky part of this patch, and key to a really convincing particle system, is the management of particle life and death. This is done by storing a life value for each cell of the particle matrix in the 4th plane of the position matrix. This value is incremented each frame by a value calculated as 1./life. When the value reaches 1., the particle is reset by setting the logic of the ? operator to false, which passes whatever is in the right inlet. You’ll see that there is a ? object for every input/output, with the reset value going into the right.

Finally, to render the particles, we just draw them as big points in OpenGL. Notice that we aren’t rendering the particles directly to the screen, but rather we’re capturing it to a texture using jit.gl.node and then passing the captured texture through a blur and an additive blending jit.gl.pix patch. Also we use a jit.gl.slab in there for a feedback loop, so we get nice trails on our particles.

After the rendering, capturing, and post-processing, the final texture is passed to a jit.gl.videoplane that displays the final image. You will also notice there is a jit.gl.camera object in there to allow you to move around the particles in space.

DISCUSSION

16 Comments

Ricardo says:

Thanks. This is just what I have been looking for. But, how would I go about changing the ScrollyBrush, so that it does not scroll. The same features, but no scrolling downwards? Some pointers would be great. I am kind of new to Jitter.

ginger says:

Awesome! This is great!

Andrew Benson says:

Hi Ricardo. The scroll is controlled by the offset param. You can set it to 0 if you don’t want it to scroll. You can also just delete the ‘nearest’ part of the jit.pix patch and connect “in 2″ directly to the first inlet of “mix”.

Ricardo says:

Thank you so much!!!!!

60131 – 3D Media Studio II (Animated Theater) C4 » Advanced Interactivity with Max says:

[...] Jitter Recipe Books by Andrew Benson: A great set of “simple” Max patches for advanced video applications; excellent tutorials for advanced Jitter work. [...]

Maarten says:

This is great! The thing that mistified me was how to get a continuous line when setting the brush size smaller in Recipe 44?
Setting the brush size smaller leaves a lot of ‘holes’ between’ points, upping the metro doesn’t seem to fix it. What is a solution to this?

thanks, M

Andrew Benson says:

Hi Maarten,
Try using much smaller offset values and don’t move the mouse so fast. Smaller brushes cover less area, so it’s harder to maintain a smooth line.

Jeremy Bailey says:

getting the following error on recipe 48


gen_domain: jit.gen: [string "gen1.jit.cpp1"]:431: assertion failed!
jit_gen: Gen patcher not compiled

excited to get it working!

Andrew Benson says:

Sounds like you are probably using an older Max 6 version. Try updating and see if that clears it up.

Julien Bayle says:

I’d love to make this using java or JS :)

Francisco says:

Hi! and Thank you!
I get the msg from hit.anim.node “doesn’t understand “anchor”"
Any suggestions ? again, Thank you

K and E says:

We are trying to use a different input method other than a mouse and we are new to using Max Start. Our project is due on friday so PLEASE HELP ASAP :(

Andrew Benson says:

@Francisco @anchor was added in an update to Max 6. You might need to upgrade to the most recent available version on the site.

@K and E, The [route mouse] in ScrollyBrush can be replaced with anything that outputs a list of 2 values in a similar range (0-299) if you’d like different inputs to drive brush position

Arda says:

Thank you so much for the patch.

However, I couldn’t seem to find which object is triggering the particle burst. I am trying to sync the burst effect to the beat of the audio signal.

adriagil says:

Hi Andrew,

First thanks for your work and contributions!

I want to study your patch deeply because I want to create a similar drawing application but instead of drawing with an airbrush effect I want to do some watercolor realtime drawing.
I’ve found an interesting paper about watercolor simulation on http://grail.cs.washington.edu/pub/papers/curtis-1997-cgw.pdf
How can I start to translating the paper pseudocode into Max? I’m able to code in C++ but I don’t know how to do it using Max objects.
Is possible to open / code in Max without objects and patch cords and do it like other languages but using the Max Runtime?
Any consideration before starting the project?
Is there any better or easy aproach to achieve a watercolor simulation in Max (maybe using OpenGL shaders, Procedural shape growth, etc)?.

I’m quite new to Max environment so sorry if this is a stupid question.

In the other hand, I’ve opened your patch but I can’t get it work!
I’ve downloaded latest Max version 6.1.2 and when I open the patch I get the following errors:

clang: error line 3024 column 10: no matching function for call to "rgb_to_rgba"
jit_gen: Gen patcher not compiled

Why if I get other Gen patches running?
How I can debug the clang error? I’m used to debug apps but I don’t know how to “see” inline code (I’ve only worked in Max with patcher window).

Thanks a lot,
Adrian.

Leave a Reply