Pixel Bender: Sphere Redux

Tweaks and improvements to the previous diced sphere Pixel Bender kernel.

Just click Go. Really.

cubes04.swf

click for
http://omino.com/pixelblog/wp-content/uploads/2008/11/cubes04.swf

As before, it uses a sort of orthogonal ray tracing technique. The depth into a particular cell determines the amount of darkness. In this sense it’s a short cut for HDRI and radiosity in that, simply, the further into the “cave”, the darker it is. Seems to work.

Pixel Bender: Waves

Everyone loves sine waves.

waves.swf

click for
http://omino.com/pixelblog/wp-content/uploads/2008/11/waves.swf

In the above .swf, a Pixel Bender kernel is summing three sine waves at various frequencies and amplitudes, and drawing it in three colors. Each pixel gets either black, or one of the three colors, depending how close it is to the waveform.

The distance to the waveform is measured only vertically, though, so the peaks get extended in a strange, sort of 60’s/70’s op-ish way.

Pixel Bender: Circles, Squares, Lines, & Metadata

This post will show a handful of simple tricks for “drawing” using Pixel Bender. That’s not what it’s for, especially in Flash. But it’s still interesting to see how it’s done.

But first, the demo:

viewerDemo1.swf

click for
http://omino.com/pixelblog/wp-content/uploads/2008/10/viewerDemo1.swf

And I’m sure the handy tabs across the top for the source code won’t escape your attention, either!

Pixel Bender Metadata

In the demo above, you can notice a couple of things. Some of the parameters are drawn as sliders, but also there’s a checkbox, some color pickers, and, in the drawing area, some draggable spots. This is done by a collusion between the Pixel Bender kernel, and the Flash viewer code. Here’s the parameters from the Pixel Bender kernel:

    parameter float3 backgroundColor<kind:"color";defaultValue:float3(1,1,1);>;

    parameter float spotRadius<defaultValue:50.0;minValue:1.0;maxValue:800.0;>;
    parameter float3 spotColor<kind:"color";defaultValue:float3(0,0,0);>;
    parameter float spotSquare<kind:"checkbox";defaultValue:0.0;>;

    // This parameter just gets poked with the rendering dimensions, always
    // Doesn't get shown to user. In my custom viewer, that is.
    parameter float2 dims<kind:"dstsize";defaultValue:float2(300,300);>;

    // "point" means it lives somewhere in the image, as a coordinate.
    parameter float2 lineStart<kind:"point";minValue:float2(0,0);maxValue:float2(400,400);defaultValue:float2(10,10);>;
    parameter float2 lineEnd<kind:"point";minValue:float2(0,0);maxValue:float2(400,400);defaultValue:float2(30,100);>;
    parameter float lineWidth<minValue:0.5;maxValue:30.0;defaultValue:2.0;>;

I’ve added a kind property to some of the parameters. Pixel Bender ignores it, but in ActionScript we can access it as part of the ShaderData. For example, it is true that shader.data.spotSquare.kind == "checkbox".

These aren’t special or magic! My Pixel Bender kernel says it, and my Flash viewer reads it. It’s a handy trick, if you happen to be in control of both parts.

How to Draw a Circle

It’s so easy! Given a center and a radius, you check each pixel to see if it’s within that distance of the center. Like so:

        float d = distance(co,center);
        if(d < spotRadius)
            dst = spotColor;

How to Draw a Square

This is ever so slightly trickier. Again, with a center and a radius, we want to see that both the x- and y-distances from the center are within the radius. Like so:

        float d = max(abs(co.x - center.x),abs(co.y - center.y));
        if(d < spotRadius)
            dst = spotColor;

How to Draw a Line

Now this is getting mathy. In an earlier post about Gradient fills, I derive an equation for “position between two points”, like so:

t = dot(uv,xy) / dot(xy,xy)

where a line segment is given by the endpoints (0,0) and (x,y), and some screen spot is given by (u,v). If t is within the range 0 to 1, then (u,v) is somewhere along that line segment if it’s drawn infinitely wide. That’s a short stubby line no matter how you slice it.

To constrain the width of the line, we need to know how far from the center (u,v) is, which is given by:

d = abs(length(xy) * dot(uv,yx) / dot(xy,xy))

(If you followed the Gradient post, it’s the right half — the y-component — of the final 2×2 matrix, times the length of the line, for scaling. But it’s not important.)

So, the combined code to draw a line between two endpoints, with a particular line width, and square-capped ends, is:

       // and now, a bit of fun math, as we plot a line between two points.
        float2 uv = co - lineStart;
        float2 xy = lineEnd - lineStart;
        float xy2 = dot(xy,xy);
        float g = dot(uv,xy) / xy2;
        // if we are between the two points, then g is between 0 and 1.
        float dl = abs(dot(uv,float2(-xy.y,xy.x)) / xy2 * length(xy));
        // dl is now the distance, in pixels, from outCoord to the line

        // if we're between the endpoints and close enough, draw.
        if(g >= 0.0 && g <= 1.0 && dl < lineWidth / 2.0)
            dst = float3(1,0,0); // draw the line in RED.

Ridiculous?

To reiterate: This is a ridiculous use for Pixel Bender. But the ideas may come in handy. Doing something with a squarish area-of-influence isn’t so outlandash… and while a solid-colored line is a bit unsubtle, a shaded field or beam area begins to seem plausible. Pixel Bender is so powerful and flexible, I know we’re going to continue to see unexpected and novel results from it.

Pixel Bender: Fun With Cubes 2 (a Dicing Sphere)

Back to the cubes. This Pixel Bender generator shows a volume subdivided into cubes, and constrained to a spherical limit.

cubes03.swf

click for
http://omino.com/pixelblog/wp-content/uploads/2008/10/cubes03.swf

And here’s the source code.

/src/pixel_bender/cubes/cubes03.pbk in new window download /src/pixel_bender/cubes/cubes03.pbk to file hide /src/pixel_bender/cubes/cubes03.pbk

Can’t wait to start incorporating this stuff into After Effects CS4… but haven’t uncovered any details on exactly how Pixel Bender integrates to it. Presumably some magic parameters may tell you things like the source or dest extant, and maybe you can add “typing” information to parameters. Looking for links… since it may be a little while before I can afford to upgrade.

Pixel Bender: Fun With Cubes 1

In which I present instances of a family of closed-cell geometric objects which are computationally trivial to render.

The Concept

Imagine moving a plane through a three dimensional mesh of cubes.

checkerSquare320.mp4

click for
http://omino.com/pixelblog/content/2008/pixelBender/checkerSquare320.mp4

You start by rotating the plane to your liking. That is, for each pixel on the plane (since that is our rendering reference point) we rotate and translate it as we like, from (x, y, 0) to (x’, y’, z’). To find out which “cell” we’re in, we just look at the integer parts of the prime-coordinates. In the animation above, the cells have been “checkered” by whether their integer coordinates’ sum is even or odd. (Actually, I just used LightWave’s 3d checker texture function. But you get the idea.)

Drawing the checkerboard is easy. Drawing some depth in the cubes is only a little bit trickier. We need a perpendicular vector from the plane, to cast a ray, so we also rotate the perpendicular vector (0,0,1) by the same amount. Then we project that ray from the fractional position within the cell until it hits one of the 6 walls of the cube. Lastly, we give a non-optical depth cue based on how far the intersected wall is.

The Implementation

Here’s the math part of the rotation. There’s probably an easier way to get the 3-axis rotation matrix… But this works.

// concatenate three simple rotations to spinM
float3x3 spinXM = float3x3(1,0,0,0,cos(spin.x),spin.x,0,-sin(spin.x),cos(spin.x));
float3x3 spinYM = float3x3(cos(spin.y),0,sin(spin.y),0,1,0,-sin(spin.y),0,cos(spin.y));
float3x3 spinZM = float3x3(cos(spin.z), sin(spin.z), 0,-sin(spin.z), cos(spin.z), 0, 0, 0, 1 );
float3x3 spinM = spinXM * spinYM * spinZM;

float2 center = float2(400,500) / 2.0; // YUCK! hardcoded for my blog entry.
float2 oc = (outCoord() - center) / zoom; // adjust "input coordinates"

// we rotate the requested coordinate by 3 axes, giving the
// R3 point on the plane of the screen (after the mesh is turnt)
float3 p = float3(oc.x,oc.y,0) * spinM; //oc.x * axis1 + oc.y * axis2;

// perp is our viewing line, straight down from the screen.
float3 perp = float3(0,0,1) * spinM;

Here is an interactive demo of the algorithm, in Flash and Pixel Bender. (I added a full screen button, whee!)

cubes01.swf

click for
http://omino.com/pixelblog/content/2008/pixelBender/cubes01.swf

And here is the Pixel Bender kernel:

/src/pixel_bender/cubes/cubes01.pbk in new window download /src/pixel_bender/cubes/cubes01.pbk to file hide /src/pixel_bender/cubes/cubes01.pbk

And for reference, here is the template for the Flash displayer, compilable by mxmlc.

/src/pixel_bender/cubes/pbTemplate.mxml in new window download /src/pixel_bender/cubes/pbTemplate.mxml to file hide /src/pixel_bender/cubes/pbTemplate.mxml

Flex trivia: stage.addEventListener(FullScreenEvent.FULL_SCREEN,screenChange);
works from mx:Application applicationComplete because the UI and display list is all instanced, but not from mx:Application creationComplete which happens a little bit earlier.

Next up: Suppose we didn’t intersect with a simple plane… !

Pixel Bender: My First Flash Program

Since I love After Effects, I need to learn Pixel Bender. To talk about Pixel Bender in this blog, it sure is handy that the new Flash Player can show it, live. But first I had to learn Flash. Darn!

So, below is a program written for Flex, compiled with Adobe’s free mxmlc command line tool. Requires Flash 10 (currently in beta). It incorporates a simple Pixel Bender kernel to draw on a rectangular area. It doesn’t use an input image.

For reference, here’s the snippet of Flex code that simply fills in an area with the Bended Pixels:

        // "draw" is the name of a UIComponent instance,
        // and "shader" is a Pixel Bender kernel instance.
        var g:Graphics = draw.graphics;
        g.clear();
        g.beginShaderFill(shader);
        var m:Number = 20;
        g.drawRect(m,m,draw.width - 2*m,draw.height - 2*m);
        g.endFill();

And, below is the swf, live, in action. Click the “animate” checkbox for most fun.

flatGenerator.swf

click for
http://omino.com/pixelblog/content/2008/pixelBender/flatGenerator.swf

As you can see, it displays each of the kernel’s numeric parameters as a slider. Since it knows the min- and max- of each parameter, we can randomize and animate them, which is much more fun that twiddling the slider by hand, yes? It also suggests some of the possibilities when animated in After Effects CS4.

Importantly, this Flex program discerns the parameter values and ranges at run time, so you can pop in another kernel, recompile, and play some more.

Here’s the kernel code. Just a bunch of Math fun… really it was just to test out the Flash displayer, but it came out kind of psychedelic.

/src/pixel_bender/cubes/flatGenerator.pbk in new window download /src/pixel_bender/cubes/flatGenerator.pbk to file hide /src/pixel_bender/cubes/flatGenerator.pbk

And here’s the Flex program. To pop in our own kernel, just alter the Embed line.

/src/pixel_bender/cubes/pbTemplate.mxml in new window download /src/pixel_bender/cubes/pbTemplate.mxml to file hide /src/pixel_bender/cubes/pbTemplate.mxml

Stay tuned for some Fun With Cubes.

Pixel Bender: Flash vs After Effects

This blog usually isn’t for industry commentary and such, but you know, when Adobe starts moving the pixels around in new ways I do get excited.

Adobe’s “Pixel Bender” framework — which facilitates fast, cross-platform, single-frame image-processing filters — will be available in Flash and After Effects, and presumably other imaging apps as well. (It should be useful in Photoshop and Illustrator and Premiere.)

Adobe developer Tinic Uro reveals some important differences between Flash 10’s support, and After Effects’.

In particular, on Flash, a Pixel Bender filter runs on the host CPU, not the graphics card! But not to worry, they’re still mighty fast; they’re compiled to native Intel code on the fly. Ah, right, yes, they’ll be slooow on PPC Macintoshes. So it goes.

On After Effects, however, they’ll run on the GPU.

Couple of relevant links:

Adobe Flash 10 beta download
Adobe Pixel Bender Toolkit download
Mr Doob, some guy with a lot of cool Pixel Bender examples (found via AEPortal, thanks!)
Pixelero’s cool examples, too (also via aeportal)