Como animar a textura 2d de cima para baixo da água abstrata?

24

Atualmente, implemento um jogo com uma vista de cima para baixo do oceano. Eu uso o seguinte, um pouco de textura abstrata:insira a descrição da imagem aqui

A textura real é transparente, eu adicionei a cor verde para maior clareza.

O problema que tenho agora é que não sei como animar essa textura para que a água pareça agradável. Tentei mover a textura com uma onda pecado texture.y += sin(angle). Claro que agora toda a textura está se movendo, o que parece meio irreal. A próxima coisa que tentei é adicionar outra camada e implementar um efeito de paralaxe. Para que as reflexões sob a superfície da água também se movessem, mas muito mais lentamente. Parece um pouco melhor, mas ainda não ... bom o suficiente.

Eu acho que a melhor animação seria, se as células individuais se expandissem e se contraíssem, como uma teia ou pedaço de pano. Imagine se alguém puxasse um pouco o vértice dessas células e a célula vizinha se expandisse e a célula para a qual eu puxo (ou pressiono) contrai. Como uma teia de molas (?). Mas não tenho idéia de como implementar algo assim:

  • Qual é o modelo matemático para isso? Algo com molas, onde as forças empurram / puxam?
  • E se sim, como mapeio esse modelo para a textura fornecida? Mantendo todas as curvas e o que não ...

(Também estou aberto a diferentes idéias / respostas sobre como animar a textura fornecida. Realismo não é o ponto aqui, apenas um pouco de água bonita como movimentos ...)

Solução de DMGregory

Publiquei um exemplo da libgdx neste post: a animação em 2D em água é irregular e não é suave (consulte a resposta sobre filtragem de textura)

morpheus05
fonte

Respostas:

41

Uma maneira comum de fazer isso é usar uma pesquisa indireta de textura no sombreador para distorcer a textura da exibição:

Gif animado mostrando animação aquática

Aqui, estou usando uma textura com algum ruído colorido de baixa frequência (lado a lado com blobs suaves de cores aleatórias) e rolando-a pela geometria da tela ao longo do tempo.

insira a descrição da imagem aqui

Em vez de desenhar as cores dessa textura, pego os canais vermelho e verde e subtraio 0.5fpara transformá-los em um vetor 2D pseudo-aleatório que muda suavemente ao longo do tempo e do espaço.

Em seguida, posso adicionar um pequeno múltiplo desse vetor às minhas coordenadas UV, antes de coletar amostras da textura principal da água. Isso muda a parte da textura que estamos lendo e exibindo, distorcendo-a.

Ao calcular a média de duas amostras desse ruído, rolando em direções opostas, podemos ocultar a direção do movimento, para que pareça um sloshing sem objetivo.

No Unity, o shader ficaria assim: deve ser simples o suficiente para traduzir para o idioma do shader de sua escolha:

fixed4 frag (v2f i) : SV_Target
{               
    float2 waveUV = i.uv * _NoiseScale;
    float2 travel = _NoiseScrollVelocity * _Time.x;

    float2 uv = i.uv;
    uv += _Distortion * (tex2D(_Noise, waveUV + travel).rg - 0.5f);
    waveUV += 0.2f; // Force an offset between the two samples.
    uv += _Distortion * (tex2D(_Noise, waveUV - travel).rg - 0.5f);

    // Sample the main texture from the distorted UV coordinates.
    fixed4 col = tex2D(_MainTex, uv);

    return col;
}
DMGregory
fonte
11
Isso parece muito bom. Não sei se entendi todos os atributos: _NoseScale = escalar para dimensionar o "mapa de ruído". _NoiseScrollVelocity = Vector2 a que velocidade nos movemos pelo mapa de ruído. _Ruído =?. _Distortion = Scalar Eu escolho como fator de distorção? v2f = Vertex, determinamos a cor. i =?
precisa saber é o seguinte
_Noiseé [um amostrador de texturas que lê] a pequena textura aleatória acima. v2f isão os dados interpolados do shader de vértice - usamos principalmente para obter as coordenadas de textura do pixel que estamos desenhando i.uv. E você está exatamente correto sobre todo o resto.
DMGregory
Eu implementei o shader e de alguma forma ele não funciona (não se move ou a distorção é grande), presumo que não definai os valores corretamente. time = a diferença do último quadro em ms. noise_scale = 1 (eu uso a sua textura, envoltório modo de repetição) noise_scroll_velocity = [0,01, 0,01] distorção = 0,02
morpheus05
Observe que a variável é chamada Time, não DeltaTime. Se você usar uma diferença de tempo e a taxa de quadros for consistente, sempre obterá o mesmo número e voltará a executar o shader com as mesmas entradas, obtendo a mesma saída (nada se move). Pior ainda, se sua taxa de quadros for inconsistente, você receberá vibrações. Você quer o tempo total decorrido, não o tempo delta.
DMGregory
Logo que clico em enviar, percebi isso e agora quase funciona. A animação parece produzir ondas do canto inferior direito e, depois de 10 ou mais segundos, ela desaparece, como ondas que param. Qual poderia ser a razão disso?
precisa saber é o seguinte
6

Isso é chamado de efeito cáustico, e a geração desses efeitos em tempo de execução consome bastante tempo; portanto, isso é tradicionalmente feito com animação quadro a quadro pré-renderizada. Existem ferramentas que irão gerar quadros de animação cáustica para você, como o Caustics Generator , que possui uma versão gratuita para uso não comercial. Existem também alguns pré-fabricados que você pode comprar por um preço significativamente mais barato que a versão pro da ferramenta que mencionei.

Observe que os efeitos cáusticos também costumam ser aplicados como um biscoito leve em um terreno subaquático ou na superfície subaquática. Ou seja, colocá-lo na superfície da água enquanto olha para ela normalmente não é o que parece com a água.

Ed Marty
fonte
Isso é muito interessante, vou também ter um olhar para este gerador (evento, porém, vou tentar a variante shader se eu entendi ...)
morpheus05
4

Parece uma textura que você pode gerar a partir de um gráfico voronoi, por exemplo:

insira a descrição da imagem aqui

Você pode fazer pequenos ajustes suaves no gráfico movendo os pontos; redesenhar o gráfico de cada quadro seria muito caro, então você provavelmente desejaria pré-renderizar a animação.

FacticiusVir
fonte
4
Na verdade, eu processei cáusticos dessa maneira em um shader no passado. Não é necessariamente tão caro quanto você imagina ( aqui está um exemplo de renderização de bordas de Voronoi em tempo real em um sombreador WebGL ), embora obter a forma suave correta nas bordas - em vez de polígonos pontiagudos - possa ser desafiador.
DMGregory
Ooo, isso é muito legal; Eu tenho alguns geradores de terreno para os quais isso seria muito útil.
FacticiusVir
0

Existe um método oldschool, envolvendo uma camada de textura inferior e duas texturas semitransparentes para reflexão no topo.

Se você deseja percorrer todo o caminho e deseja que a água não pareça cheia de ondas clonadas ou samish blue-flowmaps, é o objetivo.

https://steamcdn-a.akamaihd.net/apps/valve/2010/siggraph2010_vlachos_waterflow.pdf

Pica
fonte
3
Embora os links possam ajudar, eles nunca dão boas respostas. Você poderia expandir os dois métodos de teses? Como seria a implementação?
Vaillancourt
O primeiro método é basicamente um método muito antigo usado para animar a água - você usa uma textura de água da camada base cujas coordenadas UVW são deslocadas na direção de sua escolha. Agora você aplica um mapa / bump-map normal, que muda para outra direção - se bem feito, isso parece convincente para pequenos rios. É muito limitado, porém, para grandes massas de água, pois qualquer coisa que se assemelhe a ondas terá efeito ondulado. O link explica o uso de mapas de fluxo muito melhores que eu.
Pica
Por favor, use o recurso de edição para melhorar a pergunta com o que você adicionou aqui :) As pessoas são usadas para procurar respostas na postagem, não nos comentários.
Vaillancourt