Stateful Randomness in Shaders

I often find myself needing good random numbers in shaders, but this gets messy when you want to generate a bunch of different ones for each pixel. To get around this, I’m using a genuinely awful hack in DaeForth.

Implementation #

:m rand-given-seed (| seed |)
        [ seed seed 1141 * sin ]
        [ 12.9898 78.233 ]
    dot sin 43758.5453 * fract
@float global =pixel-seed
real-position /rand-given-seed \+ =pixel-seed
:m seed .7 rand-given-seed ;
:m gen-seed
    seed =>cur-seed
    cur-seed rand-given-seed =>next-seed
    [ next-seed ] &seed def-macro
:m next-random gen-seed pixel-seed * store rand-given-seed ;

Each time you call next-random it generates a new, high-quality random number for the given pixel. Importantly, it does so with low overhead at runtime!

Example #

For instance, this generates two random colors and then mixes them randomly (for a total of 7 invocations):

        [ next-random next-random next-random ]
        [ next-random next-random next-random ]
] ->fragColor


The majority of the RNG process actually occurs at compile-time, leaving each invocation with something along the lines of:

fract((sin(dot(vec2(tmp_0, sin((tmp_0) * (1141.))), vec2(12.9898, 78.233)))) * (43758.547));

How does it work? #

The magic here lies in the fact that it’s redefining the seed macro for each iteration. This makes the compiler generate the next seed value. Because they don’t depend in any way on the pixel seed (which can only be known at runtime, obviously) it gets boiled down to a single float per invocation.

For instance, you can see the 7 ‘seeds’ used in the example here:

    tmp_0 = (0.86328125) * (pixel_seed);
    tmp_1 = (0.19335938) * (pixel_seed);
    tmp_2 = (0.7783203) * (pixel_seed);
    tmp_3 = (0.55859375) * (pixel_seed);
    tmp_4 = (0.26171875) * (pixel_seed);
    tmp_5 = (0.7519531) * (pixel_seed);
    tmp_6 = (0.42773438) * (pixel_seed);

Happy hacking,

- Sera Brocious (Daeken)


Now read this

CTF Design 101

I’m frequently asked how I go about building a successful CTF and while I’ve tried to answer this in the past (generally on Twitter), I’ve never actually gone in-depth on it. So today we’re going to talk about what makes a CTF... Continue →