Randomness
A shader has no RND that’s different every time: the same pixel has to come
out the same every frame, or the screen would boil. What it has instead is
RND(x, y): a number from 0 to 1 that looks random, made from x and y.
The same x and y always give the same number, and numbers next to each
other give numbers that have nothing to do with each other.
SCREEN 320, 240
SHADER "snow"
WHEN DRAWING
pixel = FLOOR(UV * SCREEN_SIZE)
n = RND(pixel.x, pixel.y)
SET COLOR = RGB(n, n, n)
END WHEN
END SHADER
SET LAYER 0 !! shader("snow")
PAUSE
An old television between stations, holding perfectly still: a random grey
for each of the game’s pixels. FLOOR(UV * SCREEN_SIZE) is which pixel this
is, counted in the game’s pixels, so every bit of the window that shows that
pixel gets the same number. RND(x) with one number works too, for a random
number along a line.
Making it move
Put TIME in, and it’s different every moment. FLOOR it first and it
changes in steps, which is the noise of a broken television rather than
a blur:
SCREEN 320, 240
SHADER "static"
USE NUMBER rate DEFAULT 12
WHEN DRAWING
frame = FLOOR(TIME * rate)
pixel = FLOOR(UV * SCREEN_SIZE)
n = RND(pixel.x + frame * 7.0, pixel.y + frame * 13.0)
SET COLOR = RGB(n, n, n)
END WHEN
END SHADER
SET LAYER 0 !! shader("static")
PAUSE
Twelve new screens of noise a second.
Random blocks
Give RND the same numbers for a whole patch of pixels and the whole patch
gets the same random number. FLOOR(UV * 10.0) is the same for every pixel
in a tenth of the layer each way, so this picks a random color for each
block:
SCREEN 320, 240
SHADER "blocks"
WHEN DRAWING
cell = FLOOR(UV * 10.0)
r = RND(cell.x, cell.y)
g = RND(cell.x + 50.0, cell.y)
b = RND(cell.x, cell.y + 50.0)
SET COLOR = RGB(r, g, b)
END WHEN
END SHADER
SET LAYER 0 !! shader("blocks")
PAUSE
Adding 50 to one of the numbers gives an unrelated random number for the same block, so its red, green and blue don’t all come out the same.
Dissolving
Random numbers make good dissolves. Each pixel gets its own random number, and goes when the dissolve’s progress passes it:
SCREEN 320, 240
SHADER "dissolve"
USE NUMBER gone DEFAULT 0.5
WHEN DRAWING
c = IMAGE
n = RND(FLOOR(UV.x * 64.0), FLOOR(UV.y * 64.0))
keep = STEP(gone, n)
SET COLOR = RGBA(c.r, c.g, c.b, c.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("dissolve") shader_params({gone: 0.5})
SHOW SPRITE 0
PAUSE
Half the hero’s pixels are gone. Turn gone from 0 up to 1 and the hero
crumbles away.
Crash-tan’s Tip:
RNDis made of aSINof a big number, which is as random as a shader can cheaply get. It’s for looks, not for dice: give it numbers in the thousands and it gets less random, because the graphics chip’s numbers have only so many digits. Keep what you give it small.