Neden Perlin Gürültüm “bloklu” görünüyor?


21

Perlin Noise'i sadece teoriyi kullanarak kendi kendime uygulamaya çalıştım (flafla2.github.io/2014/08/09/perlinnoise.html). Ne yazık ki "orijinal" Perlin Gürültüsünün görünümünü elde edemedim.

Aşağıdaki kodun Perlin Gürültüsünün bloklu bir sürümünü oluşturmasının nedeni nedir?

Kodda neleri iyileştirmeli / değiştirmeliyim ki yapay eserler olmadan Perlin Gürültüsü veriyor?

İnterpolasyonumda veya gradsvektörde sorun olabileceğinden şüpheleniyorum . gradsTüm 4 yakın örgü noktaları için - vektörü (kafes noktası için rasgele vektör) ve (boyut vektör) ile nokta ürünleri içerir. (Rasgele ve boyut vektörleri ilk bağlantıda açıklanmıştır.)

GLSL Sandbox: http://glslsandbox.com/e#32663.0

Gürültü artefaktları

float fade(float t) { return t * t * t * (t * (t * 6. - 15.) + 10.); }
vec2 smooth(vec2 x) { return vec2(fade(x.x), fade(x.y)); }

vec2 hash(vec2 co) {
    return fract (vec2(.5654654, -.65465) * dot (vec2(.654, 57.4), co));
}

float perlinNoise(vec2 uv) {
    vec2 PT  = floor(uv);
    vec2 pt  = fract(uv);
    vec2 mmpt= smooth(pt);

    vec4 grads = vec4(
        dot(hash(PT + vec2(.0, 1.)), pt-vec2(.0, 1.)),   dot(hash(PT + vec2(1., 1.)), pt-vec2(1., 1.)),
        dot(hash(PT + vec2(.0, .0)), pt-vec2(.0, .0)),   dot(hash(PT + vec2(1., .0)), pt-vec2(1., 0.))
    );

    return 5.*mix (mix (grads.z, grads.w, mmpt.x), mix (grads.x, grads.y, mmpt.x), mmpt.y);
}

float fbm(vec2 uv) {
    float finalNoise = 0.;
    finalNoise += .50000*perlinNoise(2.*uv);
    finalNoise += .25000*perlinNoise(4.*uv);
    finalNoise += .12500*perlinNoise(8.*uv);
    finalNoise += .06250*perlinNoise(16.*uv);
    finalNoise += .03125*perlinNoise(32.*uv);

    return finalNoise;
}

void main() {
    vec2 position = gl_FragCoord.xy / resolution.y;
    gl_FragColor = vec4( vec3( fbm(3.*position) ), 1.0 );
}

Yanıtlar:


24

İnterpolasyon iyi görünüyor. Buradaki asıl sorun, kullandığınız karma işlevinin çok iyi olmamasıdır. Sadece bir oktav'a bakarsam ve hash sonucunu çıktı vererek görselleştirirseniz hash(PT).x, şöyle bir şey alıyorum:

kötü karma işlevi

Bunun ızgara kare başına tamamen rasgele olması gerekiyordu, ancak içinde çok sayıda çapraz çizgi deseninin olduğunu (neredeyse bir dama tahtası gibi göründüğünü) görebiliyorsunuz, bu yüzden çok rastgele bir karma değil ve bu desenler görünecek onun ürettiği gürültü.

Diğer bir problem ise, karma değerinizin sadece [0, 1] degrade vektörleri döndürmesi, her yöne degradeler alabilmesi için [−1,] olması gerekir. Bu kısım yeniden açılarak düzeltilmesi kolaydır.

Bu sorunları gidermek için, bu karma işlevini kullanmak için kodu değiştirdim (ki bu Mikkel Gjoel'den öğrendim ve muhtemelen WJJ Rey'in bir makalesinden kaynaklanıyordu ):

vec2 hash(vec2 co) {
    float m = dot(co, vec2(12.9898, 78.233));
    return fract(vec2(sin(m),cos(m))* 43758.5453) * 2. - 1.;
}

Trig fonksiyonları nedeniyle versiyonunuzdan biraz daha pahalı olacağını unutmayın. Ancak, ortaya çıkan gürültünün görünümünü önemli ölçüde iyileştirir:

Daha iyi karma fonksiyonu ile fbm gürültüsü


Açıklamalarınız için çok teşekkür ederim . Bu belki konu dışı, ama yine de soracağım; Gürültüyü hesaplayan bazı kaynak kodlarında, insanlar nokta ürününü geçerli koordinatla hesaplamak için vec3 vektörünü (1, 57, 113) kullanırlar (Sanırım amaç aynı zamanda bir karma elde etmektir). Bu özel sabit seçimi neden (57 derece derece cinsinden yaklaşık 1 radyan, 133 = derece cinsinden 2 derece radyan)? Trig fonksiyonlarındaki periyodiklik nedeniyle mi? Bunu google’dan alamıyorum.
sarasvati

3
@sarasvati Gerçekten emin değilim, ama bir tahmin 57 ve 113 seçildiğinden, bunlar asal-ish sayılarıdır. (113 asal; 57 değil, ama 3 * 19, bu yüzden hala asal ... bir şeyse.) Asal bir sayıyla çarpma veya modding bitleri karıştırmaya meyillidir, bu yüzden nadir değildir karma olarak madde.
Nathan Reed

1
@ cats GLSL programlarının deterministik olduğu göz önüne alındığında, GLSL'nin bir PRNG'si olduğundan şüpheliyim.
user253751

1
Görünüşe göre, bu yorum
başlığında

1
Bu eserleri yaptırıyordum ve bu rand () işlevi düzeltti. Sorun, arazimde 2 km gibi yürüdükten sonra, OP'ler gibi eserler tekrar ortaya çıkmaya başladı. Burada hash işlevini kullanıyordu: artefaktların ortadan kalkmasına neden olan amindforeverprogramming.blogspot.com/2013/07/… (100 km'lik mesafeler hariç, kesin olmayan, ancak bu tamam, sadece parçalara bölünmek zorunda kaldım ve bunu aldım) perlin gürültüsünün neredeyse süresiz çalışmasına izin verecek her iki değeri de alarak çalışmak. Bu yüzden, burada aynı sorunu yaşayan herkese yardım etmek için bunu burada bırakacağım.
Nicholas Pipitone
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.