1 pontos por GN⁺ 2024-09-29 | 1 comentários | Compartilhar no WhatsApp
  • GodotOceanWaves é um experimento de renderização no Godot Engine que gera a superfície de oceano aberto usando a transformada inversa de Fourier de um espectro direcional de ondas oceânicas, simulando diversos ambientes marítimos com parâmetros ajustáveis em tempo real por script
  • As Gerstner waves são adequadas para detalhes de baixa frequência em águas calmas, mas têm limitações para superfícies agitadas de oceano aberto, então este projeto usa espectros baseados em dados empíricos de oceanografia e FFT
  • A geração das ondas segue o método de Tessendorf: cria um estado espectral inicial, propaga no tempo com a relação de dispersão e depois gera mapas de deslocamento, normais e espuma com a transformada inversa de Fourier
  • A renderização segue o BSDF apresentado na GDC de Atlas, mas usa distribuição GGX; a espuma se acumula e decai em regiões onde o Jacobiano do deslocamento é negativo; o sea spray é implementado com GPUParticles3D do Godot e shaders customizados
  • Cascatas múltiplas de ondas, controle da taxa de atualização e distribuição de carga por cascata ajudam a lidar com tiling e carga de GPU, mas as cascatas precisam usar a mesma resolução de textura espectral e a abordagem de partículas para sea spray é ineficiente para aumentar a densidade

O que o GodotOceanWaves faz

  • GodotOceanWaves é um projeto experimental de renderização de oceano aberto no Godot Engine
  • A geração das ondas usa a transformada inversa de Fourier de espectros direcionais de ondas oceânicas
  • Os parâmetros expostos foram organizados de forma enxuta e podem ser alterados em tempo real por script para simular vários ambientes de ondas marítimas
  • O projeto inclui os vídeos de demonstração ocean_demo.mp4 e environment_demo.mp4

Por que usar ondas baseadas em Fourier em vez de Gerstner waves

  • Uma forma comum de animar água em jogos é deslocar vértices com Gerstner waves
  • As Gerstner waves funcionam bem para modelar detalhes de baixa frequência em águas calmas, mas não representam com precisão superfícies agitadas de oceano aberto
  • Ao usar espectros de ondas oceânicas baseados em dados empíricos coletados por oceanógrafos, fica mais direto controlar quais ondas e parâmetros devem ser alterados para produzir um estado marítimo específico
  • A FFT tem complexidade O(N log N), menor que os O(N^2) da transformada discreta de Fourier clássica, e pode escalar para sistemas paralelos, o que a torna adequada para execução em GPU
  • Nas Gerstner waves, cada thread precisa calcular N ondas, enquanto em ondas baseadas em FFT cada thread executa apenas cálculos proporcionais a log(N)

Shading, espuma e sea spray

  • O modelo de iluminação oceânica segue em grande parte o BSDF da apresentação da GDC de Atlas
  • A distribuição de microfacet usa GGX em vez de Beckmann
    • Isso porque os highlights mais suaves e achatados da GGX ofereceram uma aparência mais uniforme nos vários ambientes oceânicos testados
  • Os mapas de normais e espuma são amostrados com uma mistura de filtragem bicúbica e bilinear conforme a densidade de pixels no espaço do mundo
    • Em baixa resolução de superfície, isso reduz artefatos de aliasing das texturas, enquanto em alta resolução preserva os detalhes
  • A sea foam é gerada seguindo o método de Tessendorf, detectando onde as cristas das ondas se enrolam para dentro, ou seja, onde o Jacobiano do deslocamento é negativo
    • A espuma é acumulada linearmente na textura ao longo de várias atualizações das ondas
    • Os parâmetros "foam grow rate" e "foam decay rate" controlam, respectivamente, o acúmulo e o decaimento exponencial
  • O sea spray é implementado com o nó GPUParticles3D do Godot e um shader de partículas customizado
    • As partículas são distribuídas uniformemente em um plano dentro da bounding box de GPUParticles3D
    • Elas são descartadas conforme a quantidade de espuma naquela posição, e as que não forem descartadas iniciam seu ciclo de vida com um deslocamento aleatório
    • Cada partícula usa um billboard sprite com uma única textura estática
    • Ao longo do ciclo de vida, scale e displacement são alterados para simular o visual do splash, e um efeito de dissolve no mesh shader cria a sensação de que o spray se atomiza no ar
  • A principal desvantagem dessa abordagem de sea spray é que mesmo um grande aumento no número de partículas produz apenas um pequeno aumento de densidade
    • Isso ocorre porque as partículas são distribuídas uniformemente na bounding box e a maioria das partículas extras acaba sendo descartada

Pipeline de simulação das ondas

  • O método de geração da superfície segue de perto Tessendorf
  • Um estado inicial espectral do oceano é criado multiplicando a função espectral direcional de ondas oceânicas por números aleatórios com distribuição gaussiana
  • O estado inicial é propagado no tempo pela relação de dispersão, que liga a frequência da onda à sua velocidade de propagação
  • Em seguida, aplica-se a transformada inversa de Fourier ao estado propagado para gerar mapas de deslocamento e normais
  • A implementação é composta por um pipeline de compute shaders que usa a abstração RenderingDevice do Godot

Composição do espectro de ondas oceânicas

  • A função espectral direcional de ondas oceânicas S(ω, θ) retorna a energia da onda para uma frequência ω e direção θ
  • Essa função é composta por uma função espectral não direcional S(ω) e uma função de espalhamento direcional D(ω, θ), e as escolhas das duas são independentes entre si
  • Para o espectro não direcional, é usado o espectro Texel-Marsen-Arsloe (TMA) descrito por Horvath
    • O TMA usa velocidade do vento U, profundidade da água D e fetch length F
    • O TMA combina o espectro JONSWAP com uma função de atenuação pela profundidade
  • Para a função de espalhamento direcional, é usada uma mistura entre os espalhamentos direcionais flat e Hasselmann de Horvath, controlada pelo parâmetro spread μ
    • Também inclui o parâmetro swell ξ proposto por Horvath para modelar o alongamento das ondas oceânicas
    • O espalhamento direcional de Hasselmann foi escolhido por oferecer uma solução analítica aproximada para o coeficiente de normalização Q(σ)
  • Seguindo a proposta de Tessendorf, a função espectral resultante também é multiplicada por um termo de supressão de ondas pequenas
    • Esse termo usa a magnitude do vetor de número de onda k e o parâmetro detail δ
  • O espectro direcional final combina TMA, espalhamento direcional misto e supressão de ondas pequenas

Implementação de FFT na GPU

  • A FFT usa uma implementação customizada na GPU escrita com compute shaders
  • Em vez de Cooley-Tukey, o algoritmo usado é o Stockham FFT, evitando a permutação inicial de bit-reversal
  • Seguindo Flügge, é calculada uma textura "butterfly" que codifica o fluxo de dados da FFT
    • Essa textura é calculada apenas uma vez sempre que a resolução da textura espectral muda
  • A FFT 2D primeiro aplica o kernel FFT nas linhas da textura espectral
  • Depois, um compute shader transpõe a textura para reutilizar o mesmo kernel FFT de linha como se fosse um FFT de coluna
  • A transposição não só permite reutilizar o pipeline como também melhora o padrão de acesso à memória

Wave cascades e mitigação de tiling

  • À distância, especialmente quando há sea foam, os artefatos de tiling ficam muito evidentes
  • O sistema de geração de ondas lida com isso permitindo sobrepor várias wave cascades ao mesmo tempo
  • Cada cascade tem seu próprio tamanho de tiling e conjunto de parâmetros
  • As cascades podem ser adicionadas e removidas dinamicamente em tempo real
  • Como todas as cascades usam o mesmo compute pipeline, elas precisam ter a mesma resolução de textura espectral
  • Como alternativa, também seria possível reduzir artefatos de tiling misturando deslocamento e normais das ondas com ruído, com custo de desempenho menor
  • Para evitar interferência entre ondas ao sobrepor cascades, é preciso escolher com cuidado os parâmetros e o tamanho de cada uma
  • As fases das ondas de cada cascade também devem ser deslocadas para não interferirem entre si
    • O sistema tenta fazer isso automaticamente aplicando offsets diferentes ao tempo inicial de cada cascade
    • Há a ressalva de que não é certo se isso funciona de fato

Distribuição da carga de atualização

  • Como o movimento das ondas é irregular, o deslocamento pode parecer perceptualmente suave mesmo sem ser atualizado a cada frame
  • O parâmetro "update rate" controla com que frequência por segundo cada wave cascade será atualizada
  • Pular frames reduz o tempo de GPU gasto com FFT, mas ainda pode haver stutter nos frames em que o pipeline de geração das ondas é executado
  • Experimentos com cálculo assíncrono das atualizações de cascade usando o RenderingDevice local do Godot geraram grande overhead de desempenho por causa da transferência de texturas entre CPU e GPU
  • Em vez disso, o sistema tenta distribuir a carga entre cascades
    • Se o frame time for menor que a update rate, apenas uma cascade é atualizada por frame
    • Isso reduz o stutter e ao mesmo tempo preserva a vantagem de menor carga de GPU obtida ao pular frames

Materiais de referência

1 comentários

 
GN⁺ 2024-09-29
Comentários no Hacker News
  • Dois outros repositórios Godot criados por essa pessoa também são muito interessantes. Gosto do nível de detalhe que ela coloca ao descrever os repositórios, e este em particular chama a atenção: https://github.com/2Retr0/GodotGaussianSplatting
    Fico curioso se é estudante. Cita com frequência trabalhos de outras pessoas e parece entender muito bem materiais publicados recentemente

    • Parece bem possível que seja estudante. O título e a descrição de um dos repositórios são ENGR96A-coursework, Relevant coursework for ENGR 96A Introduction to Engineering Design F23, e, pelas datas dos commits, F23 parece significar o semestre de outono de 2023
      Claro, pode ser que as disciplinas da UCLA mencionadas no repositório estejam abertas ao público em geral, então talvez não seja necessário estar matriculado na UCLA no sentido tradicional para acompanhá-las
  • Há 20 anos, acho que poderíamos passar meses ajustando a superfície do mar em uma renderização e ainda assim não chegar perto desse nível. É um resultado muito bem feito
    Dito isso, o vídeo de demonstração parece um pouco exagerado. Como alguém com mais de 50 mil milhas náuticas de navegação em mar aberto registradas no diário de bordo, se as ondas fossem tão pontiagudas e altas assim, o vento teria que estar soprando muito mais forte. Ainda assim, parece algo que se resolve ajustando os parâmetros
    Se foi feito em Godot, dá para considerar renderização em tempo real? Também fico curioso se exige uma GPU monstruosa

    • Não é uma crítica, só uma observação: isso se parece com o que eu imaginaria para um mar de xarope de milho quente tingido de azul. A viscosidade parece certa, mas a tensão superficial pode ser diferente da água do mar real. A água do mar real é uma solução salina de H2O com material biológico em forma de coloide; é comum no mundo real, mas é um objeto bem bagunçado para dinâmica de fluidos computacional
      Além disso, aqui a espuma/borrifo do mar parece um efeito de pós-processamento, enquanto no mar real o spray suaviza a nitidez das ondas, algo que também aparece visualmente de forma sutil
      Claro, este modelo elegante, simples e eficaz quase não tem física, então espero que isso seja visto menos como uma crítica de braços cruzados e mais como sugestões de direções para cutucar e experimentar
    • Hoje em dia há muitos vídeos tratando disso, então o processo todo ficou relativamente acessível, mas ainda há muitas armadilhas
      Um dos meus vídeos favoritos sobre o tema: https://m.youtube.com/watch?v=yPfagLeUa7k
      Este também é bom: https://m.youtube.com/watch?v=kGEqaX4Y4bQ
    • Tenho um projeto de jogo e, sempre que vejo uma tecnologia de games legal, acabo sendo nerd-sniped e querendo implementá-la eu mesmo. Se eu tivesse usado ou comprado assets existentes, o progresso que tenho até agora provavelmente caberia em uma game jam de 48 horas
      Em vez disso, passo fins de semana mexendo em shader de água até chegar ao visual que quero. Só que meu jogo é de puzzle, então ele nem precisa de água. Agora só tenho uma tela inicial bonita
    • Quando me formei, fazer coisas como motor de partículas e marching cubes era projeto de conclusão de curso
      Hoje isso é só uma caixa de seleção em um motor de jogo, junto com incontáveis outros recursos. As pessoas não conseguem imaginar direito como o ambiente ficou bom graças aos motores modernos
      Não quero diminuir o valor deste trabalho; é uma realização excelente e dou os parabéns ao autor. Só queria dizer que vivemos em uma época muito boa
    • Concordo que, só pelo vídeo, parece um pouco aleatório
      Mesmo assim, está muito bom e, dentro do que pesquisei rapidamente recentemente, talvez esteja entre o melhor do que é possível
      Pessoalmente, eu gostaria de ver ondas de mar aberto geralmente com mais ritmo. Fico curioso se uma simulação de vento de 15 nós soprando por algumas horas sobre 1 km de superfície da água corresponderia ao que se observa na prática: arrebentações relativamente organizadas se formando e depois se dispersando
  • Coisas assim foram o que me atraíram para o mundo da computação, mas, em algum momento, caí na vida fácil e entediante de costurar bibliotecas, endpoints e besteira corporativa, o que está levando ao burnout
    Espero um dia conseguir voltar

    • Acho que dá para ir migrando aos poucos. Encontre uma área que despertou seu interesse no começo, sobre a qual você quer aprender mais e eventualmente fazer algo, mergulhe nela algumas horas por semana e vá aumentando gradualmente, enquanto se afasta do trabalho atual
      Espero que tente. Todo mundo está torcendo por você
    • Vejo muitos amigos ganhando mais dinheiro do que eu fazendo esse tipo de trabalho, mas segui meus interesses e, na primeira oportunidade, fui para robótica, e não me arrependo. Pelo menos para mim, nada se compara a ver meu código interagindo com o mundo real
  • A abordagem é diferente, mas, se você se interessa por simulação de ondas/oceano, o Acerola publicou um vídeo excelente sobre esse tema, como sempre. https://youtu.be/PH9q0HNBjT4 e https://youtu.be/yPfagLeUa7k
    Edit: um deles já estava linkado nas referências, mas estava com o nome real em vez do apelido, então só percebi agora

  • É interessante como esse problema é difícil. Há décadas tentamos resolvê-lo e ainda ficamos no vale da estranheza
    Se você pausar essa cena, as ondas levantadas parecem montanhas cobertas de neve. Para a água assumir formas tão pontiagudas, o vento teria que ser bem forte, mas o vento não sopraria diretamente para cima, então soa irreal. Essas características pontiagudas deveriam ter direcionalidade
    Ainda assim, capturou bem as propriedades das ondas de swell. O movimento vertical é maior que o deslocamento horizontal, que é o que se esperaria em mar aberto

    • Joguei Nightingale, e a água do mar lá é realmente especial. Para ser claro, eles mantêm as ondas calmas, então não precisam lidar com problemas como spray, e parecem ter conseguido se concentrar em outros aspectos
      Não sei como simulam a transmissão da luz, mas funciona bem. A luz atravessando as ondas ao nascer ou pôr do sol é excelente e torna o efeito realmente convincente
      Pode-se dizer que é um pouco pictórico, mas não parece errado
  • Morei alguns anos na praia. Quando você mora na praia, o mar é fascinante e agradável aos sentidos, então acaba olhando para ele por horas. Ao ver isso, acho que em nenhum momento eu teria pensado que era uma renderização

    • Moro na praia atualmente e também tenho uma vista a cerca de 14 andares acima da superfície da água; estranhamente, para mim é claramente falso. Não há manchas escuras causadas por rajadas de vento, e as partes brancas sobem diretamente para cima sem enrolar nem um pouco. Fora isso, parece bem real
    • Você já viu ondas reais e o movimento delas? Se morou anos na praia, perceberia imediatamente que a formação de espuma e o movimento das ondas não são naturais
  • Também há um bom exemplo no Shadertoy: https://www.shadertoy.com/view/Ms2SD1

  • Fourier teve a ideia da transformação de frequências de ondas enquanto media ondas de maré, então, de certa forma, isso quase fecha o ciclo
    Muito impressionante

  • Excelente, mas essa abordagem provavelmente quebra em certa medida em ondas realmente grandes por causa da não linearidade. Ondulações não são senoides, mas, para ondas pequenas e médias, são parecidas o suficiente para esse método funcionar muito bem
    Ondas muito grandes não só se afastam muito mais de senoides, como também começam a interagir entre si de forma não linear, algo que a superposição linear usada aqui não consegue capturar
    Portanto, para a maioria dos estados do mar, é fantástico. Mas, se você quiser criar ondas realistas no estilo de “Tempestade Perfeita”, precisará de outra abordagem

  • Muito impressionante e melhor do que qualquer coisa que vi até agora, mas o swell parece um pouco estranho. Se eu tivesse que explicar, diria que ondas de alta frequência não se deslocam sobre ondas de baixa frequência como no vídeo