In this post, I will show how the reference implementation of Improved Perlin Noise can be rewritten to yield an aperiodic noise function.

The reference implementation for Improved Perlin Noise (which can be found on Ken Perlin’s website here), is given (in Java) as:

The reference implementation makes use of a permutation table (omitted for brevity) to build an 8-bit hash for eight corners of the unit cube surrounding the given input coordinate. The permutation table is a fixed size of 256 but actually repeated to conveniently avoid buffer overflow errors.

To ensure that we don’t overflow this table, the modulus operator is first applied to the input coordinates. We can think of this as an initial hashing function:

A consequence of this is that the reference implementation repeats for every 256 units.

The first step in removing this repetition is to apply a better initial hashing function, that makes use of the full precision range of the input value. For example, we could choose to reuse the permutation table to perform a Pearson Hash of the input value:

We could then change the first three lines of the noise function to apply this better hashing scheme instead:

However, this isn’t enough. The following lines that make use of the X,Y and Z values make a very important assumption on the initial hashing function used to generate them:

Whilst the modulus operator has this property, our new hashing function doesn’t. We can see how this affects the computation of the gradient hashes by expanding one of them out:

For the positive corners of the unit grid we are adding 1 to the X, Y, and Z terms but these terms are the results of the initial hashing function, and will therefore only work if our initial hashing function maintains the assumption stated above.

In breaking this assumption, we must rewrite these terms as well. We’ll start by computing the hash of the positive corners too:

Then we can rewrite these these terms such that, for example, the expression:

p[ p[ p[ X + 1 ] + Y + 1 ] + Z + 1 ]

becomes:

p[ p[ p[ XX ] + YY ] + ZZ ]

After some factorisation, here is the resultant function (in C++):

The full source listing can be found here: https://gist.github.com/jbrd/290bcef984b3e2e0224da6acc76e7489

Whilst this is more expensive than the original implementation, this should go to demonstrate a technique that can be used to remove the 256 unit repetition in the reference implementation.