Using FNV32 for Value Noise

Value noise is sort of like a random() function that can be seeded. According to the libnoise author it has three important properties:

  1. Passing in the same input value will always return the same output value.
  2. The output value generated by the input value a and the output value generated by the input value b (a != b) will have no correlation with each other.
  3. The output value will always be within the range -1 to +1.

I previously created a demo using what I thought at the time was value noise, however it turns out that it was confused with gradient noise. According to wikipedia, this is a common mistake. The resource that I used which made this mistake was the fractalterraingeneration project on google code.

To achieve the above requirements for the value noise function, which is called integer noise until it is rescaled in libnoise, looks like the following:

const int X_NOISE_GEN = 1619;
const int Y_NOISE_GEN = 31337;
const int Z_NOISE_GEN = 6971;
const int SEED_NOISE_GEN = 1013;
const int SHIFT_NOISE_GEN = 8;

int noise::IntValueNoise3D (int x, int y, int z, int seed)
{
  // All constants are primes and must remain prime in order for this noise
  // function to work correctly.
  int n = (
      X_NOISE_GEN    * x
    + Y_NOISE_GEN    * y
    + Z_NOISE_GEN    * z
    + SEED_NOISE_GEN * seed)
    & 0x7fffffff;
  n = (n >> 13) ^ n;
  return (n * (n * n * 60493 + 19990303) + 1376312589) & 0x7fffffff;
}

After spending some time researching the topic some more and having problems getting this to work in a Pixel Bender (there is no support for bit-ops, for-loops and even functions or methods!)- I somehow landed on the idea for using the FNV32 hash function that I wrote awhile back, for the value noise function. It did not solve my problems with Pixel Bender but there are some considerable benefits of this approach.

  1. It adheres to the fact that the same input always returns the same output value.
  2. The output value of a has no correlation with b.
  3. I have decided to keep the scale normalised between 0 and 1. I have not found any information as to the benefit of having it range between -1 and 1.
  4. Any value type can be fed into the method, thus no worries about converting from integer to float or double, etc. The best is that I now have a way of seeding multiple values into a random number generator.

My code to achieve the value noise is below:

	/**
	 * Returns a psuedorandom value in the range [0, 1]. The 
	 * function takes in 2D coordinate values over any range
	 * and can be seeded.
	 * 
	 * @param	x		any decimal / integer value over any range
	 * @param	y		any decimal / integer value over any range
	 * @param	seed	any decimal / integer value over any range
	 * @return	value in the range [0, 1]
	 */
	public function valueNoise(x:Number, y:Number, seed:Number):Number
	{
		return fnv32Hash([1629 * x, 31337 * y, 6971 * seed]) / uint.MAX_VALUE;
	}

You can see that it is essentially a FNV32 hash. Now I am not vouching that this is true value noise… I might still have this all wrong. However, what I do have is a random number generator that can be seeded with any coordinate system. The effect this will have on the end result is yet to be known. I will continue to convert the output of this function to gradient noise and see what effect is has on future demos.