Я полностью освоил искусство 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);
}