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 GameDev.net 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"]


3 Responses to “Cell Noise CIFilter (2D Version)”

  1. December 20, 2008 at 1:28 am

    You might find some interesting results feeding textures like this into something like GL Height Field or the Rutt Etra to create fake generative landscapes of a sort. If only I could get something similar going that I could actually use with a GLSL shader… though the Kineme3D is kind of solving the issue of “landscape” with the plane and warp patches. I just wish I could generate from texture, and then use with a shader…. “wahhhhhhhhhhhh”(crying like a little baby).

    Futurismo had that really cool example of waving “grass” by layering and shifting alpha’s of the noise generator (to my memory). I have used that theory as a noise generator for GLSL and CI patches in testing and it is interesting.

    • 2 toneburst
      December 20, 2008 at 12:20 pm

      Yeah, I know. You can get texture lookup in the vertex shader working by running the image through the Kineme QCImage > OpenCV Image patch, then converting back to a QCImage with the OpenCV Image > QCImage patch. It’s quite slow though, and apparently, VS texture lookup guarantees CPU-fallback, as none of Apple’s drivers for ATI or NVIDIA cards support this feature.

      The other technique you mention sounds intriguing. I guess you could use noise function set to Perlin Noise to control the points of a Kineme Line Structure, and you might get a nice waving effect. Interesting…


  2. 3 jersmi
    February 14, 2009 at 10:50 pm

    Thanks so much for the code to this filter. Let you know if anything particularly interesting pops up along the way! 🙂

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )


Connecting to %s


December 2008
« Nov   Jan »


Blog Stats

  • 481,663 hits

%d bloggers like this: