Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

The SHADER block

Every shader is a SHADER block with a name. Inside it go the settings it takes, each on a USE line, and then one WHEN DRAWING block: the code that runs for every pixel.

SCREEN 320, 240
SHADER "darker"
    USE NUMBER amount DEFAULT 0.5
    WHEN DRAWING
        c = IMAGE
        SET COLOR = RGBA(c.r * amount, c.g * amount, c.b * amount, c.a)
    END WHEN
END SHADER

LOADIMG "city.png", "city"
PUTIMAGE (32, 0), "city"
SET LAYER 0 !! shader("darker")
PAUSE

Here’s what each part does:

  • SHADER "darker" names it. The name is how a layer, a sprite or a behavior asks for it, and defining a second shader with the same name replaces the first.
  • USE NUMBER amount DEFAULT 0.5 is a setting. Your program can change it while the game runs, and DEFAULT is what it is until it does. The next chapter but four is all about settings.
  • WHEN DRAWING … END WHEN is the code. It runs once for every pixel.
  • IMAGE is the color the pixel was going to be: what’s drawn on the layer there, or the sprite’s picture.
  • SET COLOR = is the color it is instead.

SET LAYER 0 !! shader("darker") puts the shader on layer 0, and from then on everything on that layer goes through it, including what’s drawn later.

Only two kinds of line

Inside WHEN DRAWING there are exactly two kinds of line. A name and = makes or changes a variable of the shader’s own:

c = IMAGE
grey = (c.r + c.g + c.b) / 3.0

And SET COLOR = says what the pixel’s color is:

SET COLOR = RGBA(grey, grey, grey, c.a)

There’s no IF, no loops, no PRINT, no FUNCTION. That sounds like a lot to give up, and it isn’t: the chapter on choices shows how a shader decides things without them.

The lines run top to bottom, and a variable can be given a new value as you go. If there’s more than one SET COLOR, the last one wins:

SCREEN 320, 240
SHADER "last"
    WHEN DRAWING
        c = IMAGE
        c = c * 0.5
        SET COLOR = RGBA(1.0, 0.0, 0.0, 1.0)
        SET COLOR = RGBA(c.r, c.g, c.b, 1.0)
    END WHEN
END SHADER

LOADIMG "city.png", "city"
PUTIMAGE (32, 0), "city"
SET LAYER 0 !! shader("last")
PAUSE

The city comes out at half brightness, not red.

And a shader with no SET COLOR at all leaves every pixel as it was. That’s not useful by itself, but it’s a handy way to switch a shader off while you look for what’s wrong with it.

Comments

A comment in a shader starts with ', on a line of its own or at the end of one:

SCREEN 320, 240
SHADER "commented"
    ' Turn the picture upside down.
    WHEN DRAWING
        ' UV.y runs 0 at the top to 1 at the bottom, so this reads from the
        ' other end.
        SET COLOR = OWNTEXTURE(VEC2(UV.x, 1.0 - UV.y)) ' and that's all
    END WHEN
END SHADER

LOADIMG "city.png", "city"
PUTIMAGE (32, 0), "city"
SET LAYER 0 !! shader("commented")
PAUSE

The shader block is the one place in Crash BASIC 2 where // isn’t a comment. I hand the lines between SHADER and END SHADER to the shader language as you wrote them, and the shader language came from Crash BASIC 1, where a comment starts with '. So this stops, on the line with the //:

SCREEN 320, 240
SHADER "oops"
    WHEN DRAWING
        // Not a comment in here.
        SET COLOR = IMAGE
    END WHEN
END SHADER

Big and small letters

The shader language doesn’t mind how you write a word: SET COLOR, set color and Set Color are the same, and so are IMAGE, image and Image. So are your own variables: c and C are one variable.

SCREEN 320, 240
SHADER "casual"
    WHEN DRAWING
        Pixel = image
        set color = rgba(PIXEL.r, pixel.g, 0.0, 1.0)
    END WHEN
END SHADER

LOADIMG "city.png", "city"
PUTIMAGE (32, 0), "city"
SET LAYER 0 !! shader("casual")
PAUSE

This book writes the language’s own words in capitals and your names in small letters, so you can tell them apart at a glance.