- GodotOceanWaves es un experimento de renderizado que genera superficies de mar abierto en Godot Engine usando la transformada inversa de Fourier de espectros direccionales de olas oceánicas, con parámetros ajustables en tiempo real mediante scripts para simular diversos entornos marinos
- Las Gerstner waves son adecuadas para detalles de baja frecuencia en aguas tranquilas, pero tienen limitaciones para superficies agitadas de mar abierto, por lo que este proyecto usa espectros basados en datos oceanográficos empíricos y FFT
- La generación de olas sigue el método de Tessendorf: crea un estado espectral inicial, lo propaga en el tiempo mediante la relación de dispersión y luego genera mapas de desplazamiento, normales y espuma con una transformada inversa de Fourier
- El renderizado sigue el BSDF de la presentación de Atlas en GDC, pero usa una distribución GGX; la espuma se acumula y se atenúa en las zonas donde el Jacobiano del desplazamiento es negativo, y el sea spray se implementa con GPUParticles3D de Godot y shaders personalizados
- Maneja el tiling y la carga de trabajo de GPU con múltiples wave cascades, control de frecuencia de actualización y distribución de carga por cascade, aunque las cascades deben usar la misma resolución de textura espectral y el método de partículas para sea spray es poco eficiente al aumentar la densidad
Qué hace GodotOceanWaves
- GodotOceanWaves es un proyecto que experimenta con renderizado de mar abierto en Godot Engine
- Para generar las olas usa la transformada inversa de Fourier de un espectro direccional de olas oceánicas
- Los parámetros expuestos están organizados de forma concisa y pueden modificarse en tiempo real mediante scripts para simular varios entornos de olas oceánicas
- Incluye videos de demostración:
ocean_demo.mp4yenvironment_demo.mp4
Por qué usar olas basadas en Fourier en lugar de Gerstner waves
- Una forma común de animar agua en juegos es desplazar vértices con Gerstner waves
- Las Gerstner waves funcionan bien para modelar detalles de baja frecuencia en aguas tranquilas, pero no bastan para representar con precisión la superficie agitada del mar abierto
- Al usar espectros de olas oceánicas basados en datos empíricos recopilados por oceanógrafos, se puede tratar de forma más directa qué olas y parámetros modificar para crear un estado marino específico
- FFT tiene una complejidad
O(N log N), menor que elO(N^2)de la transformada discreta de Fourier clásica, y puede escalarse a sistemas paralelos, por lo que es adecuada para ejecutarse en GPU - Con Gerstner waves, cada hilo debe calcular sobre
Nolas, mientras que con olas basadas en FFT cada hilo solo realiza cálculos equivalentes alog(N)
Shading, espuma y sea spray
- El modelo de iluminación oceánica sigue en gran medida el BSDF de la presentación de Atlas en GDC
- Para la distribución de microfacetas se usa GGX en lugar de Beckmann
- Esto se debe a que los highlights más planos y suaves de GGX ofrecieron un aspecto más uniforme en varios entornos de olas oceánicas probados
- Los mapas de normales/espuma se muestrean mezclando filtrado bicúbico y bilineal según la densidad de píxeles en espacio mundial
- En baja resolución de superficie se reducen los artefactos de aliasing de textura, y en alta resolución de superficie se conserva el detalle
- La espuma marina determina si se genera según el método de Tessendorf, en los lugares donde la cresta de la ola se enrolla hacia adentro, es decir, donde el Jacobiano del desplazamiento es negativo
- La espuma se acumula linealmente en la textura a lo largo de varias actualizaciones de olas
- Los parámetros
"foam grow rate"y"foam decay rate"controlan, respectivamente, la acumulación y la atenuación exponencial
- El sea spray se implementa con el nodo
GPUParticles3Dde Godot y un shader de partículas personalizado- Las partículas se distribuyen uniformemente sobre un plano dentro de la caja delimitadora de
GPUParticles3D - Se descartan según la cantidad de espuma en esa posición, y las partículas no descartadas inician su ciclo de vida desde un offset aleatorio
- Cada partícula usa un billboard sprite con una única textura estática
- Durante su ciclo de vida cambia la escala y el desplazamiento para simular la apariencia de un splash, y el efecto dissolve del mesh shader da la sensación de que la salpicadura se atomiza en el aire
- Las partículas se distribuyen uniformemente sobre un plano dentro de la caja delimitadora de
- La principal desventaja de este método de sea spray es que, aunque se aumente mucho el número de partículas, el incremento de densidad es pequeño
- Esto ocurre porque las partículas se distribuyen uniformemente en la caja delimitadora y la mayoría de las partículas añadidas se descartan
Pipeline de simulación de olas
- El método de generación de olas de superficie sigue de cerca a Tessendorf
- Se genera un estado inicial del mar en el dominio espectral multiplicando la función de espectro direccional de olas oceánicas por ruido aleatorio con distribución gaussiana
- El estado inicial se propaga en el tiempo mediante la relación de dispersión, que conecta la frecuencia de las olas con su velocidad de propagación
- Al estado propagado se le aplica una transformada inversa de Fourier para generar mapas de desplazamiento y de normales
- La implementación está compuesta como un compute shader pipeline que usa la abstracción
RenderingDevicede Godot
Composición del espectro de olas oceánicas
- La función de espectro direccional de olas oceánicas
S(ω, θ)devuelve la energía de la ola para una frecuenciaωy una direcciónθdadas - Esta función se compone de una función de espectro no direccional
S(ω)y una función de dispersión direccionalD(ω, θ), y ambas elecciones son independientes entre sí - Para el espectro no direccional se usa el espectro Texel-Marsen-Arsloe(TMA) descrito por Horvath
- TMA usa velocidad del viento
U, profundidad del aguaDy fetch lengthF - TMA combina el espectro JONSWAP previo con una función de atenuación por profundidad
- TMA usa velocidad del viento
- Para la función de dispersión direccional se usa una mezcla entre las dispersiones direccionales flat y Hasselmann de Horvath mediante el parámetro
spreadμ- También incluye el parámetro
swellξpropuesto por Horvath para modelar la elongation de las olas oceánicas - Se eligió la dispersión direccional de Hasselmann porque ofrece una solución analítica aproximada para el coeficiente de normalización
Q(σ)
- También incluye el parámetro
- Siguiendo la propuesta de Tessendorf, la función espectral resultante también se multiplica por un término de supresión de olas pequeñas
- Este término usa la magnitud del vector de número de onda
ky el parámetrodetailδ
- Este término usa la magnitud del vector de número de onda
- El espectro direccional final de olas oceánicas combina TMA, mixed directional spread y small-wave suppression
Implementación de FFT en GPU
- FFT usa una implementación GPU personalizada escrita como compute shader
- En lugar de Cooley-Tukey, se usa el algoritmo Stockham FFT para evitar la permutación inicial de bit-reversal
- Siguiendo a Flügge, se calcula una textura
"butterfly"que codifica el flujo de datos de la FFT- Esta textura se calcula una sola vez cada vez que cambia la resolución de la textura espectral
- La FFT 2D primero aplica el kernel FFT en la dirección de las filas de la textura espectral
- Luego se transpone la textura con un compute shader para reutilizar el mismo kernel FFT de dirección de filas como si fuera FFT en dirección de columnas
- La transposición no solo permite reutilizar el pipeline, sino que también mejora el patrón de acceso a memoria
Wave cascade y manejo del tiling
- A grandes distancias, especialmente cuando hay sea foam, los artefactos de tiling se vuelven muy evidentes
- El sistema de generación de olas aborda este problema permitiendo superponer varias wave cascades al mismo tiempo
- Cada cascade tiene su propio tamaño de tiling y conjunto de parámetros
- Las cascades pueden agregarse o eliminarse dinámicamente en tiempo real
- Como todas las cascades usan el mismo compute pipeline, deben tener la misma resolución de textura espectral
- Como alternativa, también se pueden mezclar el desplazamiento y las normales de las olas con ruido para reducir los artefactos de tiling con menor costo de rendimiento
- Al superponer cascades, los parámetros y tamaños de cada cascade deben elegirse cuidadosamente para evitar interferencias entre olas
- La phase de las olas de cada cascade también debe desplazarse para que no interfieran entre sí
- El sistema intenta hacerlo automáticamente desplazando de forma distinta el tiempo de inicio de cada cascade
- Se incluye la salvedad de que no está claro si este método funciona realmente
Distribución de la carga de actualización
- Como el movimiento de las olas es irregular, no es necesario actualizar el desplazamiento en cada frame para que perceptualmente se vea fluido
- El parámetro
"update rate"controla cuántas veces por segundo se actualiza una wave cascade - Saltarse frames reduce el tiempo de GPU usado por la FFT, pero en los frames donde se ejecuta el pipeline de generación de olas todavía puede producirse stutter
- Los experimentos de cálculo asíncrono para actualizar cascades con el
RenderingDevicelocal de Godot generaron una gran sobrecarga de rendimiento por la transferencia de texturas entre CPU y GPU - En su lugar, el sistema intenta distribuir la carga de las cascades
- Si el tiempo de frame es menor que el update rate, solo actualiza una cascade por frame
- Este método reduce el stutter y mantiene la ventaja de menor carga de trabajo en GPU que se obtiene al saltarse frames
Materiales de referencia
- 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 comentarios
Opiniones en Hacker News
Los otros dos repositorios de Godot de esta persona también son muy interesantes. Me gusta que incluya mucho detalle al describir los repositorios, y este en particular destaca: https://github.com/2Retr0/GodotGaussianSplatting
Me pregunto si será estudiante. Cita con frecuencia otros trabajos y parece entender bastante bien materiales publicados recientemente.
ENGR96A-courseworkyRelevant coursework for ENGR 96A Introduction to Engineering Design F23, y por las fechas de los commits, F23 parece significar el semestre de otoño de 2023.Claro que las clases de UCLA mencionadas en el repositorio podrían estar abiertas al público, así que quizá no necesariamente haya que ser estudiante inscrito en UCLA en el sentido tradicional para tomarlas.
Hace 20 años, aunque hubiéramos ajustado durante meses la superficie del mar en un render, creo que no nos habríamos acercado a este nivel. Es un resultado realmente bien logrado.
Dicho eso, el video demo se ve un poco exagerado. Desde la perspectiva de alguien con más de 50.000 millas náuticas de navegación en mar abierto en su bitácora, si las olas fueran tan puntiagudas y altas, el viento tendría que soplar con mucha más fuerza. Aun así, parece algo que se arregla ajustando parámetros.
Si está hecho con Godot, ¿podemos considerarlo renderizado en tiempo real? También me da curiosidad si requiere una GPU monstruosa.
Además, aquí la espuma marina parece un efecto posterior, mientras que en el mar real la espuma suaviza lo afilado de las olas, algo que también se percibe visualmente de forma sutil.
Por supuesto, este modelo elegante, simple y eficaz casi no tiene física, así que espero que esto se tome más como una exploración y una sugerencia de posibles direcciones a probar que como una crítica de brazos cruzados.
Uno de mis videos favoritos sobre el tema: https://m.youtube.com/watch?v=yPfagLeUa7k
Este también está bien: https://m.youtube.com/watch?v=kGEqaX4Y4bQ
En cambio, paso los fines de semana jugando con shaders de agua hasta que se vean como quiero. Pero mi juego es de puzzles, así que no necesita agua. Ahora solo tengo una pantalla inicial genial.
Hoy son apenas una casilla en un motor de juegos, y hay incontables funciones así. La gente no alcanza a imaginar lo buen entorno que tenemos gracias a los motores modernos.
No lo digo para restarle valor a este trabajo; es un logro realmente excelente y felicito a quien lo hizo. Solo quería señalar lo buena que es la época en la que estamos.
Aun así, se ve muy bien, y dentro de lo que he buscado por encima recientemente, probablemente esté entre lo mejor posible.
Personalmente, me gustaría ver que las olas de mar abierto tengan normalmente más ritmo. Me pregunto si una simulación de viento de 15 nudos soplando durante varias horas sobre 1 km de superficie de agua coincide con lo que se observa en la realidad: rupturas relativamente ordenadas que se forman y luego se dispersan.
Este tipo de cosas fueron las que me atrajeron al mundo de la computación, y de pronto caí en una vida fácil y aburrida de pegar librerías, endpoints y tonterías corporativas, lo que me está llevando al burnout.
Espero poder volver algún día.
Ojalá lo intentes. Todos te estamos apoyando.
Aunque el enfoque es distinto, si te interesa la simulación de olas/océanos, Acerola hizo un video excelente sobre este tema, como siempre. https://youtu.be/PH9q0HNBjT4 y https://youtu.be/yPfagLeUa7k
Edición: uno ya estaba enlazado en la bibliografía, pero estaba con su nombre real y no con el nick, así que recién me di cuenta.
Es interesante lo difícil que es este problema. Llevamos décadas intentándolo y todavía seguimos en el valle inquietante.
Si pausas esta escena, las olas elevadas parecen montañas nevadas. Para que el agua tenga formas tan afiladas, el viento tendría que ser bastante fuerte, pero el viento no soplaría directamente hacia arriba, así que se siente irreal. Esos rasgos afilados deberían tener direccionalidad.
Aun así, capta bastante bien la naturaleza del oleaje de fondo. El movimiento vertical es mayor que el desplazamiento horizontal, que es lo que uno esperaría en mar abierto.
No sé cómo simulan la transmisión de la luz, pero funciona bien. La luz que atraviesa las olas al amanecer o al atardecer es excelente y hace que el efecto resulte muy convincente.
Se podría decir que es un poco pictórico, pero no se ve mal.
Viví varios años en la playa. Cuando vives en la playa, el mar es fascinante y sensorialmente agradable, así que te quedas mirándolo durante horas. Al ver esto, ni por un instante habría pensado que era un render.
También hay un buen ejemplo en Shadertoy: https://www.shadertoy.com/view/Ms2SD1
Fourier tuvo la idea de la transformación de frecuencias de ondas mientras medía ondas de marea, así que en cierto sentido casi cerramos el círculo.
Muy impresionante.
Es excelente, pero este enfoque se romperá hasta cierto punto con olas realmente grandes debido a la no linealidad. Las olas no son senoidales, pero en olas pequeñas y medianas se parecen lo suficiente como para que este método funcione muy bien.
Las olas muy grandes no solo se alejan mucho más de una senoide, sino que además empiezan a interactuar entre sí de forma no lineal, algo que el método de superposición lineal usado aquí no puede capturar.
Así que es fantástico para la mayoría de los estados del mar. Pero si quieres crear de forma realista olas como las de “La tormenta perfecta”, necesitas otro enfoque.
Muy impresionante y mejor que lo que he visto hasta ahora, pero el oleaje de fondo se siente un poco raro. Si tuviera que explicarlo, diría que las olas de alta frecuencia no viajan sobre las de baja frecuencia como en el video.