Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- //-----------------------------------------------------------------------------------------------
- // SquirrelNoise5.hpp
- // based on GDC 2017 talk "Math for Game Programmers: Noise-Based RNG": https://www.youtube.com/watch?v=LWFzPP8ZbdU
- #pragma once
- /////////////////////////////////////////////////////////////////////////////////////////////////
- // SquirrelNoise5 - Squirrel's Raw Noise utilities (version 5)
- //
- // This code is made available under the Creative Commons attribution 3.0 license (CC-BY-3.0 US):
- // Attribution in source code comments (even closed-source/commercial code) is sufficient.
- // License summary and text available at: https://creativecommons.org/licenses/by/3.0/us/
- //
- // These noise functions were written by Squirrel Eiserloh as a cheap and simple substitute for
- // the [sometimes awful] bit-noise sample code functions commonly found on the web, many of which
- // are hugely biased or terribly patterned, e.g. having bits which are on (or off) 75% or even
- // 100% of the time (or are excessively overkill/slow for our needs, such as MD5 or SHA).
- //
- // Note: This is work in progress; not all functions have been tested. Use at your own risk.
- // Please report any bugs, issues, or bothersome cases to SquirrelEiserloh at gmail.com.
- //
- // The following functions are all based on a simple bit-noise hash function which returns an
- // unsigned integer containing 32 reasonably-well-scrambled bits, based on a given (signed)
- // integer input parameter (position/index) and [optional] seed. Kind of like looking up a
- // value in an infinitely large [non-existent] table of previously rolled random numbers.
- //
- // These functions are deterministic and random-access / order-independent (i.e. state-free),
- // so they are particularly well-suited for use in smoothed/fractal/simplex/Perlin noise
- // functions and out-of-order (or or-demand) procedural content generation (i.e. that mountain
- // village is the same whether you generated it first or last, ahead of time or just now).
- //
- // The N-dimensional variations simply hash their multidimensional coordinates down to a single
- // 32-bit index and then proceed as usual, so while results are not unique they should
- // (hopefully) not seem locally predictable or repetitive.
- //
- /////////////////////////////////////////////////////////////////////////////////////////////////
- //-----------------------------------------------------------------------------------------------
- // Raw pseudorandom noise functions (random-access / deterministic). Basis of all other noise.
- //
- constexpr unsigned int Get1dNoiseUint( int index, unsigned int seed=0 );
- constexpr unsigned int Get2dNoiseUint( int indexX, int indexY, unsigned int seed=0 );
- constexpr unsigned int Get3dNoiseUint( int indexX, int indexY, int indexZ, unsigned int seed=0 );
- constexpr unsigned int Get4dNoiseUint( int indexX, int indexY, int indexZ, int indexT, unsigned int seed=0 );
- //-----------------------------------------------------------------------------------------------
- // Same functions, mapped to floats in [0,1] for convenience.
- //
- constexpr float Get1dNoiseZeroToOne( int index, unsigned int seed=0 );
- constexpr float Get2dNoiseZeroToOne( int indexX, int indexY, unsigned int seed=0 );
- constexpr float Get3dNoiseZeroToOne( int indexX, int indexY, int indexZ, unsigned int seed=0 );
- constexpr float Get4dNoiseZeroToOne( int indexX, int indexY, int indexZ, int indexT, unsigned int seed=0 );
- //-----------------------------------------------------------------------------------------------
- // Same functions, mapped to floats in [-1,1] for convenience.
- //
- constexpr float Get1dNoiseNegOneToOne( int index, unsigned int seed=0 );
- constexpr float Get2dNoiseNegOneToOne( int indexX, int indexY, unsigned int seed=0 );
- constexpr float Get3dNoiseNegOneToOne( int indexX, int indexY, int indexZ, unsigned int seed=0 );
- constexpr float Get4dNoiseNegOneToOne( int indexX, int indexY, int indexZ, int indexT, unsigned int seed=0 );
- /////////////////////////////////////////////////////////////////////////////////////////////////
- // Inline function definitions below
- /////////////////////////////////////////////////////////////////////////////////////////////////
- //-----------------------------------------------------------------------------------------------
- // Fast hash of an int32 into a different (unrecognizable) uint32.
- //
- // Returns an unsigned integer containing 32 reasonably-well-scrambled bits, based on the hash
- // of a given (signed) integer input parameter (position/index) and [optional] seed. Kind of
- // like looking up a value in an infinitely large table of previously generated random numbers.
- //
- // I call this particular approach SquirrelNoise5 (5th iteration of my 1D raw noise function).
- //
- // Many thanks to Peter Schmidt-Nielsen whose outstanding analysis helped identify a weakness
- // in the SquirrelNoise3 code I originally used in my GDC 2017 talk, "Noise-based RNG".
- // Version 5 avoids a noise repetition found in version 3 at extremely high position values
- // caused by a lack of influence by some of the high input bits onto some of the low output bits.
- //
- // The revised SquirrelNoise5 function ensures all input bits affect all output bits, and to
- // (for me) a statistically acceptable degree. I believe the worst-case here is in the amount
- // of influence input position bit #30 has on output noise bit #0 (49.99%, vs. 50% ideal).
- //
- constexpr unsigned int SquirrelNoise5( int positionX, unsigned int seed )
- {
- constexpr unsigned int SQ5_BIT_NOISE1 = 0xd2a80a3f; // 11010010101010000000101000111111
- constexpr unsigned int SQ5_BIT_NOISE2 = 0xa884f197; // 10101000100001001111000110010111
- constexpr unsigned int SQ5_BIT_NOISE3 = 0x6C736F4B; // 01101100011100110110111101001011
- constexpr unsigned int SQ5_BIT_NOISE4 = 0xB79F3ABB; // 10110111100111110011101010111011
- constexpr unsigned int SQ5_BIT_NOISE5 = 0x1b56c4f5; // 00011011010101101100010011110101
- unsigned int mangledBits = (unsigned int) positionX;
- mangledBits *= SQ5_BIT_NOISE1;
- mangledBits += seed;
- mangledBits ^= (mangledBits >> 9);
- mangledBits += SQ5_BIT_NOISE2;
- mangledBits ^= (mangledBits >> 11);
- mangledBits *= SQ5_BIT_NOISE3;
- mangledBits ^= (mangledBits >> 13);
- mangledBits += SQ5_BIT_NOISE4;
- mangledBits ^= (mangledBits >> 15);
- mangledBits *= SQ5_BIT_NOISE5;
- mangledBits ^= (mangledBits >> 17);
- return mangledBits;
- }
- //------------------------------------------------------------------------------------------------
- constexpr unsigned int Get1dNoiseUint( int positionX, unsigned int seed )
- {
- return SquirrelNoise5( positionX, seed );
- }
- //-----------------------------------------------------------------------------------------------
- constexpr unsigned int Get2dNoiseUint( int indexX, int indexY, unsigned int seed )
- {
- constexpr int PRIME_NUMBER = 198491317; // Large prime number with non-boring bits
- return SquirrelNoise5( indexX + (PRIME_NUMBER * indexY), seed );
- }
- //-----------------------------------------------------------------------------------------------
- constexpr unsigned int Get3dNoiseUint( int indexX, int indexY, int indexZ, unsigned int seed )
- {
- constexpr int PRIME1 = 198491317; // Large prime number with non-boring bits
- constexpr int PRIME2 = 6542989; // Large prime number with distinct and non-boring bits
- return SquirrelNoise5( indexX + (PRIME1 * indexY) + (PRIME2 * indexZ), seed );
- }
- //-----------------------------------------------------------------------------------------------
- constexpr unsigned int Get4dNoiseUint( int indexX, int indexY, int indexZ, int indexT, unsigned int seed )
- {
- constexpr int PRIME1 = 198491317; // Large prime number with non-boring bits
- constexpr int PRIME2 = 6542989; // Large prime number with distinct and non-boring bits
- constexpr int PRIME3 = 357239; // Large prime number with distinct and non-boring bits
- return SquirrelNoise5( indexX + (PRIME1 * indexY) + (PRIME2 * indexZ) + (PRIME3 * indexT), seed );
- }
- //-----------------------------------------------------------------------------------------------
- constexpr float Get1dNoiseZeroToOne( int index, unsigned int seed )
- {
- constexpr double ONE_OVER_MAX_UINT = (1.0 / (double) 0xFFFFFFFF);
- return (float)( ONE_OVER_MAX_UINT * (double) SquirrelNoise5( index, seed ) );
- }
- //-----------------------------------------------------------------------------------------------
- constexpr float Get2dNoiseZeroToOne( int indexX, int indexY, unsigned int seed )
- {
- constexpr double ONE_OVER_MAX_UINT = (1.0 / (double) 0xFFFFFFFF);
- return (float)( ONE_OVER_MAX_UINT * (double) Get2dNoiseUint( indexX, indexY, seed ) );
- }
- //-----------------------------------------------------------------------------------------------
- constexpr float Get3dNoiseZeroToOne( int indexX, int indexY, int indexZ, unsigned int seed )
- {
- constexpr double ONE_OVER_MAX_UINT = (1.0 / (double) 0xFFFFFFFF);
- return (float)( ONE_OVER_MAX_UINT * (double) Get3dNoiseUint( indexX, indexY, indexZ, seed ) );
- }
- //-----------------------------------------------------------------------------------------------
- constexpr float Get4dNoiseZeroToOne( int indexX, int indexY, int indexZ, int indexT, unsigned int seed )
- {
- constexpr double ONE_OVER_MAX_UINT = (1.0 / (double) 0xFFFFFFFF);
- return (float)( ONE_OVER_MAX_UINT * (double) Get4dNoiseUint( indexX, indexY, indexZ, indexT, seed ) );
- }
- //-----------------------------------------------------------------------------------------------
- constexpr float Get1dNoiseNegOneToOne( int index, unsigned int seed )
- {
- constexpr double ONE_OVER_MAX_INT = (1.0 / (double) 0x7FFFFFFF);
- return (float)( ONE_OVER_MAX_INT * (double) (int) SquirrelNoise5( index, seed ) );
- }
- //-----------------------------------------------------------------------------------------------
- constexpr float Get2dNoiseNegOneToOne( int indexX, int indexY, unsigned int seed )
- {
- constexpr double ONE_OVER_MAX_INT = (1.0 / (double) 0x7FFFFFFF);
- return (float)( ONE_OVER_MAX_INT * (double) (int) Get2dNoiseUint( indexX, indexY, seed ) );
- }
- //-----------------------------------------------------------------------------------------------
- constexpr float Get3dNoiseNegOneToOne( int indexX, int indexY, int indexZ, unsigned int seed )
- {
- constexpr double ONE_OVER_MAX_INT = (1.0 / (double) 0x7FFFFFFF);
- return (float)( ONE_OVER_MAX_INT * (double) (int) Get3dNoiseUint( indexX, indexY, indexZ, seed ) );
- }
- //-----------------------------------------------------------------------------------------------
- constexpr float Get4dNoiseNegOneToOne( int indexX, int indexY, int indexZ, int indexT, unsigned int seed )
- {
- constexpr double ONE_OVER_MAX_INT = (1.0 / (double) 0x7FFFFFFF);
- return (float)( ONE_OVER_MAX_INT * (double) (int) Get4dNoiseUint( indexX, indexY, indexZ, indexT, seed ) );
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement