I am trying to write a function so that f(x, y, seed)
returns some float between 0.0 and 1.0. x
and y
are two floats, and the seed
would be an integer. The result should look like a random number, but using the same arguments will always return the same result. I am planning to use this for terrain generation (using Perlin Noise), but the effect should be that white noise could be created from a given seed (with the x and y arguments corresponding to positions in the image).
I have looked into using hash functions to achieve this, but all of the ones I have come across either don't accept floats, don't produce uniform results (so that each number between 0.0 and 1.0 is equally likely), show an obvious pattern, or the result doesn't change much for close co-ordinates)
After looking around for a few more hours, I came across this: https://groups.google.com/forum/#!msg/proceduralcontent/AuvxuA1xqmE/T8t88r2rfUcJ
In particular, I have used the answer from Adam Smith to make this:
def rot(x, b):
return((x<<b) ^ (x >> (32 - b)))
def pcghash(x, y, seed):
for l in range(0, 3):
x = rot(x^0xcafebabe + y^0xfaceb00c + seed^0xba5eba11, 23)
x = rot(x^0xdeadbeef + y^0x8badf00d + seed^0x5ca1ab1e, 5)
x = rot(x^0xca11ab1e + y^0xfacefeed + seed^0xdeadc0de, 17)
return(x^y^seed)
def noise(x, y, seed):
return(float('0.' + str(pcghash(x, y, seed))[-10:]))
This takes the coordinates and a seed, and returns a number uniformly distributed between 0.0 and 1.0 (with 10 decimal places). I'm not entirely happy with this, because all of the arguments have to be integers, there are a lot of unused generated bits, and I'm sure the code in the noise()
function could be improved to be faster, but this suits my purposes.
EDIT: A much much better one can be found here (https://www.shadertoy.com/view/4djSRW) in the hash12() function:
float hash12(vec2 p) {
vec3 p3 = fract(vec3(p.xyx) * .1031);
p3 += dot(p3, p3.yzx + 19.19);
return fract((p3.x + p3.y) * p3
}
This is in GLSL, but should be easy to implement in other languages. Also, while this is a 2-dimensional to 1-dimensional hash function, others are available on the Shadertoy shader linked.