Почему мой шум перлина такой... шумный?

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

Проблема шума Перлина

Вот мой код генерации:

double persistence = .25;
double octaves = 1;

double Game::GeneratePerlin2D(const double& x, const double& y)
{
    double total = 0;

    for (int i = 0; i < octaves; i++)
    {
        double frequency = pow(2, i);
        double amplitude = pow(persistence, i);

        total += InterpolatedNoise(x * frequency, y * frequency) * amplitude;
    }

    return total;
}

double Game::InterpolatedNoise(const double& x, const double& y)
{
    int intX = (int)x;
    double fractionX = x - intX;

    int intY = (int)y;
    double fractionY = y - intY;

    // Get the smoothed noise values for each corner
    double s = SmoothNoise(intX, intY);         // Bottom left
    double t = SmoothNoise(intX + 1, intY);     // Bottom right
    double u = SmoothNoise(intX, intY + 1);     // Top left
    double v = SmoothNoise(intX + 1, intY + 1); // Top right

    // Interpolate the corner values to get the middle values
    double i = Interpolate(s, t, fractionX);    // Bottom middle
    double ii = Interpolate(u, v, fractionX);   // Top middle

    // Interpolate the middle values to get the center value
    return Interpolate(i, ii, fractionY);
}

double Game::SmoothNoise(const int& x, const int& y)
{
    double corners = (Noise(x - 1, y - 1) + Noise(x + 1, y - 1) + Noise(x - 1, y + 1) + Noise(x + 1, y + 1)) / 16;
    double sides = (Noise(x - 1, y) + Noise(x + 1, y) + Noise(x, y - 1) + Noise(x, y + 1)) / 8;
    double center = Noise(x, y) / 4;

    return corners + sides + center;
}

double Game::Interpolate(const double& a, const double& b, const double& w)
{
    // Cosine interpolation
    double ft = w * M_PI;
    double f = (1 - cos(ft)) * 0.5;

    return a * (1 - f) + b * f;
}

double Game::Noise(const int& x, const int& y)
{
    int n = x + y * 57;
    n = (n << 13) ^ n;
    return (double)(1.0 - ((n * (n * n * 15731 + 789221) + 1376312589) & 0x7fffffff) / 1073741824.0);
}

А вот мой хакерский код рендеринга для целей отладки:

for (int y = 0; y < 512; y++)
{
    for (int x = 0; x < 512; x++)
    {
        double val = GeneratePerlin2D((x), (y));
        Rectangle rect(x, y, 1.0, 1.0);
        SDL_Color color{(Uint8)(val * 128 + 128), (Uint8)(val * 128 + 128), (Uint8)(val * 128 + 128), 255};
        m_renderer->RenderFillRect(rect, color);
    }
}

Я пробовал как линейную, так и косинусную интерполяцию, дважды и трижды проверял приведение типов и переменные, и я не знаю, что здесь происходит. Что мне не хватает?

Я взял за основу реализацию этой статьи.


person Dooskington    schedule 11.02.2016    source источник
comment
Не связано, но передавать двойники по ссылке const бессмысленно.   -  person molbdnilo    schedule 11.02.2016
comment
Посетите stackoverflow.com/questions/29452265.   -  person alcedine    schedule 11.02.2016
comment
Спасибо @alcedine, этот пост указал мне правильное направление.   -  person Dooskington    schedule 11.02.2016


Ответы (2)


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

for (int y = 0; y < 512; y++)
{
    for (int x = 0; x < 512; x++)
    {
        double val = GeneratePerlin2D((double)(x) / 512.0 * 10, (double)(y) / 512.0 * 10);
        Rectangle rect(x - 256, y - 256, 1.0, 1.0);
        SDL_Color color{(Uint8)(val * 128 + 128), (Uint8)(val * 128 + 128), (Uint8)(val * 128 + 128), 255};
        m_renderer->RenderFillRect(rect, color);
    }
}
person Dooskington    schedule 11.02.2016

Во-первых, вы установили свои октавы на 1, поэтому вместо суммирования ряда шумовых функций вы получаете только одну шумовую функцию.

person Pikalek    schedule 11.02.2016