2010-11-28 22 views
8

Şu anda Shader Model 4 (DirectX 10 HLSL) kullanarak bir 3D Perlin gürültü çarpması eşleştirmesi uyguluyor. Gürültünün kendiliğinden oluşması büyük bir problem değildir (etraftaki dersler ve kodlar vardır) ama bulamadığım şey 3D Perlin gürültüsünün analitik türevleridir.3D Perlin parazit analitik türevi

Türevleri dikkate alan tek siteler Ińigo Quilez's site ve ilgili GameDev.net discussion'dur. Sorun şu ki, ilk linkte gürültü değer tabanlı değil, gradyan tabanlı (benim için bir gereksinim), ikinci linkte sadece 2D gradyan gürültü türevi var.

Sayısal türevleri aramayacağımı, 4 tane komşu gürültü örneğini gerektirdiğinden ve bu şekilde çok fazla masraf gerektirmediğimi unutmayın.

Bu türevleri herhangi biri hesapladı mı? Onları kullanan bir referans uygulaması var mı?

+0

http://www.scratchapixel.com/lessons/procedural-generation-vritual-worlds%20/perlin-noise-part-2/perlin-noise-computing-derivatives – user18490

cevap

15

Ayrıca bugün internette bir çözüm bulamadım, bu yüzden onu türetmeye çalıştım.

İlk olarak bir 3D Perlin gürültüsü gösterimleri tanımlanır. Gösterim

3D Perlin gürültü varsayalım

u, v, w fraksiyon koordinatları (arasında quintic polinomla enterpolasyon faktörlerdir
n = Lerp(
     Lerp(
      Lerp(dot000, dot100, u), 
      Lerp(dot010, dot110, u), 
      v), 
     Lerp(
      Lerp(dot001, dot101, u), 
      Lerp(dot011, dot111, u), 
      v), 
     w) 

olarak üç çizgili enterpolasyon ile elde edilir, yani, perlin gelişmiş gürültü):

x0 = frac(x) 
y0 = frac(y) 
z0 = frac(z) 
x1 = x0 - 1 
y1 = y0 - 1 
z1 = z0 - 1 

u = x0 * x0 * x0 * (x0 * (6 * x0 - 15) + 10) 
v = y0 * y0 * y0 * (y0 * (6 * y0 - 15) + 10) 
w = z0 * z0 * z0 * (z0 * (6 * z0 - 15) + 10) 

ve dot___ s d vardır gradyan vektörleri (gx___, gy___, gz___) kafes noktalarda s fraksiyon ot ürünler koordinatları:

dot000 = gx000 * x0 + gy000 * y0 + gz000 * z0 
dot100 = gx100 * x1 + gy100 * y0 + gz100 * z0 
dot010 = gx010 * x0 + gy010 * y1 + gz010 * z0 
dot110 = gx110 * x1 + gy110 * y1 + gz110 * z0 
dot001 = gx001 * x0 + gy001 * y0 + gz001 * z1 
dot101 = gx101 * x1 + gy101 * y0 + gz101 * z1 
dot011 = gx011 * x0 + gy011 * y1 + gz011 * z1 
dot111 = gx111 * x1 + gy111 * y1 + gz111 * z1 

türevleri Computing n genişleterek u, v ve w

u' = 30 * x0 * x0 * (x0 - 1) * (x0 - 1) 
v' = 30 * y0 * y0 * (y0 - 1) * (y0 - 1) 
w' = 30 * z0 * z0 * (z0 - 1) * (z0 - 1) 

arasında

İlk olarak, işlem türevleri Lerp(a, b, t) = a + (b - a) * t,

ile birlikte

sonra

nx = gx000 
    + u' (dot100 - dot000) 
    + u (gx100 - gx000) 
    + v (gx010 - gx000) 
    + w (gx001 - gx000) 
    + u'v (dot110 - dot010 - dot100 + dot000) 
    + uv (gx110 - gx010 - gx100 + gx000) 
    + u'w (dot101 - dot001 - dot100 + dot000) 
    + uw (gx101 - gx001 - gx100 - gx000) 
    + vw (gx011 - gx001 - gx010 + gx000) 
    + u'vw(dot111 - dot011 - dot101 + dot001 - dot110 + dot010 + dot100 - dot000) 
    + uvw (gx111 - gx011 - gx101 + gx001 - gx110 + gx010 + gx100 - gx000) 

,
ny = gy000 
    + u (gy100 - gy000) 
    + v' (dot010 - dot000) 
    + v (gy010 - gy000) 
    + w (gy001 - gy000) 
    + uv' (dot110 - dot010 - dot100 + dot000) 
    + uv (gy110 - gy010 - gy100 + gy000) 
    + uw (gy101 - gy001 - gy100 + gy000) 
    + v'w (dot011 - dot001 - dot010 + dot000) 
    + vw (gy011 - gy001 - gy010 + gy000) 
    + uv'w(dot111 - dot011 - dot101 + dot001 - dot110 + dot010 + dot100 - dot000) 
    + uvw (gy111 - gy011 - gy101 + gy001 - gy110 + gy010 + gy100 - gy000) 

,

nz = gz000 
    + u (gz100 - gz000) 
    + v (gz010 - gz000) 
    + w' (dot001 - dot000) 
    + w (gz001 - gz000) 
    + uv (gz110 - gz010 - gz100 + gz000) 
    + uw' (dot101 - dot001 - dot100 + dot000) 
    + uw (gz101 - gz001 - gz100 + gz000) 
    + vw' (dot011 - dot001 - dot010 + dot000) 
    + vw (gz011 - gz001 - gz010 + gz000) 
    + uvw'(dot111 - dot011 - dot101 + dot001 - dot110 + dot010 + dot100 - dot000) 
    + uvw (gz111 - gz011 - gz101 + gz001 - gz110 + gz010 + gz100 - gz000) 

sonra (nx, ny, nz) gürültü fonksiyonunun, gradyan vektörünü (kısmi türevleri) olduğu, n kısmi türevlerini sunar. derleyici bunu işleyemezse

Optimizasyon

Bazı yaygın alt ifadesi, dışarı hesaba katılabilir.Örneğin: genişletilmiş n yılında

uv = u * v 
vw = v * w 
uw = u * w 
uvw = uv * w 

katsayıları birden çok kez tekrar kullanılmaktadır.

gxk0 = gx100 - gx000 
gxk1 = gx010 - gx000 
... 

n kutunun hesaplama, hem de ... k6k0 ile genişletilmiş biçimini kullanır da

k0 = dot100 - dot000 
k1 = dot010 - dot000 
k2 = dot001 - dot000 
k3 = dot110 - dot010 - k0 
k4 = dot101 - dot001 - k0 
k5 = dot011 - dot001 - k1 
k6 = (dot111 - dot011) - (dot101 - dot001) - k3 

türevleri benzer katsayıları var Bunlar hesaplanabilir.

Son sözler

Bu çözelti merkezi fark yöntemi karşı doğrulandı.

bu çözüm sakar görünüyor olsa da

, denemem (CPU sadece, SSE) bu çözümün bu türevleri işlem yalnızca tek bir 3D Perlin parazit örneği hesaplama yaklaşık % 50 ekstra zaman harcar, gösterdi.

Sonlu fark en azından% 300 ekstra süreye (ekstra 3 numune yapmak) veya% 600'e (merkezi fark için 6 örnek yapmak) ihtiyaç duyacaktır. Bu nedenle, bu çözüm performans açısından daha iyidir ve ayrıca sayısal olarak daha kararlı olmalıdır.

+2

dot111 listenizde iki kez bulunur. Bunun bir örneği aslında dot101 olmalıdır – plasmacel

+0

Teşekkürler @plasmacel. Sabit. –

+0

Türetmenin bir Wolfram Mathematica defterine sahip misiniz? – plasmacel