Обертывание 2D-шума перлина

Я работаю с Perlin Noise для алгоритма генерации карты высоты, я бы хотел, чтобы он обернулся вокруг краев, чтобы его можно было рассматривать как непрерывный. Есть ли простой способ или трюк? Наверное, мне нужно что-то вроде сферического шума, чтобы либо горизонтально, либо вертикально обертывать. Я был бы счастлив также только с одной осью обертывания, но два были бы лучше.

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

Спасибо заранее!

Ответ 1

Перлин-шум получается как сумма сигналов. Сигналы формируются путем интерполяции случайных значений, а более высокие октавные формы имеют меньшие масштабные коэффициенты, тогда как интерполированные случайные значения ближе друг к другу. Чтобы сделать эту оболочку, вам просто нужно правильно интерполировать вокруг оси y- и x обычным тороидальным способом, т.е. Если ваша ось X простирается от x_min до x_max, а самая левая случайная точка (которая интерполируется) при x0 и правее в x1 (x_min < x0 < x1 < x_max) значение для интерполированных пикселей справа на x1 и слева от x0 получается путем интерполяции от x1 до x0 (обертывание по краям).

Здесь псевдокод для одной из октав с использованием линейной интерполяции. Это предполагает матрицу 256 x 256, где размер сетки шума Perlin равен мощности в два пикселя... чтобы сделать ее доступной для чтения. Представьте себе, например. Размер == 16:

 wrappable_perlin_octave(grid, size):
   for (x=0;x<256;x+=size):
     for (y=0;y<256;y+=size):
       grid[x][y] = random()
   for (x=0;x<256;x+=size):
     for (y=0;y<256;y+=size):
       if (x % size != 0 || y % size != 0): # interpolate
         ax = x - x % size
         bx = (ax + size) % 256 # wrap-around
         ay = y - y % size
         by = (ay + size) % 256 # wrap-around
         h = (x % size) / size # horizontal balance, floating-point calculation
         v = (y % size) / size # vertical balance, floating-point calculation
         grid[x][y] = grid[ax][ay] * (1-h) * (1-v) +
                      grid[bx][ay] * h * (1-v) +
                      grid[ax][by] * (1-h) * v +
                      grid[bx][by] * h * v