Функция шума Перлина, возвращающая одинаковые результаты для разных входных данных

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

Кто-нибудь знает, почему это так? Как это исправить? Единственное, что мне удалось сделать, это добавить десятичное значение, например 0,6473, к координатам x и y, что помогло, но привело к другим проблемам, таким как значения, повторяющиеся внутри массивов.

Вот некоторый тестовый код. Я пытаюсь создать два разных 2D-массива, заполненных значениями шума. Входные данные x и y — это координаты из моей игры. В строках с '**' после них, если я не увеличу эти значения, оба массива будут заполнены нулями. В примере координаты (0,0, -768,0) и (-1024,0, -768,0) возвращают одинаковые значения шума. В моей игре 9 разных координат возвращают одинаковые значения.

Функция Perlin Noise, которую я использую для этого теста, находится здесь

public class TestPerlinMain
{
    public static void main(String[] args) 
    {
        int seed = 532434;

        //create first noise array
        double x = 0.0;    //x-coordinate
        double y = -768.0; //y-coordinate
        float z = 10.0f;

        double[][] test = new double[15][15];

        System.out.println("Noise Array 1: ");

        for(int i = 0; i < test.length; i++)
        {
            for(int j = 0; j < test[i].length; j++)
            {
                test[i][j] = ImprovedNoise.noise(x + (j * 64.0), y + (i * 64.0), 10.0);
                x += .314f;//************

                System.out.print(test[i][j] + " ");
            }
            y += .314f;//***********

        }
        System.out.println();

        //create 2nd noise array
        double x2 = -1024.0; //x coordinate
        double y2 = -768.0;  //y coordinate
        float z2 = 10.0f;    

        System.out.println();

        double[][] test2 = new double[15][15];

        System.out.println("Noise Array 2: ");

        for(int i = 0; i < test2.length; i++)
        {
            for(int j = 0; j < test2[i].length; j++)
            {
                test2[i][j] = ImprovedNoise.noise(x2 + (j * 64.0), y2 + (i * 64.0), 10.0);
                x2 += .314f;//*************

                System.out.print(test2[i][j] + " ");
            }
            y2 += .314f;//************

        }
        System.out.println();
    }

person theDazzler    schedule 06.03.2012    source источник


Ответы (1)


Шум Перлина определяется равным 0 во всех точках сетки (целое число x, y, z). Вы можете убедиться в этом сами, смоделировав это вручную в коде, который вы связали. Поскольку x, y и z становятся равными 0 при вычитании их этажей, все значения grad() равны 0, поэтому все значения lerp() равны 0.

Есть несколько способов получить нужный шум. Во-первых, если вы используете нецелое значение z, вы должны получить случайные значения шума. Однако, поскольку шаг вашей сетки 64 намного больше, чем базис шума, это будет выглядеть как статический, а не шум Перлина. Лучшим подходом было бы увеличить шум, выполнив что-то вроде noise(j/4., i/4., z). Выборка 4 точек в каждой шумовой ячейке позволит увидеть некоторую плавность шума.

Также обратите внимание, что ваша реализация шума предназначена для повторения тайлов размером 256 в каждом направлении (см. первую строку noise()). Вот почему вы получаете повторяющиеся значения каждые 4 в вашем массиве.

person Russell Zahniser    schedule 06.03.2012
comment
Я попробовал все, что вы сказали. Я сделал z значением, отличным от int, и получил те же результаты. Я также попытался масштабировать шум, как вы предложили, выполнив шум (j / 4, i / 4, z) и получил те же результаты. Любые другие предложения? Кроме того, вы имеете в виду плитку размером 256x256 или массив, содержащий 256 плиток? - person theDazzler; 06.03.2012
comment
Суть, которую я пытался подчеркнуть в последнем абзаце, заключается в том, что функция шума повторяется каждые 256 (по x, y и z). Итак, значение в (1, 3) такое же, как в (257, 259) или (1, 769) или вообще (x + 256n, y + 256m). Поскольку 1024 и 768 кратны 256, естественно, второй массив соответствует первому. - person Russell Zahniser; 06.03.2012
comment
Я проверю это, когда вернусь домой. В любом случае, я использую функцию FBM, я просто использовал ее для тестирования. Вчера вечером я заставил его работать, внеся несколько изменений, но я не думаю, что это идеально. - person theDazzler; 07.03.2012