Otimizando um jogo XNA 2D

56

Faz sentido implementar a lógica para ignorar objetos de renderização fora da janela de visualização ou não devo me preocupar com isso e deixar o Framework fazê-lo?

smnbss
fonte

Respostas:

79

A seleção é uma otimização de desempenho. Portanto, não faz sentido fazê-lo apenas por causa disso. Você tem que ter uma razão.


A GPU (não o XNA Framework) seleciona triângulos e pixels em uma velocidade incrivelmente rápida. Todo triângulo que você enviar deve ser transformado (através do seu shader de vértice). Depois, seleciona aqueles que aparecem fora da tela. Em seguida, preenche os triângulos restantes, separando os pixels que estão fora da tela. Os pixels restantes são então atraídos para o buffer traseiro (através do seu pixel shader).

(Quando digo "então" - na verdade, faz tudo isso em um pipeline massivamente paralelo).

Portanto, é muito raro e incomum que você precise selecionar triângulos individuais. Para atingir os limites dos vértices, você deve desenhar um número absurdamente grande de triângulos. Para atingir os limites de taxa de preenchimento, busca de textura ou sombreamento de pixel, geralmente é necessário ter uma alta complexidade de profundidade (nesse caso, a viewport / seleção de frustum não ajudará).


Portanto, geralmente há pouco ou nenhum custo em ter a geometria fora da tela.

O custo - particularmente no contexto de desenhar "objetos" (geralmente objetos 3D) - é realmente enviar esses objetos para a GPU em primeiro lugar . Envie muitos objetos e atinja seu limite de lotes (você recebe alguns milhares * lotes por quadro).

Eu recomendo a leitura desta resposta e deste deck de slides vinculado para uma descrição detalhada dos lotes.

Por esse motivo, se você implementar a seleção de frustum, poderá reduzir o número de lotes que enviar para a GPU. Se você é limitado por lotes - isso pode levá-lo abaixo do limite.


Agora - sua pergunta é sobre 2D XNA -, provavelmente você está usando SpriteBatch. Isso é um pouco diferente.

Não é por engano que se chama "Sprite Batch ". O que está fazendo é pegar os sprites que você desenha e fazer o melhor possível para enviá-los à GPU no menor número de lotes possível , agrupando-os.

Mas o SpriteBatch será forçado a iniciar um novo lote se:

  • Você desenha mais sprites do que pode caber em um único lote (2048 sprites no XNA 4)
  • Você altera a textura (é por isso que existe uma opção de classificação por textura)

Portanto, selecionar é uma otimização adequada se você estiver executando o primeiro. Se você está enviando um número tão grande de sprites que acaba com muitos lotes (provavelmente também está usando largura de banda - mas tenho certeza de que atingirá o limite de lotes primeiro). Isso geralmente acontecerá apenas se você tiver um mundo realmente enorme - para que você possa se safar de abates muito simplistas, rápidos, mas imprecisos nesse caso.

Agora - se você estiver desenhando com trocas de textura suficientes para ultrapassar o limite do lote, e muitas delas estiverem fora da tela e selecioná-las, você ficará abaixo do limite do lote. Então sim - selecionar é uma otimização que funcionará.

No entanto - uma melhor otimização a seguir nesse caso é usar atlas de textura (também conhecidos como: folhas de sprite). Isso permite reduzir o número de trocas de textura e, portanto, lotes - independentemente do que está na tela ou desativado. (Esse é o principal motivo pelo qual você pode especificar um retângulo de origem para seus sprites.)


(Como sempre: este é um conselho sobre otimização de desempenho. Portanto, você deve medir e entender o desempenho do seu jogo e os limites que está atingindo, antes de se esforçar para adicionar otimizações.)

Andrew Russell
fonte
5
+1 Por mencionar sobre não fazer a seleção apenas por uma questão, mas quando é necessário para o desempenho importa.
Marcouiller
12
+1 para finalmente me dizendo que as folhas de sprites têm de fato uma razão para existir excepto para programador / designer de conveniência
Bill
3
+1 para uma ótima explicação, aprendi muito com sua resposta.
precisa
11
O link para o pdf "Lote, Lote, Lote" está quebrado. Aqui está uma atualização: ce.u-sys.org/Veranstaltungen/…
Marton
13

De acordo com uma publicação nos fóruns do MSDN, a estrutura XNA não faz a seleção de frustum:

A estrutura do XNA não fará nenhum sacrifício para você - não foi possível, pois não tem idéia de onde algo realmente vai acabar. Todas as transformações são feitas na GPU e podem ser um sombreador personalizado.

http://xboxforums.create.msdn.com/forums/p/22763/121897.aspx

Este post continua dizendo que, se você tiver muitos objetos em sua cena, pode valer a pena rodar os seus.

Nate
fonte
6
Especialmente se você tiver um mapa de rolagem (você disse que era 2D, então isso pode ser relevante). É apenas um desperdício se você desenhar seções grandes que não são necessárias. Não é muito difícil e você pode ver algum tipo de melhoria.
Michael Coleman
1

Estou desenvolvendo motores procedentes de voxel terreno há alguns anos no XNA. Na maioria dos quadros, os motores estão transformando literalmente centenas de milhares de quads. Em meus perfis, descobri que o frustum e a seleção de oclusão aumentam o desempenho.

O perfil XNA HiDef (não Reach) possui uma classe OcclusionQuery que é usada para executar a Seleção de Oclusão. A seleção por oclusão remove os quadríceps de uma viewport que estão ocultos por outros quadríceps.

Outra coisa que você deve considerar é separar a geração e o mosaico separadamente.

Então, sim, quando você se aproxima de um número muito grande de quads em cada quadro que está sendo transformado, precisa pensar cuidadosamente em como aplicar técnicas de seleção e segmentação para manter a taxa de quadros, reduzindo o tráfego para os shaders de gpu.

Jason Coombes
fonte