2016-05-29 9 views
2

C++でPerlinノイズを実装しようとしています。Perlinノイズアルゴリズムが勾配ノイズを生成しないようです。

まず、問題は(私が思う)出力は私が期待しているものではないということです。現在、私は単純にgreyscaled画像に発生パーリンノイズ値を使用し、これは私が得る結果である: Perlin Noise Algorithm Output

しかし、私の理解から、それはの線に沿ってより多くのを見てすることになっています: Expected Perlin Noise Output

つまり、私が現在作り出しているノイズは、「標準的な」不規則なノイズのラインに沿っているように見えます。

これは私がこれまで実施しているノイズアルゴリズムパーリンある:

float perlinNoise2D(float x, float y) 
{ 
    // Find grid cell coordinates 
    int x0 = (x > 0.0f ? static_cast<int>(x) : (static_cast<int>(x) - 1)); 
    int x1 = x0 + 1; 
    int y0 = (y > 0.0f ? static_cast<int>(y) : (static_cast<int>(y) - 1)); 
    int y1 = y0 + 1; 

    float s = calculateInfluence(x0, y0, x, y); 
    float t = calculateInfluence(x1, y0, x, y); 
    float u = calculateInfluence(x0, y1, x, y); 
    float v = calculateInfluence(x1, y1, x, y); 

    // Local position in the grid cell 
    float localPosX = 3 * ((x - (float)x0) * (x - (float)x0)) - 2 * ((x - (float)x0) * (x - (float)x0) * (x - (float)x0)); 
    float localPosY = 3 * ((y - (float)y0) * (y - (float)y0)) - 2 * ((y - (float)y0) * (y - (float)y0) * (y - (float)y0)); 

    float a = s + localPosX * (t - s); 
    float b = u + localPosX * (v - u); 

    return lerp(a, b, localPosY); 
} 

機能calculateInfluenceは、現在のグリッドの角の点のいずれかのランダム勾配ベクトルと距離ベクトルを生成するジョブを有していますこれらの内積を返します。

std::mt19937 rdEngine(1); 
std::normal_distribution<float> dist(0.0f, 1.0f); 

そしてlerpは、単にとして実装されています:

float lerp(float v0, float v1, float t) 
{ 
    return (1.0f - t) * v0 + t * v1; 
} 
ここ

float calculateInfluence(int xGrid, int yGrid, float x, float y) 
{ 
    // Calculate gradient vector 
    float gradientXComponent = dist(rdEngine); 
    float gradientYComponent = dist(rdEngine); 

    // Normalize gradient vector 
    float magnitude = sqrt(pow(gradientXComponent, 2) + pow(gradientYComponent, 2)); 
    gradientXComponent = gradientXComponent/magnitude; 
    gradientYComponent = gradientYComponent/magnitude; 
    magnitude = sqrt(pow(gradientXComponent, 2) + pow(gradientYComponent, 2)); 

    // Calculate distance vectors 
    float dx = x - (float)xGrid; 
    float dy = y - (float)yGrid; 

    // Compute dot product 
    return (dx * gradientXComponent + dy * gradientYComponent); 
} 

は、distのはC++ 11から乱数生成器である:それは次のように実装されています

アルゴリズムを実装するために、私は主に次の2つのリソースを利用しました:

Perlin Noise FAQ Perlin Noise Pseudo Code

私が台無しにしているように見える場所を正確に私は正確に特定することは困難です。私は勾配ベクトルを間違って生成している可能性があります。私は均一な分布で試しましたが、これはテクスチャに繰り返しパターンを生成するように見えました!

同様に、影響の値を誤って平均化している可能性があります。 Perlin Noise FAQの記事から正確にどのように行うべきかを正確に見分けるのは少し難しかったです。

コードに何が間違っているかについてのヒントはありますか? :)

答えて

5

Perlin Noiseの1オクターブしか生成していないようです。示されているような結果を得るには、multiple octavesを生成し、それらを一緒に追加する必要があります。一連のオクターブでは、各オクターブは最後の2倍のグリッドセルサイズを持つ必要があります。

これと似たような使用し、マルチオクターブの音を生成するには:あなたが異なっを使用することができ、余分なランダム性について

float multiOctavePerlinNoise2D(float x, float y, int octaves) 
{ 
    float v = 0.0f; 
    float scale = 1.0f; 
    float weight = 1.0f; 
    float weightTotal = 0.0f; 
    for(int i = 0; i < octaves; i++) 
    { 
     v += perlinNoise2D(x * scale, y * scale) * weight; 
     weightTotal += weight; 
     // "ever-increasing frequencies and ever-decreasing amplitudes" 
     // (or conversely decreasing freqs and increasing amplitudes) 
     scale *= 0.5f; 
     weight *= 2.0f; 
    } 
    return v/weightTotal; 
} 

は、各オクターブのための乱数生成器を播種しました。また、各オクターブに与えられる重みは、ノイズの美的品質を調整するために変更することができる。ウェイト変数が各繰り返しで調整されていない場合、上記の例は"pink noise"(周波数が2倍になると同じウェイトを持ちます)です。

また、与えられたxGrid、yGridのペアごとに同じ値を返す乱数ジェネレータを使用する必要があります。

+0

Aha!オクターブを使っていないのが問題だったようです:)私は今より良い結果を得ています! – CodingBeagle

+0

信じられないほど、私はまたこの問題を直前に受けました! – Dave3of5

関連する問題