Estou fazendo esta pergunta porque não encontrei uma resposta definitiva para ela.
Antes de mais, deixe-me dizer algumas coisas sobre o jogo e o que eu já fiz. O jogo será um RTS ambientado em um mundo processualmente gerado usando ruído Simplex. O mundo consiste em pedaços de 16 x 16 de sprites de 64 x 64. Consegui carregar e descarregar pedaços dinamicamente, o que funciona muito bem. O mundo parecerá um pouco com o Rimworld, de cima para baixo com diferentes camadas de sprites (primeiro terreno, sprites de transição, árvores, decalques etc.). Os mundos recém-gerados podem conter entidades que podem afetar o meio ambiente (por exemplo, uma vila que se tornou uma cidade) e, portanto, o pedaço. Tenho certeza de que isso pode ser calculado usando algum tipo de função, mas é algo a ser observado.
O principal problema que tenho é quando diminui o zoom, mais e mais peças são desenhadas, o que afeta seriamente o desempenho. Em cerca de 30000 sprites, a seção de desenho leva 8 ms, que é metade do necessário para executar a 60 FPS. E esse é apenas o terreno. Estou usando atlas de textura para limitar as contagens de empate (30000 sprites desenhados em 6 contagens).
O objetivo é diminuir o zoom do nível da cidade / vila / cidade até ver um país inteiro. Isso deve ser feito dinamicamente (por exemplo, não clicando em um ícone de minimapa, mas basta rolar para trás como no Supreme Commander).
Eu li muitos artigos sobre esse problema, mas não encontrei ou vi um exemplo claro de onde ele funcionaria. Aqui está uma lista de técnicas que eu achei que deveriam funcionar:
- Retângulos sujos, como descrito aqui , onde você só desenha coisas novas e mantém o resto no backbuffer. Isso faz muito sentido, mas eu não tenho idéia de como implementar isso no Monogame.
- Minha escolha preferida: faça uso extensivo de RenderTargets, conforme descrito aqui , onde você atrai um RenderTarget e o salva como textura. No meu caso, um pedaço de 16 x 16 composto por 64 x 64 criaria uma textura de 1024 x 1024. Eu realmente duvido que isso funcione em termos de desempenho, mas o resultado consistiria em texturas altamente detalhadas e também é ótimo de usar, considerando o fato de que a maioria é estática (terreno / árvores etc.) e não muda tanto. Mas isso também significa que toda vez que uma alteração é feita em um pedaço, o Texture2D precisa ser alterado usando o SetData, que pelo que experimentei consome bastante CPU. No entanto, se as texturas fossem 16 x 16, elas podem realmente funcionar, além de reduzir o uso de memória e disco.
- Até texturas, especificando o SourceRectangle no SpriteBatch. Para prados / oceanos enormes, isso é uma vantagem, pois apenas um sprite é desenhado. No entanto, para terrenos detalhados com cores diferentes e sprites diferentes misturados (biomas e transições de biomas), receio que não faça uma diferença enorme.
- Minha própria solução, que compromete os detalhes, era usar um ladrilho branco de 64 x 64 padrão, dar a cor dos 4 ladrilhos circundantes e escalá-lo para cobrir os 4 ladrilhos anteriores. A diferença aqui (além do azulejo ter uma cor lisa) é que a paisagem mudou visivelmente. Também devo mencionar que as florestas ainda precisam ser desenhadas individualmente, pois não são perfeitamente quadradas.
Se alguém tiver alguma idéia de como resolver esse problema, mesmo que isso comprometa certas coisas (como detalhes ou uso de sprites 16 x 16), eu adoraria ouvi-lo.