Layers, sprites and shapes
A shader goes on three kinds of thing, each with its own SET, and each
with the same three modifiers: shader to put one on, shader_params for
its settings, and clear_shader to take it off. (Only a layer takes
shader_params by itself, to change the settings of a shader that’s already
on; a sprite or a shape is given shader again.)
Layers
On a layer, a shader runs over the whole layer as it goes to the screen: everything drawn on it, and the empty parts too.
SCREEN 320, 240
SHADER "night"
USE NUMBER dark DEFAULT 0.6
WHEN DRAWING
c = IMAGE
SET COLOR = RGBA(c.r * (1.0 - dark), c.g * (1.0 - dark), c.b, c.a)
END WHEN
END SHADER
CREATE LAYER 1, 320, 240
LOADIMG "city.png", "city"
PUTIMAGE (32, 0), "city"
SET LAYER 1
CIRCLE (160, 120), 40, 14, 14
SET LAYER 0 !! shader("night")
PAUSE
The city on layer 0 goes dark and blue, and the yellow circle on layer 1 doesn’t: a shader on a layer is for that layer only. Put the same shader on layer 1 as well and both go dark.
A shader on a layer doesn’t change what’s drawn on it, only how it looks.
Take it off with SET LAYER 0 !! clear_shader and the city is as bright
as it ever was.
Sprites
On a sprite, a shader runs over the sprite’s picture, at the size and place it’s drawn. Moving, turning and scaling the sprite move the shader with it.
SCREEN 320, 240
SHADER "outline"
USE NUMBER red DEFAULT 1.0
USE NUMBER green DEFAULT 1.0
USE NUMBER blue DEFAULT 0.0
WHEN DRAWING
c = IMAGE
right = OWNTEXTURE(UV + PX(1.0, 0.0))
left = OWNTEXTURE(UV - PX(1.0, 0.0))
below = OWNTEXTURE(UV + PX(0.0, 1.0))
above = OWNTEXTURE(UV - PX(0.0, 1.0))
around = MAX(MAX(right.a, left.a), MAX(below.a, above.a))
edge = around * (1.0 - c.a)
SET COLOR = MIX(c, RGBA(red, green, blue, 1.0), edge)
END WHEN
END SHADER
LOADIMG "hero.png", "hero"
ENABLE SPRITE 0
SET SPRITE 0 !! image("hero") x(140) y(100) scale((3, 3)) shader("outline")
!! rotate(15)
SHOW SPRITE 0
PAUSE
A pixel that’s see-through itself, but has a solid pixel beside it, is on the outside edge of the hero, and gets painted yellow. The hero is tilted, and the outline tilts with it.
Three things to know about shaders on sprites:
- Alpha. Whatever alpha your shader hands back, it’s multiplied by the sprite’s own. A sprite fading out with its shader on fades out with it, and your shader doesn’t have to know.
- The edge. A shader only runs on the sprite’s own rectangle. An outline has to fit inside the picture, which is why the one above is drawn on the see-through pixels around the hero, not outside them. A picture with no see-through border has nowhere for an outline to go.
- Frames. On an animated sprite,
UVandPXare the frame’s, andOWNTEXTUREstays inside the frame: reading past its edge gets the edge, not the next frame along.
Shapes
A polygon takes a shader with SET POLYGON, the same way, as long as it has
a picture: give it one with texture. IMAGE is the picture, and UV runs
across the box around the shape, from its leftmost point to its rightmost
and its top to its bottom.
SCREEN 320, 240
SHADER "sunset"
WHEN DRAWING
top = RGB(1.0, 0.8, 0.2)
bottom = RGB(0.8, 0.1, 0.4)
SET COLOR = MIX(top, bottom, UV.y)
END WHEN
END SHADER
LOADIMG "city.png", "city"
hill = mutation([(40, 200), (160, 60), (280, 200)])
SET POLYGON 0 !! bind(hill) texture("city") shader("sunset")
PAUSE
A triangle filled with a sunset, gold at its peak and pink at its foot. The
city it was given is never seen, because this shader doesn’t read IMAGE;
but without a picture, a shape is drawn in its fill color and the shader
doesn’t run on it.
Taking a shader off
clear_shader takes it off, and a layer or sprite goes back to how it was.
SCREEN 320, 240
SHADER "upside"
WHEN DRAWING
SET COLOR = OWNTEXTURE(VEC2(UV.x, 1.0 - UV.y))
END WHEN
END SHADER
LOADIMG "hero.png", "hero"
ENABLE SPRITE 0
SET SPRITE 0 !! image("hero") x(140) y(100) scale((3, 3)) shader("upside")
SHOW SPRITE 0
upside = TRUE
DO
IF COOLDOWN(60)
upside = NOT upside
IF upside
SET SPRITE 0 !! shader("upside")
ELSE
SET SPRITE 0 !! clear_shader
END IF
END IF
LOOP
The hero stands on its head for a second, then the right way up for a second, and so on.