0

Many implementations of Perlin Noise I saw, double the permutation table, because index might be out of the [0, 255] range.

private static readonly int[] p;

static Perlin() {
    p = new int[512];
    for(int x=0;x<512;x++) {
        p[x] = permutation[x%256];
    }
}

private static readonly int[] permutation = { 151,160,137,91,90,15,                 
    131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,23,
    190, 6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33,
    88,237,149,56,87,174,20,125,136,171,168, 68,175,74,165,71,134,139,48,27,166,
    77,146,158,231,83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244,
    102,143,54, 65,25,63,161, 1,216,80,73,209,76,132,187,208, 89,18,169,200,196,
    135,130,116,188,159,86,164,100,109,198,173,186, 3,64,52,217,226,250,124,123,
    5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42,
    223,183,170,213,119,248,152, 2,44,154,163, 70,221,153,101,155,167, 43,172,9,
    129,22,39,253, 19,98,108,110,79,113,224,232,178,185, 112,104,218,246,97,228,
    251,34,242,193,238,210,144,12,191,179,162,241, 81,51,145,235,249,14,239,107,
    49,192,214, 31,181,199,106,157,184, 84,204,176,115,121,50,45,127, 4,150,254,
    138,236,205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180
};

public double perlin(double x, double y, double z) {
    if(repeat > 0) {
        x = x%repeat;
        y = y%repeat;
        z = z%repeat;
    }

    // This means xi/yi/zi is in the range [0,255]
    int xi = (int)x & 255;
    int yi = (int)y & 255;
    int zi = (int)z & 255;
    double xf = x-(int)x;
    double yf = y-(int)y;
    double zf = z-(int)z;
    double u = fade(xf);
    double v = fade(yf);
    double w = fade(zf);

    // inc(xi) basically means xi + 1
    // thus we may be selecting permutation[255 + 1], which is out of range
    // hence we create a p[] array, that's double of permutation[] array.
    int aaa, aba, aab, abb, baa, bba, bab, bbb;
    aaa = p[p[p[    xi ]+    yi ]+    zi ];
    aba = p[p[p[    xi ]+inc(yi)]+    zi ];
    aab = p[p[p[    xi ]+    yi ]+inc(zi)];
    abb = p[p[p[    xi ]+inc(yi)]+inc(zi)];
    baa = p[p[p[inc(xi)]+    yi ]+    zi ];
    bba = p[p[p[inc(xi)]+inc(yi)]+    zi ];
    bab = p[p[p[inc(xi)]+    yi ]+inc(zi)];
    bbb = p[p[p[inc(xi)]+inc(yi)]+inc(zi)];

    double x1, x2, y1, y2;
    x1 = lerp(  grad (aaa, xf  , yf  , zf),
                grad (baa, xf-1, yf  , zf),
                u);
    x2 = lerp(  grad (aba, xf  , yf-1, zf),
                grad (bba, xf-1, yf-1, zf),
                  u);
    y1 = lerp(x1, x2, v);

    x1 = lerp(  grad (aab, xf  , yf  , zf-1),
                grad (bab, xf-1, yf  , zf-1),
                u);
    x2 = lerp(  grad (abb, xf  , yf-1, zf-1),
                grad (bbb, xf-1, yf-1, zf-1),
                u);
    y2 = lerp (x1, x2, v);

    return lerp (y1, y2, w);
}

However, I saw one implementation that simply add another number to the permutation table. So that it skips all the work.

public static float Noise(float x, float y, float z)
{
    var X = Mathf.FloorToInt(x) & 0xff;
    var Y = Mathf.FloorToInt(y) & 0xff;
    var Z = Mathf.FloorToInt(z) & 0xff;
    x -= Mathf.Floor(x);
    y -= Mathf.Floor(y);
    z -= Mathf.Floor(z);
    var u = Fade(x);
    var v = Fade(y);
    var w = Fade(z);
    // This implementation doesn't create p[] array
    // It just repeated a number so that permutation has 257 items.
    // And cap the result so that we never select index beyond 256.
    var A  = (perm[X  ] + Y) & 0xff;
    var B  = (perm[X+1] + Y) & 0xff;
    var AA = (perm[A  ] + Z) & 0xff;
    var BA = (perm[B  ] + Z) & 0xff;
    var AB = (perm[A+1] + Z) & 0xff;
    var BB = (perm[B+1] + Z) & 0xff;
    return Lerp(w, Lerp(v, Lerp(u, Grad(perm[AA  ], x, y  , z  ), Grad(perm[BA  ], x-1, y  , z  )),
                           Lerp(u, Grad(perm[AB  ], x, y-1, z  ), Grad(perm[BB  ], x-1, y-1, z  ))),
                   Lerp(v, Lerp(u, Grad(perm[AA+1], x, y  , z-1), Grad(perm[BA+1], x-1, y  , z-1)),
                           Lerp(u, Grad(perm[AB+1], x, y-1, z-1), Grad(perm[BB+1], x-1, y-1, z-1))));
}

//...

static int[] perm = {
    151,160,137,91,90,15,
    131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,23,
    190, 6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33,
    88,237,149,56,87,174,20,125,136,171,168, 68,175,74,165,71,134,139,48,27,166,
    77,146,158,231,83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244,
    102,143,54, 65,25,63,161, 1,216,80,73,209,76,132,187,208, 89,18,169,200,196,
    135,130,116,188,159,86,164,100,109,198,173,186, 3,64,52,217,226,250,124,123,
    5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42,
    223,183,170,213,119,248,152, 2,44,154,163, 70,221,153,101,155,167, 43,172,9,
    129,22,39,253, 19,98,108,110,79,113,224,232,178,185, 112,104,218,246,97,228,
    251,34,242,193,238,210,144,12,191,179,162,241, 81,51,145,235,249,14,239,107,
    49,192,214, 31,181,199,106,157,184, 84,204,176,115,121,50,45,127, 4,150,254,
    138,236,205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180,
    151 // It just repeated a number at index 0
};

Is this a valid implementation of Perlin Noise?

bitinn
  • 9,188
  • 10
  • 38
  • 64
  • What in particular did you change to avoid having a double array size? To avoid limiting the question to those that know the Perlin noise algorithm implementation by heart, perhaps if you showed the original code and then described your changes we can tell if you the changes are valid and that they won't change the result. – Lasse V. Karlsen Dec 06 '16 at 08:44
  • It's a difficult thing to describe, I have tried my best to edit it. Commented the code to explain their difference... (I should note all source code are available at both links) – bitinn Dec 06 '16 at 11:16

0 Answers0