2016-05-05 4 views
2

を試み:http://lodev.org/cgtutor/randomnoise.htmlパーリンノイズこの文書で説明したよう私はパーリンノイズ(3次元)での私の試みをしようとしています

しかし、これは私が取得していますものです。 perlin noise attempt スムージングが機能していないようです。 'size'パラメータのサイズをブロックすることができます。誰かが間違っていることを指摘できますか?ここで

は私のコードです:

%ffp 

ctl(1):standard,"Size",range=(1,256), pos=(300,20), size=(120,*),val=64,track, action=preview 

onFilterStart: 
{ 
allocArray(9,64,64,64,4); // Array for noise depth 
    for(int z = 0; z < 64; z++) 
    for(int y = 0; y < 64; y++) 
    for(int x = 0; x < 64; x++) { 
    fputArray(9,x,y,z,(float)(rand() % 32768)/32768.0); 
    } 

return false; 
} 

forEveryTile: 
{ 
double fractX,fractY,fractZ,xx,yy,zz; 
int x1,y1,z1,x2,y2,z2,col; 
double value = 0.0, value2 = 0.0, size, isize=(float)ctl(1); 
// int X=screen Width, int Y=screen Height 

    for(int y = 0; y < Y; y++) { 
    for(int x = 0; x < X; x++) { 
    //for(int z = 0; z < 64; z++) { 
    value2 = 0.0; 
    size = isize; 

    while (size >=1.0) { 
    xx=(float)x/size; 
    yy=(float)y/size; 
    zz=(float)clock()/size; 
    fractX = xx - (int)(xx); 
    fractY = yy - (int)(yy); 
    fractZ = zz - (int)(zz); 
    x1 = ((int)(xx) + 64) % 64; 
    y1 = ((int)(yy) + 64) % 64; 
    z1 = ((int)(zz) + 64) % 64; 
    x2 = (x1 + 64- 1) % 64; 
    y2 = (y1 + 64- 1) % 64; 
    z2 = (z1 + 64- 1) % 64; 

    value=0.0; 
    value += fractX  * fractY  * fractZ  * fgetArray(9,z1,y1,x1); 
    value += fractX  * (1 - fractY) * fractZ  * fgetArray(9,z1,y2,x1); 
    value += (1 - fractX) * fractY  * fractZ  * fgetArray(9,z1,y1,x2); 
    value += (1 - fractX) * (1 - fractY) * fractZ  * fgetArray(9,z1,y2,x2); 

    value += fractX  * fractY  * (1 - fractZ) * fgetArray(9,z2,y1,x1); 
    value += fractX  * (1 - fractY) * (1 - fractZ) * fgetArray(9,z2,y2,x1); 
    value += (1 - fractX) * fractY  * (1 - fractZ) * fgetArray(9,z2,y1,x2); 
    value += (1 - fractX) * (1 - fractY) * (1 - fractZ) * fgetArray(9,z2,y2,x2); 

    value2 += value*size; 
    size /= 2.0; 
    } 

    col=(int)((float)(128.0 * value2/isize)); 
    col=max(min(col,255),0); 
    psetp(x,y,RGB(col,col,col)); 

//} //z 
} //x 
} //y 

return true; 
} 
+0

'clock()'を 'z'座標として使用する動機は何ですか?明らかにクラウドアニメーションを作成したいと思いますが、 'clock'は内側ループのrun-throughごとに異なる値の' z'を生成することがあります。つまり、異なるアニメーションフレームで補間を行っています。 「すべてのタイルについて」が「それぞれの「z」について」を意味する場合、可能な「z」値を列挙するだけである。 –

+0

それは非常に真ですが、私がzを完全に式から取り除いても、私はまだこれらの塊状の結果を得ています。本当の3次元ノイズを得るためにもループを通ってzをループしていましたが、デバッグのためにそれを取り出して2次元ループにしました。だから私はzが問題の原因だとは思わない。 – Rich95

+0

したがって、2dノイズの場合でも結果はブロックされますか? –

答えて

1

あなたのコードが書かれたとして読み取るのは難しいの一種です。

パーリンノイズは、整数ノイズ関数で開始します。これはハッシュのように動作します。

float noise(int x, int y, int z) { return hash(x+y*5+z*7); } 

または

float noise(int x, int y, int z) { return array[x%w+y%h*w+z%d*w*h]; } 

これらは一例です。重要な部分はノイズ(x、y、z)=ノイズ(x、y、z)です。ノイズ関数は毎回同じパラメータに対して同じ値を返す必要があります。

問題があります:ノイズ関数は整数パラメータしか取らない!しかし、浮動小数値でサンプルしたいと思います。

float noisesample (float x, float y, float z) { ... } 

最も簡単な方法は、線形フィルタリングを使用することです。正の浮動小数点値は、(int)posと((int)pos)+1の間にあります。サブポジションpos(int)pos。これは、米国を取得:

fは[0..1]の範囲内のサブ位置であり、Bは、左右の値である
float Lerp(float a, float b, float f) { return a+(b-a)*f; } 

。 fが0の場合、Lerpはaを返し、1の場合はbを返します。その間で線形補間を行います。

だから、簡単な1D noisesample機能のためにこれを使用します。私は(int)を使用しています

float fract(float x) { return x-(int)x; } 

float noisesample(float x) { return Lerp(noise((int)x), noise((int)x+1), fract(x) } 

はここに気前X Xならば、それは、(x)は、床と同じですポジティブです。 xに単一のパラメータnoisesampleから行くために

、yは簡単です。それらの間のyにおけるxとy + 1、およびLerpのために二回Lerpの操作を行います。

float noisesample(float x, float y) { 
    float y0 = Lerp(noise((int)x,(int)y), noise((int)x+1,(int)y), fract(x) } 
    float y1 = Lerp(noise((int)x,(int)y+1), noise((int)x+1,(int)y+1), fract(x) } 
    return Lerp (y0, y1, fract(y)); 
} 

まず補間のX、二回、その後、結果をyで補間する。合計でノイズ()を4回サンプリングします。私はnoisesample(float x、float y、float z)を書く方法を練習として残します。 noise()を8回サンプリングし、Lerpに7回呼び出します。

私たちは、浮動小数点座標でノイズをサンプリングすることができます(いくらか滑らかです - 滑らかな方法があります)。それがパーリン・ノイズを作るために必要なものです!

float perlin(float x, float y, float z, int oc=4) { 
    // maybe: x = x*2^oc, y, z... 
    float r = 0; 
    float s = 1; 
    for (int i=0; i<oc; i++) { 
     r += noisesample(x,y,z) * s; 
     s/=2.0f; // to taste 
     x/=2.0f; 
     y/=2.0f; 
     z/=2.0f; 
    } 
    return r; 
} 

重要なアイデアはサンプリングを理解することです。単純な整数ノイズ関数をサンプリングするだけの組み合わせです。

関連する問題