Como um conto de praga: o quadro da inocência é processado


Prefácio


Como em meus outros estudos, vamos começar com a introdução. Hoje olhamos para o último jogo do desenvolvedor francês Asobo Studio. A primeira vez que vi um vídeo deste jogo no ano passado, quando um colega compartilhou comigo um trailer de 16 minutos . A mecânica do "rato contra a luz" chamou minha atenção, mas eu realmente não queria jogar esse jogo. No entanto, após o seu lançamento, muitos começaram a dizer que parece que foi fabricado no motor Unreal, mas não é assim. Fiquei curioso para ver como a renderização funciona e o quanto os desenvolvedores foram inspirados pela Unreal em geral. Eu também estava interessado no processo de renderizar um bando de ratos, porque no jogo parecia muito convincente e, além disso, é um dos elementos principais da jogabilidade.

Quando comecei a tentar capturar o jogo, pensei que teria que desistir, porque nada funcionava. Embora o jogo use o DX11, que agora é suportado por quase todas as ferramentas de análise, não consegui fazê-las funcionar. Quando tentei usar o RenderDoc, o jogo travou na inicialização e o mesmo aconteceu com o PIX. Ainda não sei por que isso acontece, mas, felizmente, consegui concluir várias capturas usando o NSight Graphics. Como sempre, levantei todos os parâmetros ao máximo e comecei a procurar quadros adequados para análise.

Quebra de quadro


Depois de fazer algumas capturas, decidi usar um dos primórdios do jogo para a análise de quadros. Não há muita diferença entre as garras e, além disso, posso evitar spoilers.

Como sempre, vamos começar com o quadro final:


A primeira coisa que notei foi um equilíbrio completamente diferente neste jogo de renderização de eventos em comparação com o que vi em outros jogos anteriores. Existem muitas chamadas de empate aqui, o que é normal, mas surpreendentemente apenas algumas delas são usadas para pós-processamento. Em outros jogos, depois de renderizar cores para obter o resultado final, o quadro passa por muitos outros estágios, mas em A Plague Tale: Innocence a pilha de pós-processamento é muito pequena e otimizada para apenas alguns eventos de renderização / computação.

O jogo começa a construir um quadro renderizando GBuffer com seis alvos de renderização. Curiosamente, todos esses destinos de renderização têm um formato inteiro não assinado de 32 bits (com exceção de um) em vez de cores RGBA8 ou outros formatos específicos para esses dados. Isso foi difícil porque tive que decodificar cada canal manualmente usando a função Custom Shader do NSight. Passei muito tempo descobrindo quais valores são codificados em destinos de 32 bits, mas é possível que eu tenha perdido alguma coisa.


GBuffer 0

O primeiro alvo contém alguns valores de sombreamento em 24 bits e outros para cabelos em 8 bits.


GBuffer 1

O segundo alvo se parece com um alvo RGBA8 tradicional com diferentes valores de controle de material em cada canal. Pelo que entendi, o canal vermelho é metal (não está totalmente claro por que algumas folhas estão marcadas com ele), o canal verde parece um valor de rugosidade e o canal azul é a máscara do personagem principal. Nenhuma das capturas que fiz usou o canal alfa.


GBuffer 2

O terceiro alvo também se parece com RGBA8 com albedo nos canais RGB, e o canal alfa em cada captura que fiz foi completamente branco, então não entendo bem o que esses dados devem fazer.


GBuffer3

O quarto alvo é curioso, porque em todas as minhas capturas é quase completamente preto. Os valores parecem uma máscara de parte da vegetação e de todos os cabelos / pêlos. Talvez isso tenha algo a ver com translucidez.


GBuffer 4

O quinto alvo é provavelmente algum tipo de codificação normal, porque eu não os vi em nenhum outro lugar, e o shader parece amostrar mapas normais e, em seguida, enviar para esse destino. Com isso em mente, ainda não descobri como visualizá-los adequadamente.


Profundidade do GBuffer 5


Máscara do GBuffer 5

O último destino é uma exceção, pois usa um formato de ponto flutuante de 32 bits. A razão para isso é que ele contém a profundidade linear da imagem e o bit de sinal codifica alguma outra máscara, mascarando novamente o cabelo e parte da vegetação.

Após a criação da GBuffer, a resolução do mapa de profundidade é reduzida no sombreador computacional e, em seguida, os mapas de sombra são renderizados (mapas de sombra em cascata direcionais do sol e mapas de profundidade cúbica de fontes de luz pontuais).


Raios crepusculares

Depois de completar os mapas de sombras, você pode calcular a iluminação, mas antes disso, os raios divinos são renderizados em um alvo separado.


SSAO

No estágio de cálculo da iluminação, um sombreador computacional é realizado para calcular o SSAO.


Geometria opaca iluminada

A iluminação é adicionada a partir de mapas cúbicos e fontes de luz locais. Todas essas diferentes fontes de luz, combinadas com os alvos renderizados acima, formam uma imagem HDR iluminada como resultado.


Elementos de renderização proativos

Os elementos renderizados na renderização proativa são adicionados sobre a geometria opaca iluminada, mas não são particularmente perceptíveis nesta cena.

Após o acúmulo de todas as cores, estamos quase terminando, existem apenas algumas operações de pós-processamento e a interface do usuário.


A resolução de cores é reduzida no sombreador computacional e depois aumentada para criar um efeito de flor suave e muito bonito.


Após compor todos os resultados anteriores, adicionar sujeira da câmera, classificação de cores e, finalmente, correção de imagem tonal, obtemos as cores da cena. A sobreposição da interface do usuário fornece uma imagem desde o início do artigo.

Vale mencionar algumas coisas interessantes sobre a renderização:

  • Instanciamento (duplicação de geometria) é usado apenas para malhas individuais (parece que apenas para vegetação). Todos os outros objetos são renderizados em chamadas de desenho separadas.
  • Parece que os objetos são classificados aproximadamente da frente para trás, com algumas exceções.
  • Parece que os desenvolvedores não fizeram nenhum esforço para agrupar as chamadas de empate em termos de parâmetros materiais.

Ratos


Como eu disse no começo do artigo, uma das razões pelas quais eu queria explorar esse jogo foi por causa da maneira de renderizar o bando de ratos. A decisão me decepcionou de certa forma: parece que foi tomada pela força bruta. Aqui eu uso capturas de tela de outra cena do jogo, mas espero que não haja spoilers.


Como em outros objetos, os ratos não parecem ter nenhuma duplicação de geometria, a menos que alcancemos a distância na qual passamos para o último nível de detalhe da malha (LOD). Vamos ver como isso funciona.


LOD0


LOD1


LOD2


LOD3

Os ratos têm 4 níveis de LOD. Curiosamente, no terceiro nível, a cauda é dobrada para o corpo, enquanto a quarta cauda não. Isso provavelmente significa que as animações estão ativas apenas para os dois primeiros níveis. Infelizmente, o NSight Graphics não parece ter ferramentas suficientes para testar isso.


Sem duplicação (instanciação) de ratos.

Com duplicação.


Na cena mostrada acima, o seguinte número de ratos foi renderizado:

  • LOD0 - 200
  • LOD1 - 200
  • LOD2 - 1258
  • LOD3 - 3500 (com duplicação de geometria)

Isso nos faz entender que existe um limite estrito no número de ratos que podem ser renderizados nos dois primeiros LODs.

Na captura que fiz, não consegui identificar nenhuma lógica que vinculasse ratos a LODs individuais. Às vezes, os ratos mais próximos da câmera não são muito detalhados e, às vezes, os ratos que são pouco visíveis têm altos detalhes.

Em conclusão


Conto de Praga: Inocência é muito interessante em termos de renderização. Seus resultados, sem dúvida, me impressionaram, eles servem muito bem a jogabilidade. Como em qualquer mecanismo proprietário, seria ótimo ouvir uma análise mais detalhada dos lábios dos próprios desenvolvedores, principalmente porque não consegui confirmar algumas de minhas teorias. Espero que meu artigo um dia chegue a alguém do Asobo Studio e eles vejam que as pessoas têm interesse nisso.

Source: https://habr.com/ru/post/pt456614/


All Articles