From 76f0065d8b930aad3d9928fbfbfeac091db17fef Mon Sep 17 00:00:00 2001 From: Eryn Wells Date: Sun, 4 Nov 2018 22:30:06 -0500 Subject: [PATCH] Generate some pseudo-random numbers with a PRNG class in the shaders. --- Terrain2/TerrainAlgorithms.metal | 42 +++++++++++++++++++++++++++++--- 1 file changed, 39 insertions(+), 3 deletions(-) diff --git a/Terrain2/TerrainAlgorithms.metal b/Terrain2/TerrainAlgorithms.metal index a355873..80deb6d 100644 --- a/Terrain2/TerrainAlgorithms.metal +++ b/Terrain2/TerrainAlgorithms.metal @@ -7,9 +7,42 @@ // #include +#include #include "ShaderTypes.h" using namespace metal; +/// A pseudo-random number generator providing several algorithms. +/// - http://reedbeta.com/blog/quick-and-easy-gpu-random-numbers-in-d3d11/ +struct PRNG { + PRNG(uint seed) : mSeed(wangHash(seed)) { } + + /// Generate a random unsigned integer using a linear congruential generator. + uint lcg() { + mSeed = 1664525 * mSeed + 1013904223; + return mSeed; + } + + /// Generate a random unsigned integer using the Xorshift algorithm from George Marsaglia's paper. + uint xorShift() { + mSeed ^= (mSeed << 13); + mSeed ^= (mSeed >> 17); + mSeed ^= (mSeed << 5); + return mSeed; + } + + uint wangHash(uint seed) { + seed = (seed ^ 61) ^ (seed >> 16); + seed *= 9; + seed = seed ^ (seed >> 4); + seed *= 0x27d4eb2d; + seed = seed ^ (seed >> 15); + return seed; + } + +private: + uint mSeed; +}; + kernel void zeroKernel(texture2d outTexture [[texture(GeneratorTextureIndexOut)]], uint2 tid [[thread_position_in_grid]]) { @@ -17,8 +50,11 @@ kernel void zeroKernel(texture2d outTexture [[texture(Gene } kernel void randomKernel(texture2d outTexture [[texture(GeneratorTextureIndexOut)]], - uint2 tid [[thread_position_in_grid]]) + uint2 tid [[thread_position_in_grid]], + uint2 tgid [[threadgroup_position_in_grid]]) { - float x = 2.0 * M_PI_F * (tid.x / 128.0); - outTexture.write(sin(x), tid); + PRNG rng(tid.x * tid.y); + uint r = rng.lcg(); + float x = float(r * (1.0 / float(UINT_MAX))) * 0.5f; + outTexture.write(x, tid); }