Archive for December, 2008


Rendering Volume Data Set

More info to follow.


Voronoi Volumes

It occurred to me yesterday that, it would be possible to render ‘slices’ of the Voronoi texture on a series of sprites arranged in 3D space, to give a kind of volume rendering effect.

I’ve thought about this before, but it’s always meant running some kind of shader inside an Iterator, and the whole thing would crawl to a halt.

My brainwave yesterday was that I could use the Queue to eliminate the need for the texture to be generated inside the Iterator. All you have to do is change the texture, and every change made adds another item to the Queue, and you end up with a 3D map of the changes to the texture over time, as each new image pushes the Queue along and each sprite is updated with a new texture.

Here are some examples of my cheap volume-rendering in action:

The macro/DOF type effect is simply the result of applying a circular vignette to the alpha, so it fades out a little around the edges. I’ve also added a small square vignette around the edges of the texture to help smooth things out when the volume is rotated. Of course, since it’s just a stack of 2D sprites (50, in this case), when viewed near edge-on, the illusion of a 3-dimensional volume disappears, and you get all kinds of nasty glitching. If I ever decide to finalise this experiment, and setup proper controls, I’ll limit rotation so you’ll never see this though.


tb Quartz Composer Clips

For those not in the know, Clips are a really handy way of keeping a library of commonly-used macros, ready for instantly adding to your composition. Unlike Virtual Patches though, Clips appear as ordinary macros when added to your composition, so you can see what’s inside them. The other difference is that once added, they lose all links with the original Clip, so if you update the Clip, it’s not automatically updated in all the compositions that use it.

I’ve found myself using Clips more and more lately, and have built up a library of macros I commonly use. I don’t know how useful they’ll be to anyone else, but someone out there might find a use for some of them, so I thought I’d put them out there, just in case.

To use them, copy the contents of the zip file to
~/Library/Application Support/Apple/Developer Tools/Quartz Composer/Clips
(where /~ is your Home Folder). You should then be able to see them in the patch browser, with descriptions.

‘’ in widget.

tb Quartz Composer Clips

tb Quartz Composer Clips


Cell Noise CIFilter (2D Version)

I’ve been a fan of Cellular or Voronoi noise for a while now, and have investigated a couple of different ways of producing it. While looking for something else yesterday, I came across this post on on that very subject.

The author proposes a method for generating Voronoi textures entirely on the GPU, so I thought I’d give it a go.

Here’s what I came up with. I’ve left the old code in there, but commented-out so you can see how I tweaked it to work in a CIFilter. The main change to Flavien’s code was that I converted the effect from 3D to 2D, since the extra dimension isn’t needed in a Core Image filter. There are probably extra optimisations that can be made, but my understanding of the original code isn’t complete, so I’m not sure what they would be.

Voronoi / Cell shader

Code from:

CIFilter translation and Quartz Composer setup
toneburst 2008

//vec4 gpuGetCell3D(const in int x, const in int y, const in int z)
vec3 gpuGetCell3D(const in int x, const in int y, const in vec2 dims, const in sampler img)
float u = float(x + y * 31) / 256.0;
float v = float(y – x * 3) / 256.0;
// Make sure sample is not take outside noise image area
vec2 uvFract = fract(vec2(u, v));

// Sample noise image
return unpremultiply(sample(img, uvFract * dims)).rgb;

//vec2 gpuCellNoise3D(const in vec3 xyz)
float gpuCellNoise3D(const in vec2 xy, const in vec2 dims, const in sampler img)
//int xi = int(floor(xyz.x));
int xi = int(floor(xy.x));
//int yi = int(floor(xyz.y));
int yi = int(floor(xy.y));
//int zi = int(floor(xyz.z));

//float xf = xyz.x – float(xi);
float xf = xy.x – float(xi);
//float yf = xyz.y – float(yi);
float yf = xy.y – float(yi);
//float zf = xyz.z – float(zi);

float dist1 = 9999999.0;
//float dist2 = 9999999.0;
//vec3 cell;
vec2 cell;

for (int z = -1; z <= 1; z++) { for (int y = -1; y <= 1; y++) { for (int x = -1; x <= 1; x++) { //cell = gpuGetCell3D(xi+x,yi+y,zi+z).xyz; cell = gpuGetCell3D(xi+x,yi+y,dims,img).xy; cell.x += (float(x) - xf); cell.y += (float(y) - yf); //cell.z += (float(z) - zf); float dist = dot(cell, cell); dist1 = (dist < dist1) ? dist : dist1; /*if (dist < dist1) { dist2 = dist1; dist1 = dist; } else if (dist < dist2) { dist2 = dist; }*/ } } } //return vec2(sqrt(dist1), sqrt(dist2)); return sqrt(dist1); } kernel vec4 voronoi(sampler image, vec2 Scale, float Type) { vec2 dims = samplerSize(image); vec2 xyNorm = samplerCoord(image) / dims; xyNorm *= Scale; float shade = gpuCellNoise3D(xyNorm,dims,image); return vec4(vec3(shade),1.0); }[/code] The keen observer might spot that a lot of texture-lookups are happening per-pixel, so it's not particularly fast. To alter the pattern generated, you'd can feed it an animated noise texture, maybe by passing a Random Generator patch through an Image Crop. You could then automate the Crop X and Crop Y parameters and pipe the result into the 'image' input of the CIFilter. [gallery orderby="post_name"]


New Audio-Reactive Thing

Inspired by the famous 3D waveform display of the 80’s Fairlight CMI sampler.
Requires Kineme Audio Tools and GL Tools plugins.

I must start using the Queue patch more! This one uses a Queue to create the movement of the waves. Each frame, coordinates for a new waveform line are created by a JavaScript patch, as a series of X, Y and Z points, with their Z-positions modulated by data from the Audio Tools Waveform output structure.

This array of points then goes into a Queue.

Each line is created by a single iteration of the Iterator patch, and each iteration picks a different item out of the Queue- so iteration 0 picks the data from the first Queue slot (ie the most recent), the second iteration gets data from the second slot, and so on.

The points data for each line is then fed into a Kineme GL Line Structure patch, which joins the points to form a line.

Then, it’s just a matter of spreading the lines out along the Y axis. This was done with a 3D Transformation patch inside the Iterator, to save having to mess around with JavaScript to change the Y-position of each point individually.

I stuck the whole thing inside another 3D Transformation patch, to rotate it and make the lines appear to recede into the distance. I also added an Interpolator patch, driven by Iterator Position and linked to the Alpha of each line, to make them fade out as they got further away, for a kind of fog effect.

Because the data in the Queue is continually being pushed along to the next slot by new incoming data, you get the effect of the waveform moving, as the waveform ‘jumps’ from one line to the next.

The only slight annoyance is that the speed of movement is entirely down to the frame-rate the QTZ is running at. I may investigate artificially slowing down the framerate (as psonice has mentioned doing with some of his demos) to make it more consistent. I could also sync the update rate to VDMX’s tempo, which would make it more jerky, but if it’s tempo-synced, you probably won’t notice.

‘tb Fairlight Waveform 1.01.qtz’ in the download widget.


Watery Audio-Reactive VDMX Courtesy of L1nk-dna

l1nk-dna has kindly donated a VDMX file using a new QTZ I converted from an original VVVV shader by Digital Slaves. I’m not quite sure if the conversion worked properly, since I’ve never managed to get VVVV fully-working, but it looks quite nice, anyway.

l1nk-dna has done a nice setup using the Audio Analysis plugin in VDMX, and several layers with feedback taps. He’s also asked me to mention that it’s ‘a bit rough around the edges’, but it looks cool to me!

‘l1nk-dna + toneburst Fake Wave’ in the widget

Note: you might have to relink the QTZ. If so, it’s in the same folder as the VDMX file itself.

Here’s an example clip, from the man himself:


Error: Twitter did not respond. Please wait a few minutes and refresh this page.

December 2008
« Nov   Jan »


Blog Stats

  • 465,901 hits