Estou desenvolvendo um jogo 2D e tenho muitos sprites. Eu usei animações e modelos 3D para renderizar em 2D, para dar a eles que "Fallout" ou "Diablo" olhem para eles. Também é mais fácil do que desenhar à mão, lol.
Eu já tive que reduzir a taxa de quadros para 15 fps, que foi a menor que eu pude diminuir sem fazer com que eles tivessem uma aparência instável. No entanto, foi triste devido à aparência incrivelmente suave de 24 quadros.
Há duas razões pelas quais fiz isso:
1) Reduza o espaço no disco rígido. Quanto menos imagens, menor será o meu jogo total.
2) Reduza o consumo de RAM. Quanto menos imagens forem carregadas, maior a probabilidade de evitar problemas que limitam minha limitação de RAM.
No entanto, se houvesse uma maneira de compactar as imagens no espaço do disco rígido e na RAM, eu o faria. Eu testei isso antes, e a maioria não recebe nenhuma alteração na qualidade ao passar de RGBA8888 para RGBA5555 e apenas um pequeno golpe ao converter para RGBA4444 no meu programa TexturePacker. No momento, não faço isso porque o SFML parece usar a mesma quantidade de memória, independentemente do tipo de imagem .PNG. Eu pesquisei sobre como carregá-lo de maneira diferente, mas não consegui encontrar nada sobre o assunto.
Eu li muito sobre como lidar com videogames 2D. O consenso é esmagador: coloque seus Sprites em uma textura maior para obter um ótimo desempenho! Então, eu agrupo meus pequenos sprites em uma planilha muito maior usando o TexturePacker.
No entanto, pretendo ter 10 a 15 animações por personagem, 5 direções para mover e 15 a 40 quadros por animação (provavelmente uma média de 24). Com 15 animações, 5 direções e uma média de 24 quadros por animação; Isso significa 1800 quadros individuais por personagem. Se embalado em uma folha de sprite, são apenas 75 imagens. (Uma folha de sprite por animação, por direção. 15 * 5)
Para o grande personagem chefe do jogo, não posso usar uma planilha e preciso programar uma maneira de simplesmente carregar uma imagem de cada vez. Ainda não sei se posso fazer isso por desempenho.
Para os personagens, eu já os coloco em uma planilha. Para um único personagem andando, isso parece funcionar na maioria das vezes, embora às vezes pare. No entanto, atribuo isso ao meu código mal concebido que troca as texturas em vez de pré-carregar todas as texturas para esse personagem.
Se eu fosse pré-carregar as texturas, faz sentido para folhas de sprite. Imagino que seja uma má ideia pré-carregar 1800 pequenas imagens para cada personagem.
No entanto, imagino que transmiti-los para dentro e para fora da memória, um de cada vez, seria extremamente rápido, portanto, eu só precisaria ter uma única imagem na memória de cada vez. Isso não significaria que, em um determinado momento, cada personagem consumisse apenas alguns KB em vez de 45 + MB?
Eu imagino que isso prejudicaria meu desempenho, pois o streaming precisaria ser incrivelmente rápido (15 imagens entrando e saindo da memória e renderizando por segundo) e, embora as imagens fossem muito pequenas, seria uma idéia melhor carregar planilhas de caracteres na memória. Mas terei que codificar um sistema de renderização semelhante a um fluxo de imagem única para meu personagem maior, de qualquer maneira.
Eu tenho experimentado, mas não é um processo simples. Especialmente porque estou trabalhando em outras partes do mecanismo de jogo que não lidam com gráficos no momento.
Respostas:
Temos um caso semelhante com o nosso RTS Remake. Todas as unidades e casas são sprites. Temos 18.000 sprites para unidades e casas e terrenos, além de outros ~ 6.000 para cores de equipe (aplicadas como máscaras). Além disso, também temos cerca de 30.000 caracteres usados em fontes.
Portanto, a principal razão por trás dos atlas é:
O que não funcionou para nós:
Agora temos tudo em várias dezenas de atlas 1024x1024 (as GPUs modernas suportam dimensões ainda maiores) e isso funciona muito bem, consumindo apenas ~ 300mb de memória, o que é bastante bom para um jogo de PC. Algumas otimizações que tivemos:
Ao considerar seriamente a possibilidade de mudar para dispositivos móveis, você se preocupará com restrições. Por enquanto, basta começar o jogo e atrair jogadores! ;)
fonte
Eu tenho uma resposta tangencialmente relacionada em aqui , mas a ideia geral é que, se você estiver carregando e desenhando texturas em momentos diferentes (você não está carregando texturas adicionais enquanto está renderizando), então existem dois lugares onde você afetará seu desempenho:
Tempo de carregamento:
Este é o momento em que você carrega suas texturas na memória. a inteira quantidade de dados que você está enviando para VRAM é o que a maioria irá definir quanto tempo o seu tempo de carregamento será. Tornar suas texturas formatos menores, como RGBA4444, tornará isso mais rápido. No entanto, a menos que você esteja carregando texturas nas centenas de megabytes para a VRAM, provavelmente não terá um gargalo aqui. Se o fizer, uma boa tela de carregamento pode facilitar a espera.
Unir suas texturas aos atlas terá pouco efeito, pois toda a quantidade de informações que você está enviando para o VRAM será a mesma. De fato, se você está atlasando suas texturas e precisa deixar espaços vazios em seus atlas, estará enviando mais dados para o VRAM e, portanto, essa parte será mais lenta!
Desempenho de renderização:
Quando todas as suas texturas estiverem em VRAM, a quantidade de texturas que você possui não afetará o desempenho da renderização. Existem quatro elementos que afetam o desempenho da renderização:
Alterações de estado de renderização : sempre que você alterar a imagem da qual deseja renderizar, aumentará seriamente o tempo necessário para renderizá-la. Em geral, você deseja minimizar a quantidade de alterações de estado e pode reduzir a quantidade de alterações de estado agrupando várias imagens que serão desenhadas consecutivamente em um atlas de textura.
Apenas atlas não é suficiente. Você precisa atlas de uma maneira em que as alterações de estado sejam reduzidas, a fim de obter ganhos de desempenho. Por exemplo, pode-se pensar que ter seu personagem principal em uma folha de sprite obterá um ganho de desempenho, mas se você estiver apenas desenhando um sprite dessa folha de sprite por quadro, não obterá nenhum ganho de desempenho em comparação a ter cada sprite em um arquivo separado.
Atlasing adequado não é trivial, mas em geral você pode agrupar sprites com segurança da mesma camada. Por exemplo, ter todos os itens da GUI em uma planilha de sprites é uma idéia muito promissora, enquanto agrupar monstros em ordem alfabética pode não.
Chamadas de empate: em geral, convém manter suas chamadas de empate no mínimo. Uma boa regra geral é que, se não houver alterações no estado de renderização entre duas chamadas de draw, você poderá juntá-las em uma única chamada de draw. Para obter ganhos de desempenho mais avançados, você pode usar, por exemplo, 8 amostradores de textura e chamadas em grupo para cada 8 texturas; portanto, você só precisa alterar as texturas a cada 8 texturas.
Contagem de triângulos: Na verdade, quanto mais triângulos você desenhar, mais tempo levará para desenhá-los. No entanto, nos computadores modernos e na maioria dos jogos 2D, você estará muito longe de maximizar isso. Você pode desenhar com segurança centenas de milhares de sprites por quadro e ainda obter taxas de quadros incrivelmente boas. Você provavelmente estará mais ligado à CPU se estiver desenhando quantidades extremas de sprites antes de ter problemas com sua GPU.
Configurações da API: se você estiver fazendo tudo certo e continuar com taxas de quadros estranhamente baixas, verifique as configurações com as quais está desenhando seus sprites. Não conheço SFML, mas, por exemplo, no Direct3D 9, a criação de um buffer de vértice com
D3DUSAGE_DYNAMIC
, ouD3DPOOL_MANAGED
pode aumentar facilmente o tempo de renderização em dez vezes. Obviamente, o uso do vSync limitará a taxa de quadros na taxa de atualização do seu monitor. Além disso, o uso de FVFs não alinhados pode diminuir o desempenho em algumas GPUs. Isso também é para o Direct3D 9.No seu caso, verifique a documentação da API que você está usando.
Se você tiver apenas uma quantidade baixa a moderada de texturas (menos de 1 GB) e estiver desenhando pequenas quantidades de sprites (menos de um milhão por quadro), a primeira coisa que gostaria de ver é alterar as configurações da API e reduzindo a quantidade de estados de renderização e fazer chamadas.
fonte