No three.js, podemos simplesmente mesclar a geometria para limitar a quantidade de chamadas de empate e, assim, aumentar o desempenho. Em um teste simples com um material, eu poderia desenhar 50.000 cubos + sombras a 60fps na minha GPU GTX660. Sem a fusão da geometria, 5.000 cubos já causaram um problema.
Gostaria de saber como preservar os benefícios de renderizar cada malha de cubo por si própria. Por exemplo, como escolher uma malha de cubo quando tudo é mesclado em uma geometria? Por padrão, isso não é possível, é claro.
Existe alguma técnica comum para esse problema? Afinal, eu tenho todos os objetos de malha não imersos, mesmo após a mesclagem. Portanto, deve haver alguma maneira de utilizá-los para a colheita?
O que eu quero fazer em poucas palavras
- SimCity como jogo para fins de aprendizado
- Cada casa é uma malha de cubo
- Deseja renderizar 50.000 casas e poder adicionar e remover casas
- A seleção da casa via cursor do mouse (picking) deve ser possível
Respostas:
OK, entendi. Depois de mesclar toda a geometria, ainda tenho as malhas individuais em uma matriz. Então, eu posso simplesmente usar essas malhas para transmissão de raios, mesmo que elas nem sejam renderizadas. Levei um tempo para perceber isso.
Para a colheita, uso esta implementação de octree: http://threejs.org/examples/#webgl_octree_raycasting
Isso reduz os testes de interseção por atualização de 50.000 para ~ 500. Sem o octree, o fps diminuirá bastante.
O casco de picking laranja que você vê é, na verdade, a malha agora renderizada (+1 de chamada) com um material alterado e tamanho modificado.
Então, acho que o próximo passo é implementar algum tipo de particionamento de mapa. Ou seja, quebre a geometria mesclada em várias partes. A razão para isso é que a geometria mesclada possui uma grande quantidade de vértices. Isso significa que, se eu retirar o mapa 99% da tela, a placa de vídeo ainda precisará processar todos os vértices porque a geometria ainda está em exibição, pelo menos 1% dela. Portanto, se estiver quebrado, apenas as peças em exibição precisam ser renderizadas.
fonte
Para escolher, você também pode renderizar IDs de cada cubo para outro destino de renderização e apenas verificar qual é o valor do ID no cursor. O benefício é que a escolha é perfeita em pixels e funciona com eficiência também para geometria mais complexa.
Se todos os objetos tiverem a mesma geometria, você poderá usar a renderização instanciada. Um fluxo define a geometria, enquanto outro define propriedades por instância (por exemplo, transformação). Para o descarte de frustum, você precisaria criar o fluxo da instância de cada quadro com base no teste de visibilidade. Se você tiver uma grande quantidade de objetos, convém colocá-los em uma octree frouxa ou em algo para acelerar a seleção.
fonte
Não tenho certeza dos detalhes do three.js, mas dois possíveis problemas de desempenho vêm à mente em geral no OpenGL:
fonte
Outra abordagem que você pode adotar é criar algum atributo de vértice em sua geometria e colocar a lógica de destaque em seu shader de fragmento. Isso é extremamente útil quando você não deseja ter duas cópias de dados na memória e terá mais controle de como o destaque é implementado.
fonte