コヒーレントノイズのさまざまな実装のいくつかを調べています(私はライブラリがあると知っていますが、これは主に自分の恩恵と好奇心のためです)、どのように使用できるか、私はオリジナルのPerlinノイズのものを持っています。Perlinノイズの出力範囲
this frequently linked Math FAQによれば、出力範囲は-1
と1
の間になりますが、値がその範囲にどのようになるか分かりません。
私が理解するように、アルゴリズムは基本的にこれです:各格子点には、長さが1
の関連するランダム勾配ベクトルがあります。次に、各点について、4つの周囲のグリッド点すべてに対して、ランダムな勾配とそのグリッド点からのベクトルの内積を計算します。次に、ファンシーなイージーカーブと線形補間を使用して、その値を1つの値にします。
しかし、これらのドットプロダクトは時には範囲[-1, 1]
の外に出ることがあり、最終的にドットプロダクト間で線形補間を行うので、最終的な値は、場合によっては[-1, 1]
の範囲外になりますか?
言う、例えば、ランダムなベクターの1つは、(単位正方形である)(sqrt(2)/2, sqrt(2)/2)
(1の長さを有する)と(0.8, 0.8)
であることを、あなたがおおよそ1.131
の結果を得ます。その値が線形補間で使用される場合、生成される値が1
より大きい可能性があります。実際、私の単純な実装では、それはかなり頻繁に起こります。
ここに何か不足していますか?
参考までに、私のコードはJavaです。 Vec
は簡単な2次元ベクトル演算を行う単純なクラスです。fade()
はイージーカーブ、lerp()
は線形補間、gradient(x, y)
はそのグリッドポイントのグラデーションをVec
として与えます。 gridSize
変数はあなたにピクセル単位でグリッドのサイズを与えます(それは二重の型を持つ):
public double getPoint(int x, int y) {
Vec p = new Vec(x/gridSize, y/gridSize);
Vec d = new Vec(Math.floor(p.x), Math.floor(p.y));
int x0 = (int)d.x,
y0 = (int)d.x;
double d00 = gradient(x0 , y0 ).dot(p.sub(x0 , y0 )),
d01 = gradient(x0 , y0 + 1).dot(p.sub(x0 , y0 + 1)),
d10 = gradient(x0 + 1, y0 ).dot(p.sub(x0 + 1, y0 )),
d11 = gradient(x0 + 1, y0 + 1).dot(p.sub(x0 + 1, y0 + 1));
double fadeX = fade(p.x - d.x),
fadeY = fade(p.y - d.y);
double i1 = lerp(fadeX, d00, d10),
i2 = lerp(fadeX, d01, d11);
return lerp(fadeY, i1, i2);
}
編集:ここでは、ランダムな勾配を生成するためのコードがあります:gen
がjava.util.Random
ある
double theta = gen.nextDouble() * 2 * Math.PI;
gradients[i] = new Vec(Math.cos(theta), Math.sin(theta));
。
ありがとうございました!それはそれを修正した。 – Oskar