O artigo é principalmente sobre shaders GLSL, e como eu os usei neste mini-demo game.
O artigo está dividido na seguinte ordem:
- Links e uma breve descrição.
- Uma descrição muito breve da lógica do jogo e recursos usados de Godot.
- Sobre os shaders usados.
- Um pouco mais sobre Godot e suas características.
- O WebGL2 funciona
- Multijogador
1. Links e descrição
Você pode baixar a versão Win / Linux no link para itch.io
O código fonte do jogo inteiro está disponível no github ou no gitlab .
Jogabilidade:
Mínimo, este não é um jogo completo. (nenhum som no jogo)
O objetivo do jogo é manter o número máximo de rodadas. Os rounds começam quando as esferas da HP são zero e não há robôs no jogo.
Quando as peças são destruídas, os bônus aparecem, uma vez por rodada , fornecem a velocidade da animação do tiro, o dano (apenas na esfera principal) e a altura do salto, na cor azul, vermelho / verde e amarelo. Bots também dão um bônus, mas aleatoriamente. O personagem do jogador restaura + 1HP a cada nova rodada.
2. A lógica do jogo e os recursos utilizados
Recursos utilizados:
O Blender foi usado apenas para reduzir o número de polígonos nos modelos e criar peças quebradas.
O módulo futari-addon é usado . (Vou escrever sobre isso abaixo)
No jogo, dois modelos têm animações.
Movimentos de personagem de jogador que fiz em Godot, o modelo original
O segundo modelo é o sphere-bot, que possui animações de alta qualidade.
Todos os modelos de objetos prontos para uso usados estão listados aqui .
Lógica do jogo e recursos Godot:
A lógica do jogo não é feita da melhor maneira, vou listar os pontos que são feitos normalmente.
Somente uma Viewport é usada para uma cena 3D e várias Viewports (baixa resolução) nas quais existem câmeras ortogonais para 2D Viewports (também baixa resolução) nas quais os shaders Multipass / Feedback são processados, mais sobre eles abaixo.
Todas as texturas têm mipmap e até funcionam no navegador. Existem configurações gráficas adicionais (Esc - Configurações) . Por exemplo, você pode fazer qualquer resolução para o jogo , até 32x32
pixels. Por exemplo, defino a resolução 320x240
nas configurações, executando o jogo em um navegador e ativei o máximo de MSAA com anti-aliasing. 
Todas as fontes de luz funcionam em tempo real , são 16 no total.
O piso e a cerca são as partículas mais simples que duplicam o mesmo modelo muitas vezes; o código é trivial .
A matriz de rotação de partículas (pedaços de piso) nos meus shaders é apenas uma pequena entrada desta fórmula:
mat4 rotationAxisAngle( vec3 v, float angle ) { float s = sin( angle ); float c = cos( angle ); float ic = 1.0 - c; return mat4( vx*vx*ic + c, vy*vx*ic - s*vz, vz*vx*ic + s*vy, 0.0, vx*vy*ic + s*vz, vy*vy*ic + c, vz*vy*ic - s*vx, 0.0, vx*vz*ic - s*vy, vy*vz*ic + s*vx, vz*vz*ic + c, 0.0, 0.0, 0.0, 0.0, 1.0 ); }
por exemplo, v=vec3(0.0,0.0,1.0)
é a rotação ao longo do eixo z
e angle=PI/2.
substitua-os e obtenha o turno desejado.
A animação de blocos destrutíveis é considerada um mecanismo de física em tempo real
A física em Godot é bastante limitada e começa a reduzir significativamente o FPS mesmo com uma dúzia de objetos ativos; portanto, todas as colisões entre peças destruídas são desativadas e outras são definidas, os níveis de física são definidos, também há um limite no número de destruição simultânea e o número máximo de bots ao mesmo tempo (seis).
A física da inércia e a interação do personagem do jogador com objetos dinâmicos. É desativado por padrão em Godot, escrevi uma interação mínima, o código nos arquivos:
A função bot_hit.gd _integrate_forces e tudo o que se chama são movimentos adversos -bot
player_l.gd primeiro, a função move_and_slide
desativa a inércia infinita e a função process_collision
repele objetos.
O pré-carregamento (pré-carregamento) no início do jogo é usado para evitar atrasos quando o objeto é exibido pela primeira vez; isso ajuda no entanto, quando você ativa as Sombras (e algumas outras opções), os atrasos aparecerão novamente na primeira aparição do objeto. Também no navegador, isso não ajuda devido às peculiaridades dos navegadores que trabalham com shaders.
Vários objetos duplicados em um e vários GIProbe, todos os formatos e parâmetros das fontes de luz são projetados , feitos para contornar as limitações do OpenGL ou as restrições do Godot.
3. Shaders usados
Panorama do ambiente:
Este jogo usa um panorama estático, a imagem é obtida a partir deste sombreador (cores c1 c2, posição ldir)
vec3 sky(vec3 d, vec3 c1, vec3 c2) { vec3 ldir = normalize(vec3(0.,0.,-1.)); vec3 col = mix(c1*100., c2*100., min(abs(dy)*2. + .5, 1.)) / 255.*.5; col *= (1. + vec3(1., .7, .3) / sqrt(length(d - ldir))*2.); //sun return clamp(col,vec3(0.),vec3(1.)); }
para obter um panorama, remova o comentário da linha 57 panorama_uv(fragCoord,ro,rd);
e colocar um comentário na linha 58
Panoramas dinâmicos para Godot em demonstrações anteriores (YouTube e há links para o código) panorama de nuvens .
E o panorama do ciclo dia / noite com o movimento das nuvens foi usado nesta demonstração:
outro panorama dia / noite, por exemplo, no shadertoy eu não o usei em nenhum lugar
Se você precisar converter o CubeMap em um panorama do ambiente para Godot , criei um simples conversor da web .
Shaders muito simples:
Os shaders de partículas determinam estaticamente sua posição para animação ou não. Por exemplo spawn.shader)
Para um brilho adicional ao redor dos objetos , não apenas das bolas, esta é uma linha do gglow.shader (os números podem ser alterados conforme necessário)
float intensity = pow(0.122 + max(dot(NORMAL, normalize(VIEW)),0.), 010.85);

Exibindo dígitos de texto em 3D , como eu o entendo em Godot, não há meios para isso (sem criar um FBO (viewport) adicional); portanto, um simples sombreador imprime números a partir de uma textura (para que seja mipmapping ), o código do sombreador
Elementos da interface do usuário:
Tornar o formulário personalizado dos painéis da interface do usuário o mais fácil para mim é em shaders, talvez isso não esteja certo . O método correto é mostrado aqui como um exemplo (na seção UI).
Neste jogo, a animação de fundo do menu mais simples e o indicador HP . Acima, no link para o vídeo do panorama dia / noite, também é feito, existem faixas nas laterais e toda a animação no shader.
Sobre o módulo futari-addon:
Funciona quase da mesma forma que esse sombreador para partículas 2D em vídeo (veja 1:41).
Um mapa 2D-SDF de todos os polígonos é construído no vídeo uma vez no início e a textura resultante é simplesmente enviada para as partículas, as próprias partículas se normalizam na posição atual e alteram o movimento.
O futari-addon faz quase a mesma coisa; somente em vez de um mapa de textura 2D, são transmitidas as coordenadas das esferas e dos planos 3D que são processados por condição no sombreador de partículas, para que você possa alterar livremente sua posição e outros parâmetros.
Além disso, o vento (no meu exemplo 2D, adicionar vento é muito simples, como outra textura com valores + - à velocidade, e as partículas simplesmente adicionam o valor da velocidade deste mapa em sua posição).
O módulo futari-addon é muito bom , usou-o em vez de criar seu próprio sistema de partículas.
Efeito de escudo:
Partículas para as quais as coordenadas do impacto na esfera e a posição do jogador são transmitidas e desaparecendo usando o buffer de feedback de transformação . Código de sombreador no arquivo en_m.shader
Bots Shield:

Shader como um ruído tridimensional sheild.shader essencialmente tudo funciona graças à função de flow
original aqui
O plano de fundo é determinado por gl_FrontFacing
e é pintado mais escuro e mais verde, e não azul.
Resposta a um soco - o temporizador de eventos de choque é simplesmente transmitido.
Shaders lendo seu último quadro ou Feedback / Multipass shaders:
Quase todos os efeitos são feitos usando essa lógica.
Um dos shaders do jogo .
Como fonte, configurei uma câmera ortogonal que fotografa objetos em um determinado grupo a uma curta distância (sem processar a cena inteira)
.
Efeito do campo de gelo:
O sombreador está indicado acima, no arquivo do projeto é ice_feedback.shader e um sombreador de fragmento para o plano que cria a ilusão de profundidade do piso usando um loop simples de profundidade:
while(current_depth < depth){ ofs -= delta; depth = textureLod(texture_depth, ofs,0.0).r; current_depth += layer_depth; }
Efeito de campo de partículas:
O sombreador é o mesmo , a coordenada y
(altura) das partículas de acordo com o brilho da cor do buffer de quadro do sombreador, a cor também de acordo com o brilho da cor ( não floor/visible_/floor3/grass/grass
o sombreador de partículas separadamente, ele está no projeto no objeto floor/visible_/floor3/grass/grass
).
Animação dinâmica de sinalizador:
Godot tem o SoftBody para animar o tecido, mas é uma CPU, então eu não o usei. Usei um link de código pronto para o original . Essa bandeira é empurrada de três bolas ao lado e a cabeça do personagem é a quarta bola.
A lógica do sombreador de várias passagens , como no exemplo acima, com apenas três eixos, o código de várias passagens do sombreador (1) flag.shader , o sombreador que desenha o flag mostra apenas a textura e altera a geometria do avião (2) flag.shader .
Aparência das figuras:
As formas não têm UV, portanto, mapeamento de textura triplanar para mapeamento de textura e triangling ( vértice ), todos os códigos no cchess.shader
Animação de um hitbox (quadro vermelho) que causa danos ao personagem do jogador e um traço do quadro (as partículas são óbvias):
Ele usa apenas o shader já especificado gglow.shader .
PS Criou a mesma animação em um shader , link para shadertoy
Para partículas, apenas duas texturas são usadas, um círculo e um quadrado.
4. Sobre Godot, e suas características
Godot é muito bom e simples (não para iniciantes). Eu realmente gostei de Godot por suas características.
Existem muitos bugs, a documentação do Godot é incompleta e, às vezes, enganosa devido a erros e não indica pontos críticos (o que não é óbvio para mim), a fim de entender qual código-fonte do Godot teve que ser relido várias vezes (o código não é grande e bem escrito).
Esta é apenas a minha impressão, pode ser errado, não quero enganar ninguém.
Enfatizo que mesmo erros muito críticos em Godot podem ser contornados em Godot por meio do GDScript, com o mínimo esforço. O que é sem dúvida uma grande vantagem
Também observo que Godot não está de maneira alguma protegido das peculiaridades de fatores externos, como WASM em navegadores, restrições ANGLE, fortes limitações dos próprios navegadores e, é claro, dezenas de bugs nos drivers da placa de vídeo, tudo isso deve ser contornado manualmente.
Lags - há um grande problema com a gerência, é 100% do lado Godot, eu não consertei. (cunhas de controle durante a compilação de shaders e atrasos de FPS (por exemplo, no navegador)), também outros atrasos relacionados aos recursos de renderização em 3D no Godot, fiz um desvio de alguns deles, mas eles ainda existem / podem ser.
5. O WebGL2 funciona Apenas Linux
Não inicie o jogo pelo link se você tiver o Windows. Link para a versão WebGL2 / WASM.
Atualização de informações : a versão WebGL foi lançada no Windows10 (apenas no Firefox, com o ANGLE desativado) em um PC super poderoso (vídeo i9 / 16gb ram / 8gb), embora o piso não tenha mais renderizado (por algum motivo) e o firefox esteja com memória perdida (> 16 GB ) em cinco minutos ... é melhor não correr, por seu próprio risco e risco
Funciona apenas no Chrome 76+ e Firefox (Linux).
Um relatório de bug (link) foi enviado sobre o Windows; se esse é um bug do navegador, o Google reage após 2 meses. Mas, aparentemente, isso é um bug no ANGLE, e isso é quase certo.
O relatório de erros já está fechado e ANGLE também não será editado. Portanto, no Windows, o navegador não funcionará.
No decorrer deste projeto, um bug no Chrome foi corrigido devido ao qual o feedback de transformação e minha última demonstração (acima do vídeo com um panorama dia / noite) , que não funcionava antes, começaram a funcionar.
6. Multiplayer
Adicionado multiplayer, exclusivamente para fins de teste (e amostra de multiplayer em Godot). Código-fonte e versões binárias próximas à versão principal no github e itch (links no início).
Quando o Godot 3.2 for lançado, adicionarei o WebRTC para o teste também.