Colors
In a shader, a color is four numbers: red, green, blue and alpha, each from
0 to 1. Not 0 to 255 like a PSET, and not a palette number like a
CIRCLE: 0 is none, 1 is all of it, and 0.5 is halfway. Alpha is how solid
the color is, from 0, not there at all, to 1, solid.
RGBA(r, g, b, a) makes one, and RGB(r, g, b) makes one that’s solid.
SCREEN 320, 240
SHADER "orange"
WHEN DRAWING
SET COLOR = RGB(1.0, 0.5, 0.0)
END WHEN
END SHADER
SET LAYER 0 !! shader("orange")
PAUSE
Taking a color apart
A color’s parts are .r, .g, .b and .a. Put a color in a variable and
you can read them one by one:
SCREEN 320, 240
SHADER "swap"
WHEN DRAWING
c = IMAGE
SET COLOR = RGBA(c.b, c.r, c.g, c.a)
END WHEN
END SHADER
LOADIMG "city.png", "city"
PUTIMAGE (32, 0), "city"
SET LAYER 0 !! shader("swap")
PAUSE
The red goes where the green was, the green where the blue was, and the blue where the red was. The purple city turns gold.
You can take more than one part at once, in any order, and the same part more
than once: c.bgr is the color’s blue, green and red, in that order, and
c.rrr is three of its red. That’s called a swizzle. Three parts make a
color with no alpha, so give it one back before SET COLOR sees it:
SCREEN 320, 240
SHADER "reds"
WHEN DRAWING
c = IMAGE
r = c.rrr
SET COLOR = RGBA(r.r, r.g, r.b, c.a)
END WHEN
END SHADER
LOADIMG "city.png", "city"
PUTIMAGE (32, 0), "city"
SET LAYER 0 !! shader("reds")
PAUSE
The city in black and white, by how red each pixel was. Four parts are a
whole color, so SET COLOR = IMAGE.bgra is a color too.
Sums with colors
A color times a number makes every part of it bigger or smaller at once,
alpha too. A color times a color multiplies part by part, which is how you
tint something: a pixel times RGB(1.0, 0.6, 0.6) keeps all its red and
loses some of its green and blue.
SCREEN 320, 240
SHADER "rosy"
WHEN DRAWING
SET COLOR = IMAGE * RGB(1.0, 0.6, 0.6)
END WHEN
END SHADER
LOADIMG "city.png", "city"
PUTIMAGE (32, 0), "city"
SET LAYER 0 !! shader("rosy")
PAUSE
+ and - work part by part too, so c + RGBA(0.2, 0.2, 0.2, 0.0) lightens
a color, and RGBA(1.0, 1.0, 1.0, 1.0) - c is its opposite. Careful with
that one: alpha gets turned around along with the rest, and a solid pixel
becomes see-through. The cookbook’s invert keeps c.a as it was.
A part can go above 1 or below 0 in the middle of a sum, and that’s fine. The
screen shows anything over 1 as 1 and anything under 0 as 0, and CLAMP
(next chapter but one) holds a number inside a range when you’d like to keep
it there yourself.
From one color to another
MIX(a, b, amount) is the color part of the way from a to b: all a at
0, all b at 1, and halfway between at 0.5. It’s the one function you’ll
use more than any other.
SCREEN 320, 240
SHADER "fog"
USE NUMBER thick DEFAULT 0.5
WHEN DRAWING
c = IMAGE
SET COLOR = MIX(c, RGBA(0.7, 0.7, 0.8, c.a), thick)
END WHEN
END SHADER
LOADIMG "city.png", "city"
PUTIMAGE (32, 0), "city"
SET LAYER 0 !! shader("fog")
PAUSE
The city half lost in grey fog. The fog’s alpha is c.a, the pixel’s own, so
the fog is exactly as solid as what it covers.
Crash-tan’s Tip: Keep
c.ain mind on sprites. A sprite is a rectangle, and the parts of it around the character are pixels with an alpha of 0. A shader that hands back a solid color for those pixels paints the whole rectangle. Keeping the pixel’s own alpha keeps the shape.
Grey
How bright a color looks is mostly its green, a good deal of its red and a little of its blue. Adding them up in those amounts gives its grey:
SCREEN 320, 240
SHADER "grey"
WHEN DRAWING
c = IMAGE
g = c.r * 0.3 + c.g * 0.59 + c.b * 0.11
SET COLOR = RGBA(g, g, g, c.a)
END WHEN
END SHADER
LOADIMG "city.png", "city"
PUTIMAGE (32, 0), "city"
SET LAYER 0 !! shader("grey")
PAUSE
The plain average, (c.r + c.g + c.b) / 3.0, works too, but the blues come
out too bright and the greens too dark next to how your eye sees them.