Attention: Here be dragons
This is the latest
(unstable) version of this documentation, which may document features
not available in or compatible with released stable versions of Godot.
Checking the stable version of the documentation...
Otimizando o desempenho 3D
Culling (recorte)
A Godot executará automaticamente o frustum culling (corte do frusto de visão) para evitar a renderização de objetos que estão fora da viewport. Isso funciona bem para jogos que ocorrem em uma área pequena, no entanto, as coisas podem rapidamente se tornar problemáticas em níveis maiores.
Descarte por oclusão
Caminhando por uma cidade, por exemplo, você pode ser capaz de ver apenas alguns edifícios na rua em que está, bem como o céu e alguns pássaros voando acima. No que diz respeito a um renderizador ingênuo, no entanto, você ainda pode ver a cidade inteira. Ele não renderizará apenas os edifícios à sua frente, ele renderizará a rua atrás deles, com as pessoas naquela rua, e os edifícios atrás disso. Você rapidamente acaba em situações onde está tentando renderizar 10× ou 100× mais do que o visível.
As coisas não são tão ruins quanto parecem, porque o Z-buffer geralmente permite que a GPU sombreie completamente apenas os objetos que estão na frente. Isso é chamado de pré-passagem de profundidade (depth prepass) e vem ativado por padrão no Godot ao usar os métodos de renderização Forward+ ou Compatibility. No entanto, objetos desnecessários ainda estão reduzindo a performance.
Uma maneira de reduzirmos potencialmente a quantidade a ser renderizada é aproveitar a oclusão. O Godot oferece uma abordagem para oclusão (occlusion culling) usando nós oclusores. Veja Descarte por oclusão para instruções sobre como configurar oclusão em sua cena.
Nota
Em alguns casos, você pode ter que adaptar o design do seu nível para adicionar mais oportunidades de oclusão. Por exemplo, você pode ter que adicionar mais paredes para evitar que o jogador veja muito longe, o que diminuiria a performance devido às oportunidades perdidas para o descarte por oclusão.
Objetos transparentes
O Godot classifica objetos por Material e Shader para melhorar o desempenho. Isso, entretanto, não pode ser feito com objetos transparentes. Objetos transparentes são renderizados de trás para frente para fazer com que a mistura com o que está atrás funcione. Como resultado, tente usar o menor número possível de objetos transparentes. Se um objeto tiver uma pequena seção com transparência, tente tornar essa seção uma superfície separada com seu próprio material.
Para mais, veja o documento Otimizações de GPU doc.
Nível de detalhe (LOD)
Em algumas situações, particularmente à distância, pode ser uma boa ideia substituir geometrias complexas por versões mais simples. O usuário final provavelmente não conseguirá notar muita diferença. Considere olhar para um grande número de árvores na distância remota. Existem várias estratégias para substituir modelos em distâncias variadas. Você poderia usar modelos com menos polígonos (low poly), ou usar transparência para simular geometrias mais complexas.
O Godot 4 oferece várias maneiras de controlar o nível de detalhe:
Uma abordagem automática na importação da malha usando Nível de detalhe de malha (LOD).
Uma abordagem manual configurada no nó 3D usando Faixas de visibilidade (HLOD).
Decals e luzes também podem se beneficiar do nível de detalhe usando suas respectivas propriedades de Distance Fade (Esmaecimento por Distância).
Embora possam ser usados de forma independente, essas abordagens são mais eficazes quando usadas juntas. Por exemplo, você pode definir faixas de visibilidade para ocultar efeitos de partículas que estão muito longe do jogador para serem notados. Ao mesmo tempo, você pode confiar no LOD de malha (mesh LOD) para fazer com que as malhas do efeito de partícula sejam renderizadas com menos detalhes à distância.
Os intervalos de visibilidade também são uma boa maneira de configurar impostores para geometrias distantes (veja abaixo).
Billboards e impostores
A versão mais simples de usar transparência para lidar com LOD são os billboards (quads sempre virados para a câmera). Por exemplo, você pode usar um único quad transparente para representar uma árvore à distância. Isso pode ser muito barato de renderizar, a menos que, é claro, existam muitas árvores uma na frente da outra. Nesse caso, a transparência pode começar a afetar a taxa de preenchimento (fill rate) (para mais informações sobre taxa de preenchimento, veja Otimização da GPU).
Uma alternativa é renderizar não apenas uma árvore, mas um número de árvores juntas como um grupo. Isso pode ser especialmente eficaz se você consegue ver uma área, mas não pode se aproximar fisicamente dela em um jogo.
Você pode criar impostores pré-renderizando visões de um objeto em ângulos diferentes. Ou você pode até ir um passo além e, periodicamente, re-renderizar a visão de um objeto em uma textura para ser usada como um impostor. À distância, você precisa mover o observador por uma distância considerável para que o ângulo de visão mude significativamente. Isso pode ser complexo de fazer funcionar, mas pode valer a pena dependendo do tipo de projeto que você está fazendo.
Use instanciação automática
Isso só está implementado no renderizador Forward+, não nos modos Mobile ou Compatibility.
Se você tiver muitos objetos idênticos em sua cena, você pode usar o instanciamento automático para reduzir o número de chamadas de desenho (draw calls). Isso acontece automaticamente para nós MeshInstance3D que usam a mesma malha e material: nenhuma configuração manual é necessária.
Para que a instanciação automática seja eficaz, o material deve ser opaco ou testado por alfa (alpha scissor ou alpha hash). Materiais com mistura alfa (alpha-blended) ou pré-passagem de profundidade nunca são instanciados dessa forma. Em vez disso, você deve usar MultiMesh conforme descrito abaixo.
Use instanciação manual (MultiMesh)
Se vários objetos idênticos precisam ser desenhados no mesmo lugar ou próximos, tente usar MultiMesh. O MultiMesh permite o desenho de muitos milhares de objetos com muito pouco custo de performance, tornando-o ideal para bandos, grama, partículas e qualquer outra coisa onde você tenha milhares de objetos idênticos.
Veja também a documentação Usando MultiMesh.
Asse a iluminação
Iluminar objetos é uma das operações de renderização mais dispendiosas. Iluminação em tempo real, sombras (especialmente múltiplas luzes) e iluminação global são especialmente caras. Elas podem simplesmente ser demais para dispositivos móveis de menor potência suportarem.
Considere usar iluminação assada (baked lighting), especialmente para mobile. Isso pode parecer fantástico, mas tem a desvantagem de que não será dinâmico. Às vezes, essa é uma compensação que vale a pena fazer.
Veja Usando a iluminação global Lightmap para instruções sobre como usar lightmaps (mapas de luz) assados. Para obter o melhor desempenho, você deve definir o modo de cozimento (bake mode) das luzes como Static (Estático) em vez do padrão Dynamic (Dinâmico), pois isso ignorará a iluminação em tempo real em malhas que possuem iluminação assada.
A desvantagem das luzes com o modo de assamento Static é que elas não podem projetar sombras em malhas com iluminação assada. Isso pode fazer com que cenas com ambientes externos e objetos dinâmicos pareçam planas. Um bom equilíbrio entre performance e qualidade é manter Dynamic para o nó DirectionalLight3D e usar Static para a maioria (se não todas) as luzes omni e spot.
Animação e skinning
Animação e animação de vértices, como skinning e morphing, podem ser muito caras em algumas plataformas. Você pode precisar reduzir consideravelmente a contagem de polígonos para modelos animados, ou limitar o número deles na tela em um determinado momento. Você também pode reduzir a taxa de animação para malhas distantes ou ocluídas, ou pausar a animação inteiramente se for improvável que o jogador note a animação sendo interrompida.
Os nós VisibleOnScreenEnabler3D e VisibleOnScreenNotifier3D podem ser úteis para esse propósito.
Mundos grandes
Se você está criando mundos grandes, existem considerações diferentes daquelas com as quais você pode estar familiarizado em jogos menores.
Mundos grandes podem precisar ser construídos em blocos (tiles) que podem ser carregados sob demanda conforme você se move pelo mundo. Isso pode evitar que o uso de memória saia do controle e também limitar o processamento necessário à área local.
There may also be rendering and physics bugs due to floating-point errors in
large worlds. This can be resolved using Coordenadas de mundo grande.
If using large world coordinates is not an option, other common techniques include
orienting the world around the player (rather than the other way
around), or shifting the origin periodically to keep things centered around
Vector3(0, 0, 0).