Como posso reduzir o impacto no desempenho da renderização de árvores?

24

Estou fazendo um tipo de jogo estilizado de baixo poli. Eu tenho um terreno com um pouco de água e quero muitas e muitas árvores; No momento, tenho 10.000 árvores em massa. Cada árvore consiste em não mais que 200 triângulos, portanto, eles não são muito exigentes.

O principal problema é que existem lagos, e os lagos são bem grandes. Você não pode ver nenhuma árvore do outro lado do lago, e isso parece muito ruim, especialmente quando você caminha por lá e as árvores aparecem de repente.

Para consertar isso, tenho que aumentar a distância das árvores para que você possa ver uma quantidade decente de árvores do outro lado do lago, mas isso reduz o desempenho a 40-50fps, e quase não há mais nada no jogo. Estou usando uma GTX 1080, se isso ajudar.

O que posso fazer para tornar meu jogo mais rápido com mais árvores?

Sr. Matt
fonte
No IIRC, Silent Hill usava neblina para ocultar o corte no plano de recorte mais distante, o que lhes permitia começar a carregar dinamicamente coisas além do local onde a neblina é cortada. Você pode se beneficiar de uma mudança na atmosfera do jogo.
Cody
As árvores estão atraindo você a olhar pela janela, diminuindo assim seu desempenho.
mbomb007
Você já tentou executar o criador de perfil? Se sim, onde está o gargalo?
Mikael Högström
Você está fazendo algum tipo de seleção de frustum?
Krythic #
O que é o descarte de frustum?
mr-mate

Respostas:

43

Há algumas coisas que você pode fazer para aumentar o desempenho do desenho.

  1. Você disse que eles estavam bem longe. Você pode usar o LOD para diminuir a contagem de vértices dessas árvores e, assim, diminuir o tempo necessário para percorrer todos os vértices que estão sendo desenhados. Embora esse provavelmente não seja o problema em questão (GTX1080 com apenas 10 mil árvores com 200 tris cada, números insignificantes para a gpu), eu ainda a incluí. O outdoor é uma ferramenta eficaz para o nível mais baixo de LOD, pois é essencialmente um plano plano sempre voltado para a câmera com uma imagem renderizada da árvore. Ele perde a sensação de profundidade, e é por isso que é bom para o nível mais baixo, pois o jogador provavelmente não notará a diferença.

  2. Você ativou o lote ? O lote dinâmico geralmente é feito automaticamente se a contagem de vértices das malhas for bastante baixa. O lote estático também pode ser tentado, tornando as árvores estáticas, marcando a caixa de seleção no editor de unidade no objeto pai do jogo. Isso não funciona bem com objetos animados. Você precisa que os objetos tenham material compartilhado para fazer isso funcionar.

  3. O lote personalizado permite controlar a renderização gerando você mesmo os blocos, em vez de permitir que a unidade lide com isso, e também permite o lote para malhas maiores. Isso é feito facilmente pelo Mesh.CombineMeshes . Isso também não funciona bem com objetos animados. Você precisa que os objetos tenham material compartilhado para fazer isso funcionar. Você provavelmente deseja dividir seu mundo em algum tipo de pedaço e criar lotes a partir deles. Como esses pedaços devem ser gerados depende realmente de como sua câmera se move no mundo.

  4. Ativar instanciamento nos shaders. A instância permite que o mecanismo desenhe vários objetos (com a mesma malha) com apenas uma chamada de desenho. Você precisa que os objetos tenham malha compartilhada e shader compartilhado para que isso funcione. O material pode variar, mas o sombreador deve suportar todas as diferentes propriedades variáveis.

    Para melhorar o mecanismo de criar lotes de renderização instanciados, você provavelmente deseja agrupar as mesmas malhas na cena. Também brincar com a fila de renderização do material fornecerá bons resultados se uma malha tiver sempre o mesmo material. Durante o desenvolvimento do jogo para celular em que estou trabalhando, usei isso para reduzir as chamadas de empate em mais da metade na minha cena de teste. Também desde o Unity 5.6, marque a Enable Instancingcaixa de seleção no material.

  5. Mantenha suas chamadas de chamada e as chamadas do SetPass em geral. Essas são as chamadas brutas para a sua GPU desenhar coisas e elas têm uma grande sobrecarga. Reduzir as chamadas de chamada (que é o que os lotes e instâncias estão fazendo) aumentará o desempenho geral que sua CPU pode oferecer, pois é necessário esperar muito menos. As chamadas SetPass são alterações nos shaders atuais; portanto, se você tiver muitos materiais diferentes, terá várias chamadas SetPass, o que também fará com que a CPU aguarde um pouco.

  6. Se a sua cena for enorme e o tempo da CPU gasto para percorrer todos os objetos da cena, tente reduzi-los. Agrupe algumas árvores em vez de colocá-las invidualmente e tenha-as como um único objeto. Verifique também se você não está movendo as árvores ou os objetos pais, pois isso faz com que o Unity descartar transformações em cache e recalcular toda a árvore da cena.

  7. Se a sua cena é enorme e o tempo da CPU ainda se concentra principalmente no Unity, percorrendo a árvore de cenas para fazer listas para renderizar todos os objetos, uma coisa que você pode fazer é não deixar o Unity lidar com a renderização. Se você tiver uma maneira melhor de rastrear objetos desenháveis, poderá usar CommandBuffer.DrawMeshInstanced ou Graphics.DrawMeshInstanced para desenhá-los manualmente. Não vou entrar em muitos detalhes sobre isso, pois é muito mais avançado e envolve selecionar objetos para você e outros enfeites.

Caso o lote estático ou dinâmico não esteja funcionando corretamente (o que você pode ver verificando o depurador de quadros), é necessário certificar-se de que realmente está usando material compartilhado e não está fazendo cópias do material por acidente com a chamada meshRenderer.material. Se você ligar .material, fará cópias de seus materiais e interromperá o lote. Use em .sharedMaterialvez disso.

Desde o Unity 5.6, você pode usar o Frame Debugger para determinar por que determinadas chamadas de draw não fizeram lote com as chamadas de draw anteriores. Isso será realmente útil ao tentar reduzir as chamadas do seu jogo.

A instância tem as seguintes vantagens sobre o lote estático / dinâmico / personalizado:

  • Usa menos memória, pois a malha não precisa ser duplicada na memória
  • Pode usar vários materiais, apenas shader compartilhado é necessário
  • Objetos podem ser animados

Também como desvantagem, é um recurso bastante novo no Unity e pode ser um pouco instável. GPUs de dispositivos móveis ou mais antigos também não oferecem suporte necessariamente à instanciação.

Lasse
fonte
1. Sim, eu tentei LODs e, para minha surpresa, realmente piorou. Eu tinha 3 variações das árvores, cada uma com uma contagem de vértices um pouco menor, e um plano plano com uma imagem renderizada da árvore.
mr-mate
2. Todas as minhas árvores estão marcadas como estáticas. Tanto quanto eu sei que permite o lote? Isso está correto? E quando você diz material compartilhado, você quer dizer simplesmente que as árvores têm o mesmo material?
mr-mate
3. Que tipo de melhoria de desempenho isso realmente faria? Vale a pena tentar?
mr-mate
11
2/3: Na minha experiência, o Unity não faz um trabalho muito bom em lotes dinâmicos e lotes estáticos aumentam o tamanho da compilação, então eu mesmo implementei os lotes e fiz a malha combinando o tempo de carregamento. Usando essa técnica, consegui fazer 2500 drawcalls para comprimir em aproximadamente 300 drawcalls, o que foi crucial para o nosso jogo móvel, onde as drawcalls são importantes. Fazia um pouco de vértices desnecessários a serem calculados (fora da tela), mas valia a pena.
Lasse
2
tfw quando você lê uma pergunta sobre o mau desempenho com árvores e não uma única palavra sobre billboarding está perdido
Num Lock
13

Ok, então o problema era simplesmente que eu não estava usando GI pré-calculado em tempo real. Verifico isso há pouco tempo, mas não teve um efeito imediato, por isso deixei e esqueci, e o tempo de processamento da iluminação também foi muito longo. No entanto, acabou de processá-lo, e minha palavra, meus fps aumentaram em 3x. Então, por enquanto, deixarei assim e, no futuro, tenha certeza de estar sempre usando o GI em tempo real do pré-computador!

Se ainda houver mais alguma coisa que eu possa fazer para melhorar ainda mais a performance, entre em contato, ficaria muito grato!

Sr. Matt
fonte
2
Use o Oclusion Culling, também se a sua cena for grande - considere dividi-la em pedaços, por exemplo, muitos terrenos, carregue e descarregue.
Candid Lua _Max_
Dado que você parece ter resolvido o seu problema, provavelmente deve aceitar esta resposta.
Gnemlock