Two Illustrator Scripts

Here’s a pair of Illustrator scripts I’ve had up for a while, but this is the first time I’ve posted examples. Also, Javier Enciso of www.formaestudio.com in Uruguay spotted a bug in the triangle script, which is now fixed.

Both available at http://omino.com/sw/ominoAdobeScriptsSuite/.

Circular Gauge (circularGauge.jsx)

circularGauge.jpg

This script draws numbers and tick-marks to resemble a circular gauge. It lands up in its own layer, and the text and ticks are in their own group, ready for tweaking. I use it to make pretty machines in Second Life. A bit of emboss and off you go.

Triangle By Sides (triangleBySides.jsx)

triangleBySides.jpg

I can’t remember what I needed this for, but it was exactly what I needed at the time. Self explanatory!

Found Graphic Design, Penang

Hello from balmy Penang, Malaysia!

My Northern California employer, a well-known FPGA vendor, has an office here in Penang Malaysia. I got permission to “telecommute” from here for a couple of months. Today is just cooling down, it’s 5pm and about 80F outside, with a chance of rain. Same weather year round.

Not much in the way of pixels going on in this part of the world… but I did stumble upon this bit of remarkable graphic design work, on some signage atop Penang Hill, showing roads, hiking trails, and such.

Penang Hill Map Detail

Just look at that! That amazing plotter-font, and what’s that OR gate doing there? And lovingly aged by time, itself. This is the real deal.

here’s the whole sign.

Penang Hill map

Flex: Simple Visualizer

Well I’ve gone way off target, and presently am having a little fun with Flex*. Here’s an audio player experiment. Just for fun. Terrible code. You know how it is. I think you need to click it to start it. Yeah.

aud02.swf

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

Source code follows.

/src/flex/aud02.mxml in new window download /src/flex/aud02.mxml to file hide /src/flex/aud02.mxml

*If I’ve got the nomenclature right, Flex refers to ActionScript code which uses MXML code structure and is compiled by Adobe’s freely available MXMLC compiler and is playable by the Flash browser plugin. But maybe not. I’m a bit confused by the names. Anyway, it’s fun to code.

Rehi All! Rewelcome to Pixel Blog

Hello seekers!

I’ve been getting a fair amount of traffic lately, mostly from Pixel Bender searches and a few references from forums and other blogs. And the number of subscribers is steadily growing. I guess some of the stuff here is useful to someone. Hooray, I say!

(And of course by “fair amount of traffic” I don’t mean, like, enough hire an editor or start selling ad space. My ISP isn’t complaining yet about the load. I mean, enough traffic that you and I can still enjoy an intimate little shared pixel experience, as told with words and numbers.)

So this post is mostly just a quick blog reintroduction. And below is a cool little video I did last year that I’ve been meaning to document. Ok, let’s go.

accentSpotsW.jpg

Reintroduction

I started this blog a bit over a year ago, focusing mostly on After Effects techniques and scripts. Adobe After Effects is just about my favorite piece of software ever. So clean and elegant, so complete, and rather delightfully ROCK SOLID. I’m a software engineer myself, and can appreciate just how monumental that simple truth is.

Lately I’ve been having GREAT FUN with Adobe Pixel Bender. It’s so satisfying to rapidly implement a complex function and see it in action. Also: math. Yay.

Perhaps prematurely, I’m thinking in this coming year of 2009, I’ll be getting back to After Effects and techniques… and of course announcements of updates to my free plugins, scripts, and Pixel Bender kernels. If this is the sort of thing you like, too, please consider subscribing.

accentSpotsB.jpg

A Retro-tv Treatment

And now, some pixels. Here’s a little video I did last year as part of a “fundraiser” for my friend Briya. She injured her ankle playing roller derby in Santa Cruz, and we helped pay for her ambulance ride.

onTv400b.mov

click for
/pixelblog/content/2008/misc/onTv400b.mov

I grew up staring at our black and white tv set, and tried to capture that feeling here. I think, often, various “retro” image treatments are too aggressive on the degradation. Black and white tv in the 1960’s was actually quite sharp! I tried to keep that feeling here. Here’s the recipe I used.

  1. Character generator. Old tv production had only a few effects available. I used a “character generator” here, white text at about 80% opacity. In the olden days, they rarely used shadow or background to enforce contrast; if the text was over something light-colored, it was just harder to read, sorry!
  2. Picture in picture. I also drop in a rectangular insert image, flat. Notice both the insert and the text only flash, no fading or morphing. That came later.
  3. The telethon look. This was the fun part, of course. I videotaped about 45 seconds each of three different actors sitting at my kitchen table, in front of our red curtain. That’s it! In After Effects, these are shoved next to each other and lined up in rows. It’s amazing how forgiving our eyes are. Yes, you can see that it’s all wrong. But it’s also oh-so-right.
  4. Curved glass tube. I added some arbitrary mesh distortion, suggestive of a glass picture tube. But tubes also get magnetized this way and that. (Or at least, in the 1960’s, mine did, because I played with magnets on it.) It adds an interesting travel to the image.
  5. Transmission loss. To add “ringing” and “aliasing” to the image, something I keenly remember from seeing television, I used my plugin called omino_diffusion, superimposed slightly over the original and blurred. It somewhat simulates the analog behavior of errors and their correction, since it proceeds left to right just like the scanning of the vacuum tube.
  6. Brevity. And of course, the most important trick here is to keep it short, to reduce the time one might have to ponder the image and question it too closely…
  7. I had worked up a “tv-turning-off” dotsweep, also. There’s something wonderfully dramatic about the old CRT dotfall… Modern tv’s just “turn off” and that’s that, but the old disappearing dot was an event providing real closure. But for this piece, I went with looping.

    And good night.

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: Crazy Spots

I was trying to do something else. But, as you well know, sometimes bugs are really cool. Here’s my bug of the night. Click Go, once, and Scramble a few times.

crazyspots.swf

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

Geometrical interpretation: a perfectly nonreflective sphere is in each cubical cell, getting cross-sected just like the cubes.

And here’s the source code. It’s based on “cubes” from a few posts back.

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

Pixel Bender: A Gradient… and Some Math

Featuring mix(), clamp(), and dot().

Very often I need a simple linear-gradient in After Effects, and end up sing the four-color gradient because that’s all I can find. And so, here, for your perusal, is a Pixel Bender implementation of a Linear Gradient Generator.

After that, we’ll see the code, and after that, a quick review of the math.

Here is the .swf. (With some improvements on the Pixel Bender viewer — you can drag any float2 parameters as points, now.)

gradient.swf

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

Isn’t that fun? Well, I’m easily amused.

The Code

Here’s the Pixel Bender code.



kernel Gradient
{
    output pixel4 dst;
    parameter float2 p1<minValue:float2(0,0);maxValue:float2(400,400);defaultValue:float2(10,10);>;
    parameter float2 p2<minValue:float2(0,0);maxValue:float2(400,400);defaultValue:float2(130,130);>;

    parameter float3 color1<defaultValue:float3(0,0,0);>;
    parameter float3 color2<defaultValue:float3(1,1,1);>;

    void evaluatePixel()
    {
        float2 co = outCoord();

        // shift everything relative to p1.
        float2 uv = co - p1;
        float2 xy = p2 - p1;

        // the math.
        float g = dot(uv,xy) / dot(xy,xy);
        g = clamp(g,0.0,1.0);

        // the color.
        dst.a = 1.0;
        dst.rgb = mix(color1,color2,g);
    }
}

The Math

I’m ok at math, but not always fluent in it. I can remember what a matrix is, but not necessarily exactly what a cross-product is. Maybe you’re like me. In which case this quick run through the math and logic behind the gradient fill will be quite useful in your own Pixel Bender bending!

And be assured, a few pages of high-school-algebra-style scribblings, and the occasional google (How do I invert a rotation again? What’s the formula for perspective?) really can lead to workable results. Good clean fun!

Let’s go.

Consider a trivial gradient, where our two control points are at (0,0) and (1,0). That would be easy! Just take the x-value of any pixel, and that’s your color. (That is, the position on the ramp between your two gradient colors.)

trivialGradient.png

By the way, this picture is from Ron Avitzur’s “Graphing Calculator”. The story of its development is legendary; less well known is that it’s actually a very powerful and useful tool.

I found the easiest way to think about a general two-point gradient was to ask, “How do we rotate and scale our control points back to this trivial gradient?” And let’s assume that the first control point is always at (0,0).

Here is matrix for a basic rotation, which moves any input point by a rotation around (0,0):

gradientEq1.jpg[1]

A rotate-and-scale matrix looks like that, times a constant on each element.

We want to think of our general gradient as a transformation on the trivial gradient. Let’s say our second control point is (X,Y), and our first control point is (0,0) as mentioned above. The rotate-and-scale matrix being applied, conceptually, is:

gradientEq2.jpg[2]

To figure out the 0-to-1 trivial position of any of our input points, we need to invert it. A matrix inversion looks like:

gradientEq3.jpg[3]

So, we invert the second equation [2] by plugging it in to [3] and get:

gradientEq4.jpg[4]

Now, let’s call each pixel position of our output (U,V). For our gradient, we actually don’t care about the resulting Y position; just X gives us our gradient value. So we get:

gradientEq5.jpg[5]

Now, the definition of the dot product of (A1,A2,A3,…) and (B1,B2,B3,…) is (A1B1 + A2B2 + A3B3 + …). So, from the above, UV+XY is, conveniently, (U,V) dot (X,Y). Similarly, X2 + Y2 is (X,Y) dot (X,Y).

And now, when you read this part of the code a second time, it should be much clearer what’s going on:

    void evaluatePixel() {
        float2 co = outCoord();

        // shift everything relative to p1.
        float2 uv = co - p1;
        float2 xy = p2 - p1;

        // the math.
        float g = dot(uv,xy) / dot(xy,xy);
        g = clamp(g,0.0,1.0);

        // the color.
        dst.a = 1.0;
        dst.rgb = mix(color1,color2,g);
    }

Simple and useful!

Next up, soon, more cubes.

« Previous Page« Previous entries « Previous Page · Next Page » Next entries »Next Page »