Godot’ta Uygulanan FFT Tabanlı Okyanus Dalgası Render’ı
(github.com/2Retr0)- GodotOceanWaves, Godot Engine’de yönlü okyanus dalgası spektrumunun ters Fourier dönüşümünü kullanarak açık deniz yüzeyi oluşturan bir render deneyi; gerçek zamanlı olarak betiklerle ayarlanabilen parametrelerle çeşitli okyanus ortamlarını simüle eder
- Gerstner waves sakin suyun düşük frekanslı ayrıntıları için uygun olsa da dalgalı açık deniz yüzeylerinde sınırlı kalır; bu proje bu nedenle ampirik oşinografi verilerine dayalı spektrumlar ve FFT kullanır
- Dalga üretimi Tessendorf yöntemini izleyerek başlangıç spektrum durumunu oluşturur, dağılım ilişkisiyle zaman içinde yayar ve ters Fourier dönüşümüyle displacement, normal ve foam map üretir
- Render, Atlas GDC sunumundaki BSDF’yi izler ancak GGX dağılımını kullanır; foam, displacement’ın Jacobian’ının negatif olduğu bölgelerde biriktirilip sönümlenir, sea spray ise Godot’un GPUParticles3D ve özel shader’larıyla uygulanır
- Çoklu wave cascade, güncelleme periyodu ayarı ve cascade bazında yük dağıtımıyla tiling ve GPU iş yükü yönetilir; ancak cascade’lerin aynı spektrum texture çözünürlüğünü kullanması gerekir ve sea spray parçacık yöntemi yoğunluk artışı açısından düşük verimlidir
GodotOceanWaves ne yapıyor
- GodotOceanWaves, Godot Engine’de açık deniz render’ını deneyen bir projedir
- Dalga üretiminde yönlü okyanus dalgası spektrumunun ters Fourier dönüşümü kullanılır
- Dışa açılan parametreler sade tutulmuştur ve betiklerle gerçek zamanlı değiştirerek çeşitli okyanus dalgası ortamları simüle edilebilir
- Demo video olarak
ocean_demo.mp4veenvironment_demo.mp4dahildir
Gerstner waves yerine neden Fourier tabanlı dalgalar kullanılıyor
- Oyunlarda suyu canlandırmanın yaygın bir yolu, vertex’leri Gerstner waves ile displacement’a uğratmaktır
- Gerstner waves sakin suyun düşük frekanslı ayrıntılarını modellemek için uygundur, ancak açık denizin dalgalı yüzeyini doğru ifade etmekte yetersiz kalır
- Oşinografların topladığı ampirik verilere dayalı okyanus dalgası spektrumları kullanıldığında, belirli bir deniz durumu oluşturmak için hangi dalgaların ve parametrelerin değiştirileceği daha doğrudan ele alınabilir
- FFT, klasik ayrık Fourier dönüşümünün
O(N^2)karmaşıklığından daha düşükO(N log N)karmaşıklığa sahiptir; paralel sistemlere ölçeklenebildiği için GPU’da çalıştırmaya uygundur - Gerstner waves’te her thread’in
Nadet dalga için hesaplama yapması gerekirken, FFT tabanlı dalgalarda her thread yalnızcalog(N)düzeyinde hesaplama yapar
Shading, foam ve sea spray
- Okyanus aydınlatma modeli genel olarak Atlas GDC sunumundaki BSDF’yi izler
- Mikrofacet dağılımı olarak Beckmann yerine GGX kullanılır
- Çünkü GGX’in daha düz ve yumuşak highlight’ları, test edilen çeşitli okyanus dalgası ortamlarında daha tutarlı bir görünüm sağladı
- Normal/foam map’ler, dünya uzayı piksel yoğunluğuna göre bicubic ve bilinear filtreleme karıştırılarak örneklenir
- Düşük yüzey çözünürlüğünde texture aliasing artefaktlarını azaltır, yüksek yüzey çözünürlüğünde ise ayrıntıyı korur
- Sea foam, Tessendorf yöntemine göre dalga tepelerinin içe kıvrıldığı yerlerde, yani displacement’ın Jacobian’ının negatif olduğu bölgelerde oluşturulup oluşturulmayacağına karar verir
- Foam, birden fazla dalga güncellemesi boyunca texture içinde doğrusal olarak birikir
"foam grow rate"ve"foam decay rate"parametreleri sırasıyla birikimi ve üstel sönümlenmeyi kontrol eder
- Sea spray, Godot’un
GPUParticles3Dnode’u ve özel particle shader’ıyla uygulanır- Parçacıklar
GPUParticles3Dbounding box’ı içindeki bir düzleme eşit dağıtılır - İlgili konumdaki foam miktarına göre culling uygulanır; culling edilmeyen parçacıklar yaşam döngüsüne rastgele bir offset’ten başlar
- Her parçacık, tek bir statik texture kullanan billboard sprite kullanır
- Yaşam döngüsü boyunca scale ve displacement değiştirilerek splash görünümü simüle edilir; mesh shader’daki dissolve efektiyle havada su serpintisinin atomize olması hissi verilir
- Parçacıklar
- Bu sea spray yaklaşımının büyük dezavantajı, parçacık sayısı büyük ölçüde artırılsa bile yoğunluk artışının küçük olmasıdır
- Çünkü parçacıklar bounding box’a eşit dağıtıldığından eklenen parçacıkların çoğu culling edilir
Dalga simülasyonu pipeline’ı
- Yüzey dalgası üretim yöntemi Tessendorf’u yakından izler
- Yönlü okyanus dalgası spektrum fonksiyonu, Gaussian dağılımlı rastgele sayılarla çarpılarak başlangıç spektrum deniz durumu oluşturulur
- Başlangıç durumu, dalganın frekansı ile yayılma hızını ilişkilendiren dağılım ilişkisiyle zaman içinde yayılır
- Yayılan duruma ters Fourier dönüşümü uygulanarak displacement map ve normal map oluşturulur
- Uygulama, Godot’un
RenderingDevicesoyutlamasını kullanan bir compute shader pipeline olarak yapılandırılmıştır
Okyanus dalgası spektrumunun yapısı
- Yönlü okyanus dalgası spektrum fonksiyonu
S(ω, θ), frekansωve yönθverildiğinde dalganın enerjisini döndürür - Bu fonksiyon, yönsüz spektrum fonksiyonu
S(ω)ve yönlü yayılım fonksiyonuD(ω, θ)bileşenlerinden oluşur; iki seçim birbirinden bağımsızdır - Yönsüz spektrumda Horvath’ın açıkladığı Texel-Marsen-Arsloe(TMA) spektrumu kullanılır
- TMA, rüzgâr hızı
U, su derinliğiDve fetch lengthFkullanır - TMA, öncülü olan JONSWAP spektrumu ile su derinliği sönümleme fonksiyonunu birleştirir
- TMA, rüzgâr hızı
- Yönlü yayılım fonksiyonunda Horvath’ın flat ve Hasselmann yönlü yayılımlarını
spreadparametresiμile karıştıran yöntem kullanılır- Horvath’ın önerdiği
swellparametresiξde okyanus dalgalarının elongation’ını modellemek için dahildir - Hasselmann yönlü yayılımı, normalizasyon katsayısı
Q(σ)için yaklaşık analitik çözüm sunduğu için seçilmiştir
- Horvath’ın önerdiği
- Tessendorf’un önerisine göre sonuç spektrum fonksiyonu küçük dalga bastırma terimiyle de çarpılır
- Bu terim dalga sayısı vektörünün büyüklüğü
kvedetailparametresiδkullanır
- Bu terim dalga sayısı vektörünün büyüklüğü
- Nihai yönlü okyanus dalgası spektrumu TMA, mixed directional spread ve small-wave suppression bileşenlerini birleştirir
GPU FFT uygulaması
- FFT, compute shader ile yazılmış özel bir GPU uygulaması kullanır
- Cooley-Tukey yerine, başlangıçtaki bit-reversal permutation’ı önlemek için Stockham FFT algoritması kullanılır
- Flügge’yi izleyerek, FFT’nin veri akışını kodlayan
"butterfly"texture’ı hesaplanır- Bu texture, spektrum texture çözünürlüğü her değiştiğinde bir kez hesaplanır
- 2D FFT önce spektrum texture’ının satır yönünde FFT kernel’ini uygular
- Ardından compute shader ile texture transpose edilir ve aynı satır yönlü FFT kernel’i sütun yönlü FFT gibi yeniden kullanılır
- Transpose yalnızca pipeline’ın yeniden kullanımını mümkün kılmakla kalmaz, bellek erişim desenini de iyileştirir
Wave cascade ve tiling’e karşı önlemler
- Uzak mesafelerde, özellikle sea foam olduğunda tiling artefaktları çok belirginleşir
- Dalga üretim sistemi, bu sorunu ele almak için birden fazla wave cascade’in aynı anda katmanlanmasına izin verir
- Her cascade’in kendi tiling boyutu ve parametre seti vardır
- Cascade’ler gerçek zamanlı olarak dinamik biçimde eklenip çıkarılabilir
- Tüm cascade’ler aynı compute pipeline’ını kullandığından aynı spektrum texture çözünürlüğüne sahip olmalıdır
- Alternatif olarak, dalga displacement’ı ve normal’leri noise ile harmanlayarak daha düşük performans maliyetiyle tiling artefaktları azaltılabilir
- Cascade’ler üst üste bindirilirken dalga girişimini önlemek için her cascade’in parametreleri ve boyutu dikkatle seçilmelidir
- Cascade’lerin dalga phase’leri de birbirleriyle girişim yapmayacak şekilde offset edilmelidir
- Sistem, her cascade’in başlangıç zamanını farklı offset’leyerek bunu otomatik olarak denemektedir
- Bu yöntemin gerçekten işe yarayıp yaramadığına dair bir caveat bulunduğu belirtilir
Güncelleme yükünü dağıtma
- Dalga hareketi düzensiz olduğu için displacement her frame güncellenmese bile algısal olarak akıcı görünebilir
"update rate"parametresi, wave cascade’in saniyede ne sıklıkla güncelleneceğini kontrol eder- Frame atlamak, FFT için kullanılan GPU süresini azaltır; ancak dalga üretim pipeline’ının çalıştığı frame’lerde yine de stutter oluşur
- Godot’un yerel
RenderingDevice’ı ile cascade güncellemelerini asenkron hesaplama olarak yürütme deneyi, CPU ile GPU arasındaki texture aktarımı nedeniyle büyük performans overhead’i oluşturmuştur - Bunun yerine sistem cascade’lerin yük dağıtımını dener
- Frame süresi update rate’ten kısaysa frame başına yalnızca bir cascade güncellenir
- Bu yöntem, stutter’ı azaltırken frame atlamayla elde edilen düşük GPU iş yükü avantajını korur
Yararlanılan kaynaklar
- Realtime GPGPU FFT Ocean Water Simulation: Fynn-Jorin Flügge, Hamburg University of Technology, 2017
- I Tried Simulating The Entire Ocean: Garrett Gunnell, 2023
- Empirical Directional Wave Spectra for Computer Graphics: Christopher J. Horvath, DigiPro, 2015
- Simulating Ocean Water: Jerry Tessendorf, SIGGRAPH, 2004
- Implementing Fast Fourier Transform Algorithms of Real-Valued Sequences: Robert Matusiak, Texas Instruments, 2001
- Wakes, Explosions and Lighting: Interactive Water Simulation in 'Atlas': Mark Mihelich, GDC, 2019
- FFT-Ocean: Ivan Pensionerov, GitHub, 2020
1 yorum
Hacker News yorumları
Bu kişinin yaptığı diğer iki Godot deposu da çok ilginç. Depoları açıklarken bol ayrıntı vermesini seviyorum; özellikle şu depo dikkat çekiyor: https://github.com/2Retr0/GodotGaussianSplatting
Öğrenci mi merak ediyorum. Başka çalışmalara sık sık atıf yapıyor ve yakın zamanda yayımlanan materyalleri epey iyi anlamış görünüyor
ENGR96A-coursework,Relevant coursework for ENGR 96A Introduction to Engineering Design F23; commit tarihlerine bakınca F23 muhtemelen 2023 güz dönemi demekElbette depoda adı geçen UCLA dersleri herkese açık olabilir; bu yüzden geleneksel anlamda UCLA'ya kayıtlı bir öğrenci olmadan da alınabiliyor olabilir
20 yıl önce render'da deniz yüzeyini aylarca ayarlasak bile bu seviyenin yakınına gelemezdik sanırım. Gerçekten çok iyi yapılmış bir sonuç
Yine de demo videosu biraz abartılı görünüyor. Seyir kayıtlarında açık deniz seyri 50 bin deniz milini aşan biri olarak, bu kadar sivri ve yüksek dalgalar varsa rüzgârın çok daha sert esmesi gerekir. Yine de muhtemelen sadece parametre ayarıyla çözülecek bir kısım
Godot ile yapıldıysa gerçek zamanlı render sayılır mı? Canavar gibi bir GPU gerektirip gerektirmediğini de merak ediyorum
Ayrıca burada deniz serpintisi sonradan eklenmiş bir efekt gibi görünüyor; gerçek denizde ise serpinti dalgaların keskinliğini köreltir ve bu görsel olarak da belli belirsiz fark edilir
Elbette bu zarif, basit ve etkili modelde neredeyse hiç fizik yok; o yüzden bunları kolları kavuşturup eleştirmekten çok, kurcalayıp denenebilecek yönler önermek olarak görün
Bu konuda sevdiğim videolardan biri: https://m.youtube.com/watch?v=yPfagLeUa7k
Bu da fena değil: https://m.youtube.com/watch?v=kGEqaX4Y4bQ
Onun yerine her hafta sonu su shader'ıyla oynayıp istediğim görüntüyü elde etmeye çalışıyorum. Ama oyunum bir bulmaca oyunu, suya ihtiyacı yok. Şimdi sadece havalı bir başlangıç ekranım var
Bugünlerde oyun motorunda tek bir checkbox'tan ibaret ve buna benzer sayısız özellik var. Modern motorlar sayesinde ortamın ne kadar iyi olduğunu insanlar pek hayal edemiyor
Bu çalışmanın değerini düşürmek istemiyorum; gerçekten harika bir başarı ve yapana şapka çıkarıyorum. Sadece şu anda ne kadar iyi bir dönemde olduğumuzu söylemek istedim
Yine de çok iyi görünüyor ve yakın zamanda üstünkörü baktıklarım arasında muhtemelen mümkün olanların en üst seviyesinde
Kişisel olarak açık deniz dalgalarının genelde daha ritimli görünmesini isterdim. 15 knot rüzgârın 1 km'lik su yüzeyi üzerinde birkaç saat estiği bir simülasyonun gerçekten gözlenen şeye, yani nispeten düzenli kırılmaların oluşup dağıldığı görünüme uyup uymadığını merak ediyorum
Beni bilgisayar dünyasına çeken şeyler bunlardı; ama bir bakmışım kütüphaneleri, endpoint'leri ve kurumsal saçmalıkları birbirine bağlayan kolay ve sıkıcı bir hayata saplanmışım, bu da tükenmişliğe gidiyor
Bir gün geri dönebilmeyi umuyorum
Denemeni isterim. Hepimiz destekliyoruz
Yaklaşımı farklı olsa da dalga/okyanus simülasyonu ile ilgileniyorsanız Acerola bu konuda her zamanki gibi harika bir video yayımladı. https://youtu.be/PH9q0HNBjT4 ve https://youtu.be/yPfagLeUa7k
Düzenleme: Bunlardan biri kaynakçada zaten linklenmişti; kullanıcı adıyla değil gerçek adıyla yer aldığı için ancak şimdi fark ettim
Bu problemin ne kadar zor olduğu ilginç. On yıllardır deneniyor ama hâlâ tekinsiz vadide kalıyor
Bu sahneyi durdurduğunuzda yükselen dalgalar karla kaplı dağlara benziyor. Suyun böyle keskin şekiller alması için rüzgârın epey güçlü olması gerekir; rüzgârın da doğrudan yukarı esmesi mümkün olmadığından gerçek dışı geliyor. Böyle keskin özelliklerin bir yönlülüğü olmalı
Yine de solugan dalgaların karakterini epey iyi yakalamış. Yatay hareketten çok yukarı-aşağı hareket daha büyük; açık denizde beklenebilecek görünüm de bu
Işık geçirgenliğini nasıl simüle ettiklerini bilmiyorum ama iyi çalışıyor. Gün doğumu ya da gün batımında dalgaların arasından süzülen ışık harika ve efekti gerçekten inandırıcı kılıyor
Biraz resimsel denebilir, ama yanlış görünmüyor
Yıllarca sahilde yaşadım. Sahilde yaşayınca deniz büyüleyici ve duyusal olarak hoş olduğu için saatlerce bakıyorsunuz. Bunu görsem bir an bile render olduğunu düşünmezdim
Shadertoy'da da iyi bir örnek var: https://www.shadertoy.com/view/Ms2SD1
Fourier gelgit dalgalarını ölçerken dalga frekansı dönüşümünü düşündüğüne göre, bir anlamda neredeyse başa dönmüş sayılırız
Çok etkileyici
Harika, ama bu yaklaşım gerçekten büyük dalgalarda doğrusal olmama nedeniyle bir noktada bozulacaktır. Su dalgaları sinüs dalgası değildir; ama küçük ve orta yükseklikteki dalgalarda yeterince benzer oldukları için bu yöntem çok iyi çalışır
Çok büyük dalgalar sinüs dalgasından çok daha fazla uzaklaşmakla kalmaz, dalgalar birbirleriyle doğrusal olmayan biçimde etkileşmeye başlar; burada kullanılan doğrusal süperpozisyon yöntemi bunu yakalayamaz
Bu yüzden çoğu deniz durumu için şahane. Ama “Kusursuz Fırtına” türü dalgaları gerçekçi yapmak istiyorsanız başka bir yaklaşım gerekir
Çok etkileyici ve şimdiye kadar gördüklerimden iyi, ama solugan biraz yanlış hissettiriyor. Açıklamaya çalışırsam, yüksek frekanslı dalgaların videodaki gibi düşük frekanslı dalgaların üzerinde ilerlediğini sanmıyorum