Hello World / plɹoM ollǝH

Programmers Live in Vain

2D Perlin Noise in C++

こんな感じやろか?

float interp(float x, float y, float t) {
    return x + (y - x) * t;  // とりあえず線形
}

float noise(int32_t x, int32_t y) {
    auto n = x + y * 57;
    n = (n << 13) ^ n;
    return (1.0f - ((n * (n * n * 15731 + 789221) + 1376312589) & 0x7fffffff) / 1073741824.0f);
}

float smooth(int32_t x, int32_t y) {
    float corners = (noise(x - 1, y - 1) + noise(x + 1, y - 1) + noise(x - 1, y + 1) + noise(x + 1, y + 1)) / 16.0f;
    float sides = (noise(x - 1, y) + noise(x + 1, y) + noise(x, y - 1) + noise(x, y + 1)) / 8.0f;
    float center = noise(x, y) / 4.0f;
    return corners + sides + center;
}

float interpNoise(float x, float y) {
    auto ix = static_cast<int32_t>(x);
    auto fx = x - ix;
    auto iy = static_cast<int32_t>(y);
    auto fy = y - iy;
    auto v1 = smooth(ix, iy);
    auto v2 = smooth(ix + 1, iy);
    auto v3 = smooth(ix, iy + 1);
    auto v4 = smooth(ix + 1, iy + 1);
    auto i1 = interp(v1, v2, fx);
    auto i2 = interp(v3, v4, fx);
    return interp(i1, i2, fy);
}

float perlinNoise(float x, float y, float persistence, int octaves) {
    float total = 0.0f;
    for (int i = 0; i < octaves; ++i) {
        auto f = powf(2.0f, static_cast<float>(i));
        auto a = powf(persistence, static_cast<float>(i));
        total += interpNoise(x * f, y * f) * a;
    }
    return total;
}

参考
http://www.technotype.net/hugo.elias/models/m_perlin.html

これは古いやり方(Classic way)と呼ばれていて現在はハッシュテーブルを使った実装が多いようだ
https://mrl.nyu.edu/~perlin/noise/
Understanding Perlin Noise
noise/_perlin.c at master · caseman/noise · GitHub

時間があれば読んでおきたい
Texturing & Modeling A Procedural Approach Third Edition 日本語版