2D Perlin Noise

Я полностью овладел искусством Perlin Noise в 3D, и теперь я пытаюсь использовать ту же самую реализацию для 2D-алгоритма. Проблема, кажется, заключается в выборе моих градиентных направлений. В 3D я использую 16 градиентов в равномерно распределенных направлениях, и это прекрасно работает. В 2D я решил использовать 8 градиентов. вверх, вниз, влево, вправо и четыре диагональных направления.

Вот что я получаю:

Общий вид шума всегда правильный, но края квадратов не совсем совпадают. Я также пытался использовать другие градиенты или меньше градиентов, но получаю похожие результаты. Здесь, в другом примере, вы можете видеть, что края иногда совпадают, и результаты в этой области хорошие -

Когда я не использую градиенты и вместо этого просто интерполирую между значением, выбранным случайным образом в каждом из 4 углов, я получаю правильные результаты, и это заставляет меня думать, что это градиентная часть, которая портит это.

Вот мой код:

//8 different gradient directions
private Point[] grads = new Point[] { 
    new Point(0, 1), new Point(1, 1), new Point(1, 0), new Point(1, -1), 
    new Point(0, -1), new Point(-1, -1), new Point(-1, 0), new Point(-1, 1),};

//takes the dot product of a gradient and (x, y)
private float dot2D(int i, float x, float y)
{
    return
        grads[i].X * x + grads[i].Y * y;
}

public float Noise2D(float x, float y)
{
    int
        ix = (int)(x),
        iy = (int)(y);

        x  = x - ix;
        y  = y - iy;

    float
        fx  = fade(x),
        fy  = fade(y);

        ix &= 255;
        iy &= 255;

    // here is where i get the index to look up in the list of 
    // different gradients.
    // hashTable is my array of 0-255 in random order
    int
        g00 = hashTable[ix +     hashTable[iy    ]],
        g10 = hashTable[ix + 1 + hashTable[iy    ]],
        g01 = hashTable[ix +     hashTable[iy + 1]],
        g11 = hashTable[ix + 1 + hashTable[iy + 1]];

    // this takes the dot product to find the values to interpolate between
    float
        n00 = dot2D(g00 & 7, x, y),
        n10 = dot2D(g10 & 7, x, y),
        n01 = dot2D(g01 & 7, x, y),
        n11 = dot2D(g11 & 7, x, y);

    // lerp() is just normal linear interpolation
    float
        y1 = lerp(fx, n00, n10),
        y2 = lerp(fx, n01, n11);
    return
        lerp(fy, y1, y2);
}

Ответы на вопрос(3)

Ваш ответ на вопрос