Sunday, October 22, 2006

Curves: Color

I wrote a post about "section radius" recently, which involved drawing curves with a discreet number of anchor points. The application there was a more robust replacement for the Taper attribute of prims. Of course, the usefulness of using a curve instead of one or two numbers is not limited to Taper alonethere are innumerable other uses for them, completely aside from the Object attributes.

One of my backburner obsessions for the past few months has been color. (No surprise there, given that I'm currently enrolled in a color theory class, I suppose.) In particular and with regard to SL, two aspects have been on my mind. The first is using a base color as input to an algorithm to generate related colors (lighter tint, darker shade, blue-shifted, red-shifted, visual complement...). The second is blending between two colors in a smooth and visual appealing fashion.

This is where curves come in.

You see, colors can be represented in a computer program as multidimensional vectors, usually 3-vectors: the x component corresponds to the intensity of the red color channel, the y to the green, and the z to the blue. For example, [1.0, 0.0, 0.0] is pure red, [0.8, 0.5, 0.0] is an orangey color, [1.0, 1.0, 1.0] is pure white, and [0.0, 0.0, 0.0] is pure black.* (In additive color models, such as light, the presence of all colors is white. In subtractive color models, such as pigment or paint, the presence of all colors is black, at least theoretically; in practice, mixing all your paint colors together usually makes a grayish brown.)

* NB: for convenience, I am denoting vectors with square brackets, [ ], instead of the usual angled brackets, < >, which are also used to denote HTML tags, causing the silly Blogger software to interpret my vectors as malformed HTML code. Yes, I am too lazy to search-replace them with the symbol codes.

So suppose we want to blend between, say, [1.0, 0.0, 0.0] red and [0.0, 0.0, 1.0] blue. The simplest way to do this would be a straight linear blend. Since positions in space, like colors, can be represented as 3-vectors, a linear blend is equivalent to moving in a straight line from point A to point B.

We could write an algorithm thusly, with a being the starting color/point, b being the ending point, and t being a number between 0.0 and 1.0, representing our progress moving from a to b (e.g. t = 0.5 means we are exactly halfway between the two; t = 0.25 means we are ¼ of the total distance from a, and so ¾ of the distance from b):

line(t, a, b) = a + t * (b - a)
Here are some sample points using our algorithm to blend between red and blue:
line(0.00, [1,0,0], [0,0,1]) = [1.00, 0.00, 0.00]
line(0.25, [1,0,0], [0,0,1]) = [0.75, 0.00, 0.25]
line(0.50, [1,0,0], [0,0,1]) = [0.50, 0.00, 0.50]
line(0.75, [1,0,0], [0,0,1]) = [0.25, 0.00, 0.75]
line(1.00, [1,0,0], [0,0,1]) = [0.00, 0.00, 1.00]




To be ct'd in Issue #452: Pierre Bézier and Paul de Casteljau unite once more in... O What a Twisted Curve We Weave!! Don't miss it, gang!
  --JA


3 comments:

Keoni Chavez said...

I like eating paste.

Unknown said...

So, I says to Mabel, I says...

Roenik Newell said...

That was a fun read :)


Reminds me of this:

Dim black2white_Brsh As New _
LinearGradientBrush( _
New Point(x, y), New Point(x + wid, y), _
Color.Black, Color.White)


Look forward to Part II!