A cookbook
Shaders worth stealing. Each one is whole: put it in your game, give it to a layer or a sprite, and change the numbers until it’s yours.
Sepia
An old photograph: grey first, then tinted brown.
SCREEN 320, 240
SHADER "sepia"
WHEN DRAWING
c = IMAGE
g = c.r * 0.3 + c.g * 0.59 + c.b * 0.11
SET COLOR = RGBA(MIN(g * 1.2, 1.0), g, g * 0.8, c.a)
END WHEN
END SHADER
LOADIMG "city.png", "city"
PUTIMAGE (32, 0), "city"
SET LAYER 0 !! shader("sepia")
PAUSE
Negative
Every color turned to its opposite, and the alpha left alone so a sprite keeps its shape.
SCREEN 320, 240
SHADER "negative"
WHEN DRAWING
c = IMAGE
SET COLOR = RGBA(1.0 - c.r, 1.0 - c.g, 1.0 - c.b, c.a)
END WHEN
END SHADER
LOADIMG "city.png", "city"
PUTIMAGE (32, 0), "city"
SET LAYER 0 !! shader("negative")
PAUSE
Pixelate
Big pixels: every pixel in a block reads the same spot, the block’s corner.
Turn blocks down for bigger ones.
SCREEN 320, 240
SHADER "pixelate"
USE NUMBER blocks DEFAULT 40
WHEN DRAWING
SET COLOR = OWNTEXTURE(FLOOR(UV * blocks) / blocks)
END WHEN
END SHADER
LOADIMG "city.png", "city"
PUTIMAGE (32, 0), "city"
SET LAYER 0 !! shader("pixelate")
PAUSE
Old monitor
Dark lines across the screen, and the red and blue each pulled a little to one side, the way a cheap old monitor smears them.
SCREEN 320, 240
SHADER "monitor"
USE NUMBER split DEFAULT 1.0
USE NUMBER lines DEFAULT 0.3
WHEN DRAWING
red = OWNTEXTURE(UV + PX(split, 0.0))
green = IMAGE
blue = OWNTEXTURE(UV - PX(split, 0.0))
row = STEP(0.5, FRACT(UV.y * SCREEN_SIZE.y / 2.0))
shade = 1.0 - lines * row
SET COLOR = RGBA(red.r * shade, green.g * shade, blue.b * shade, green.a)
END WHEN
END SHADER
LOADIMG "city.png", "city"
PUTIMAGE (32, 0), "city"
SET LAYER 0 !! shader("monitor")
PAUSE
UV.y * SCREEN_SIZE.y is which row of the layer’s pixels this is, so every
other pair of rows is darker, however big the window is.
Under water
Each row of the picture swings from side to side, a little later than the one above it.
SCREEN 320, 240
SHADER "underwater"
USE NUMBER size DEFAULT 2.0
USE NUMBER waves DEFAULT 20.0
WHEN DRAWING
swing = SIN(UV.y * waves + TIME * 3.0) * size
c = OWNTEXTURE(UV + PX(swing, 0.0))
SET COLOR = MIX(c, RGBA(0.0, 0.3, 0.6, c.a), 0.25)
END WHEN
END SHADER
LOADIMG "city.png", "city"
PUTIMAGE (32, 0), "city"
SET LAYER 0 !! shader("underwater")
PAUSE
size is in pixels, by way of PX, so it’s the same swing on any layer.
Heat haze
Like under water, but small and fast, and only near the bottom, over a fire or a hot road.
SCREEN 320, 240
SHADER "haze"
WHEN DRAWING
low = SMOOTHSTEP(0.5, 1.0, UV.y)
swing = SIN(UV.y * 90.0 + TIME * 12.0) * 1.5 * low
SET COLOR = OWNTEXTURE(UV + PX(swing, 0.0))
END WHEN
END SHADER
LOADIMG "city.png", "city"
PUTIMAGE (32, 0), "city"
SET LAYER 0 !! shader("haze")
PAUSE
Hit flash
A sprite that’s hit goes white and fades back, from a behavior, so your program only has to say when.
SCREEN 320, 240
SHADER "white"
USE NUMBER amount DEFAULT 0
WHEN DRAWING
c = IMAGE
SET COLOR = MIX(c, RGBA(1.0, 1.0, 1.0, c.a), amount)
END WHEN
END SHADER
BEHAVIOR "hit"
USE SHADER "white" !! param("amount") start(1) to(0) duration(12)
END BEHAVIOR
LOADIMG "hero.png", "hero"
ENABLE SPRITE 0
SET SPRITE 0 !! image("hero") x(140) y(100) scale((3, 3))
SHOW SPRITE 0
DO
IF COOLDOWN(45)
SET SPRITE 0 !! behavior("hit")
END IF
LOOP
Burning away
A dissolve with a glowing edge: each pixel has a random number, goes when
gone passes it, and glows orange just before it does.
SCREEN 320, 240
SHADER "burn"
USE NUMBER gone DEFAULT 0
WHEN DRAWING
c = IMAGE
n = RND(FLOOR(UV.x * 40.0), FLOOR(UV.y * 40.0))
keep = STEP(gone, n)
glow = keep * (1.0 - STEP(gone + 0.08, n))
lit = MIX(c, RGBA(1.0, 0.5, 0.1, c.a), glow)
SET COLOR = RGBA(lit.r, lit.g, lit.b, lit.a * keep)
END WHEN
END SHADER
LOADIMG "hero.png", "hero"
ENABLE SPRITE 0
SET SPRITE 0 !! image("hero") x(140) y(100) scale((3, 3)) shader("burn")
SHOW SPRITE 0
gone = 0
DO
IF COOLDOWN(1)
gone = gone + 0.01
IF gone > 1.1
gone = 0
END IF
SET SPRITE 0 !! shader("burn") shader_params({gone: gone})
END IF
LOOP
keep is whether the pixel’s still there, and glow is whether it’s still
there but won’t be for much longer: there, and not past gone + 0.08 yet.
Glitch
Most of the time, nothing. Every so often, for a moment, rows of the picture jump sideways and the colors come apart.
SCREEN 320, 240
SHADER "glitch"
USE NUMBER often DEFAULT 0.15
WHEN DRAWING
moment = FLOOR(TIME * 8.0)
on = 1.0 - STEP(often, RND(moment))
row = FLOOR(UV.y * 24.0)
jump = (RND(row, moment) - 0.5) * 30.0 * on
moved = UV + PX(jump, 0.0)
red = OWNTEXTURE(moved + PX(4.0 * on, 0.0))
rest = OWNTEXTURE(moved)
SET COLOR = RGBA(red.r, rest.g, rest.b, rest.a)
END WHEN
END SHADER
LOADIMG "city.png", "city"
PUTIMAGE (32, 0), "city"
SET LAYER 0 !! shader("glitch")
PAUSE
Eight times a second, moment changes, and RND(moment) decides whether
this eighth of a second glitches: on is 1 about 15% of the time. While
it’s on, each of 24 bands of rows jumps by its own random amount, and the
red is read from four pixels further along than the rest.