Posted by: pixelero | June 12, 2008

Pixel Bender: HexCells

Pixel Bender -filter for tiling with regular hexagons, and as a tutorial a couple of words to explain how this hexagonalization was done:

// petri­(dot)le­skinen[a­t]aalto­(dot)­fi
// Espoo, Finland, 25 Feb, 2008 – June 2008

<languageVersion: 1.0;>
kernel HexCells
< namespace : “Hex cells – not just pixels”;
vendor : “Petri Leskinen”;
version : 1;
description : “Hexagonal Tiling”;


parameter float size
minValue: float(1);
maxValue: float(200);
defaultValue: float(50);
description: “Hexagon Size”;
parameter float2 base
minValue: float2(-200,-200);
maxValue: float2(800,500);
defaultValue: float2(400,250);
description: “base point”;
>;// some constants needed for hexagon maths
const float sqrt3 = 1.7320508076;
const float halfSqrt3 = 0.866025404;input image4 img;
output pixel4pxl;void evaluatePixel()
// Tiling by counting a distance to two regular grids,
// and choosing the sample point of the closer one
// Scales of this transformation are ‘size’ in x-direction
// and sqrt(3)*size in y-direction

float2 grid = float2(size,sqrt3*size);

// First grid ( like red dots in the above image )
// to get regular ‘pixelation’ we first divide by grid size,
// apply ‘floor’ and then multiply back

float2 po1 = floor((outCoord()-base)/grid+0.5);
po1 = po1*grid +base -outCoord();

// squared distance to a center point of that
// (we only compare the distances, so no reason applying ‘heavy’ sqrt-operation )
float dst1 = po1.x*po1.x + po1.y*po1.y;

// Same thing with the Second grid (blue dots):
// base point here is in the middle of first grid
float2 base2 = base+size*float2(0.5,halfSqrt3);

float2 po2 = floor((outCoord()-base2)/grid+0.5);
po2 = po2*grid +base2 -outCoord();

// second distance
float dst2 = po2.x*po2.x + po2.y*po2.y;

// pick the closer point for sampling :

po1= (dst1<dst2) ? po1 : po2;
pxl= sampleNearest(img, po1+outCoord());




PB-bytecode in Adobe Exchange


DEMO (for Flash Player 10 beta) featuring also FileReference.load() and .save() – up’n’download your own picture to player ! ps. If you try save, do not overwrite an older file, it has a know bug. … and here’s an hexsample of same image saved and loaded a couple of times


I used Kevin Goldsmith’s PB HTML formatter for code hilighting – although pasting to this site didn’t support all the tabs …

When it comes to the algorithm for hexagonal tiling as explained above, there might be some ‘simplier’ ways of achieving it – as maths it’s ancient stuff. Anyway, when I first tried googling for more info and perhaps some code snippets, somehow I didn’t came up with any generally useful examples, in case of pixel manipulation algorithm. Nevertheless I did find a whole lot of inspirating stuff such as Spidrons or more on uniform tilings. So where next ?


‘Pingback’ : Brooks Andrus has a pb-demo showing plenty of pb-filters collected around the net, including HexCells.


  1. once again a nice one, petri.

  2. i am wondering how can i apply the script in the pixel bender. can u help me with it.pls.

  3. @zack: you can either copy-paste the code from my post – or just download the pbk:

    • thanx a lot man…

  4. […] seconds. In this example we transition “to” each state using a modified version of the Hexagonal Tiling shader written by Petri […]

  5. […] […]

  6. […] you’d like to understand tiling further, pixelero did a good article about it. there’s also this wikipedia […]

  7. Hi! Nice filter too.
    Did you try to make antialiasing on edges?

    • Thanks for your comments everyone.
      @Bell, no, I haven’t tried that … but I did try to add a solid border between the cells.

      I think supersampling would be one solution for antialiasing … count the values of several points inside a pixel and average those.

      • What about this:

        add new parameter:

        parameter float feather

        and calculate result:

        float feather2 = feather * feather * size / 10.0;
        float m = smoothStep(-feather2, feather2, dst1 – dst2);

        pixel4 px1 = sampleNearest(img, po1 + outCoord());
        pixel4 px2 = sampleNearest(img, po2 + outCoord());

        pxl = mix(px1, px2, m);

  8. […] principle of doing that with code is to first create a regular hexagonal tiling. Get the integer coordinates for current hexagon and evaluate the ‘magic’ modulo […]

Leave a Reply

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

You are commenting using your 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


%d bloggers like this: