Estou desenvolvendo um jogo 2D baseado em sprite para plataforma (s) móvel (s) e estou usando o OpenGL (bem, na verdade, o Irrlicht) para renderizar gráficos. Primeiro, implementei a renderização de sprite de uma maneira simples: todo objeto de jogo é renderizado como um quad com sua própria chamada de empate na GPU, o que significa que, se eu tivesse 200 objetos de jogo, fiz 200 chamadas de empate por quadro. É claro que essa foi uma péssima escolha e meu jogo foi completamente vinculado à CPU porque há uma pequena sobrecarga de CPU associada a cada chamada de empate da GPU. A GPU permaneceu ociosa a maior parte do tempo.
Agora, pensei em melhorar o desempenho coletando objetos em lotes grandes e processando esses lotes com apenas algumas chamadas de empate. Eu implementei lotes (para que todos os objetos do jogo que compartilham a mesma textura sejam renderizados no mesmo lote) e pensei que meus problemas haviam desaparecido ... apenas para descobrir que minha taxa de quadros estava ainda mais baixa do que antes.
Por quê? Bem, eu tenho 200 (ou mais) objetos de jogo e eles são atualizados 60 vezes por segundo. Cada quadro que eu tenho que recalcular nova posição (translação e rotação) para vértices na CPU (GPU em plataformas móveis não suporta instanciação, então não posso fazê-lo lá), e fazendo esse cálculo 48000 por segundo (200 * 60 * 4 desde todo sprite tem 4 vértices) simplesmente parece muito lento.
O que eu poderia fazer para melhorar o desempenho? Todos os objetos do jogo estão se movendo / girando (quase) todos os quadros, então eu realmente tenho que recalcular as posições dos vértices. A única otimização que eu conseguia pensar é uma tabela de consulta para rotações, para que eu não tivesse que calculá-las. Os sprites de ponto ajudariam? Algum hacks desagradável? Algo mais?
Obrigado.
fonte
Eu recomendaria ter um VBO, com cada vértice que contenha a posição / rotação de cada objeto renderizado e os lotes com base na textura como você está fazendo. Eu não estou muito familiarizado com o ogl ES, por isso não tenho certeza de qual versão do glsl ele suporta, mas você pode até fazer um lote com base em um conjunto de texturas e armazenar quais das quatro texturas que você está passando em que você usaria dentro do vértice. Os sprites pontuais definitivamente melhorariam seu desempenho, pois reduziriam drasticamente a quantidade de dados que você está enviando, e os lotes nunca diminuirão o desempenho se você estiver fazendo isso corretamente. Além disso, você pode melhorar um pouco o desempenho calculando a rotação no sombreador e passando apenas um valor int / float para os parâmetros ou dentro do próprio vértice. (os parâmetros seriam mais rápidos,
fonte
Você menciona plataformas móveis que não possuem instanciamento. Mas você ainda tem shaders de vértice, não é?
Nesse caso, você ainda pode executar pseudo-instanciamento, o que também é muito rápido. Faça um VBO (GL_STATIC_DRAW) com os pontos de canto (relativos ao ponto central do sprite, por exemplo, -1 / -1, 1 / -1, 1/1, -1/1) e todas as coordenadas de textura necessárias, nele .
Em seguida, defina um dos atributos genéricos do vértice para cada chamada de desenho no ponto central do sprite e desenhe os dois triângulos com o buffer vinculado. Dentro do sombreador de vértice, leia o atributo de vértice genérico e adicione as coordenadas do vértice.
Isso economizará o bloqueio de uma transferência de dados para cada sprite e deve ser muito mais rápido. O número real de chamadas de empate não é tão importante, o bloqueio / bloqueio no meio é.
fonte
O problema reside na quantidade de dados que você está enviando para a GPU em cada quadro. Apenas crie um VBO para cada lote e preencha-o uma vez e aplique as matrizes de transformação correspondentes (via glMultMatrix ou um sombreador se você estiver usando o ES 2.0) ao desenhar os lotes.
fonte