Fora dos limites em jogos AAA

21

Em muitos títulos AAA comuns (principalmente jogos de mecanismo de origem), quando o jogador alcança uma área 'não atendida', como fora dos limites, ou beliscando o mapa; um efeito estranho ocorre na tela (ruptura do buffer?).

Pode ser descrito como semelhante à trilha de janelas que o Windows XP pode deixar para trás, arrastando uma janela enquanto há um travamento do sistema.

Só posso postular que os desenvolvedores não limpam o buffer de cores ao atualizar a tela?

Isso está correto? Se sim, por quê?

deceleratedcaviar
fonte
8
BTW, isso geralmente é chamado de efeito "Hall of Mirrors" ou HOM.
Nathan Reed

Respostas:

35

Era uma vez, limpar os buffers de cor e profundidade, na verdade, levava tempo. Fazer uma limpeza significava que a placa gráfica teria que percorrer todos os pixels do buffer de quadros e escrever um valor para ele.

Por esse motivo, os desenvolvedores de jogos descobriram que seria mais eficiente simplesmente assumir que cada pixel seria renderizado novamente. Eles desenvolveram muitas técnicas para fazer isso.

O buffer de cores é o mais fácil de ignorar. Menos fácil é o buffer de profundidade, porque seria poluído com dados antigos. Então, o que eles fizeram foi simples.

No quadro 0, eles renderizariam com um glDepthRange(ou o equivalente D3D) de (0, 0,5) e usariam um glDepthFuncde GL_LESS(ou GL_LEQUAL). Isso significa que o valor de profundidade mais distante que você obteria no buffer de profundidade é 0,5. Portanto, o maior valor no buffer de profundidade no final do quadro 0 é 0,5 (supondo que você tenha gravado em cada pixel).

No quadro 1, eles alterariam o alcance da profundidade para (1, 0,5). Observe que, nesse caso, o valor da profundidade próxima é maior que a profundidade distante. Mas eles também mudariam a função de profundidade para GL_GREATER(ou GL_GEQUAL), o que reverte o significado do teste de profundidade. Como o maior valor no buffer de profundidade é 0,5, tudo o que você escrever terá um valor maior que isso. Como o teste de profundidade foi revertido, isso efetivamente significa que tudo o que foi escrito no quadro 0 está agora mais distante do que qualquer coisa que possa ser escrita no quadro 1. No final do quadro 1, o menor valor no buffer de profundidade é agora 0,5.

E então eles repetem.

Em qualquer hardware fabricado desde 2003, isso não é mais uma otimização. De fato, é uma otimização negativa . Limpar o buffer de profundidade realmente torna o hardware mais rápido . Não mesmo.

Basicamente, o que acontece é que a limpeza de buffers não grava nada. Eles armazenam alguns bits nos caches da GPU que permitem ao sistema saber para que cor / profundidade foram limpos. Quando o sistema tenta gravar em uma linha de cache do buffer de quadros, não se preocupa em ler o que está lá, porque já sabe que é um campo em branco do valor de cor / profundidade clara. Se você tentar se misturar com o que está lá ou fazer um teste de profundidade, novamente, não há necessidade de ler: ele sabe qual valor misturar / testar com / contra.

Portanto, toda primeira leitura / modificação / gravação que você faz em cada linha de cache após uma limpeza é basicamente uma gravação. É grátis .

Além disso, ter um buffer de profundidade irregular pode funcionar contra o Hyper-Z / Hierarchial-Z / qualquer otimização de descarte de Z no hardware. Sim, sua cena funcionará contra essas opções à medida que você adicionar detalhes. Mas se o seu buffer de profundidade estiver irregular de renderizações anteriores, mesmo que esses objetos de segundo plano estejam em segundo plano, isso poderá afetar a eficiência das técnicas de descarte de Z. E isso não vai ajudar no desempenho.

Portanto, você nunca deve fazer essa técnica de reversão de profundidade nos jogos modernos.

Nota: O Jari faz um bom argumento em arquiteturas de renderização baseadas em blocos (como encontrado na maioria das plataformas móveis). Não limpar a profundidade também pode tornar as coisas desagradáveis.

Nicol Bolas
fonte
Sua última afirmação implica nunca fazer o buffer de profundidade alternando ou? Ótima resposta.
Deceleratedcaviar
1
@Daniel Sim. Esclarei minha postagem.
Nicol Bolas
3
Além disso, ignorar as arquiteturas de binning (como a maioria dos chips OpenGL ES) causa uma enorme perda de desempenho, pois o chip gráfico não pode fazer suposições sobre o estado do buffer de cores.
Jari Komppa
5

Sim, você está certo que o buffer de fundo não está sendo limpo.

Por que (principalmente) é mais rápido o uso de um sombreador personalizado que penetra os valores de profundidade em direções opostas a cada quadro e se baseia no fato de que seu jogo sempre renderiza todos os pixels na tela.

Portanto, com custo zero, você salva um buffer limpo por quadro.

Patrick Hughes
fonte
1
Eu não sei sobre ping-pong em profundidade; todo mecanismo com o qual estou familiarizado limpa o buffer de profundidade / estêncil em cada quadro. Além disso, sim, se o jogo renderizar todos os pixels (como deveria), você não precisará limpar o buffer de cores.
Nathan Reed
Você poderia dar um exemplo para o shader, boa resposta caso contrário.
Deceleratedcaviar
1
Sei que você está perguntando sobre mecanismos recentes, lendo o comentário do @ NathanReed é quantos mecanismos somente para PC funcionam agora. A torção do buffer Z é uma técnica mais antiga, vou ver se consigo encontrar uma referência. Os mecanismos do console também limparão todo o buffer de cores, mesmo um pixel que mostra o efeito HOM que Nathan nomeou falhará em um título e forçará ele a passar por envios novamente.
Patrick Hughes