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:

http://www.gamedev.net/community/forums/mod/journal/journal.asp?jn=263350

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"]

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.

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…

a|x

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