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
    cur-seed
;
: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 ]
        next-random
    mix
    1
] ->fragColor

randomness.png

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)

 
10
Kudos
 
10
Kudos

Now read this

Steal This Idea

This blog post will exist as a living document of ideas – some very fleshed out, some barely more than a concept – which I would love to implement if I had 15 of me. Unfortunately, there’s just the one (for now) and I don’t have time to... Continue →