O Diablo Immortal aumenta a qualidade da imagem com o rastreamento de raios de hardware

Diablo Immortal é um jogo de ação multijogador (ARPG) sem custo financeiro desenvolvido em conjunto pela Blizzard Entertainment e pela NetEase. Diablo Immortal, um novo capítulo da série Diablo, lançado em 2022. O jogo preenche a lacuna entre Diablo 2 e Diablo 3 e desenvolve uma nova aventura em torno dos fragmentos da Pedra do Mundo, em que os jogadores exploram o continente de Sanctuary para lutar contra demônios e forças corrompidas.

Com a inovação da arquitetura de GPU para dispositivos móveis e os avanços nos recursos de aceleração de hardware, a tecnologia de ray tracing está migrando gradualmente de computadores para dispositivos móveis, se tornando um dos principais fatores de renderização de gráficos de alta fidelidade. O cálculo de reflexos dinâmicos fisicamente realistas é computacionalmente exigente, mas uma unidade de hardware dedicada torna isso possível em plataformas móveis com restrição de energia. Ao rastrear o caminho de propagação da luz pela cena em tempo real, a tecnologia simula com precisão o comportamento de reflexão de superfícies complexas, como espelhos, metais e líquidos. O ray tracing supera as limitações espaciais e os erros de aproximação dos esquemas de rasterização tradicionais e oferece suporte à expressão global consistente de fontes de luz dinâmicas, objetos fora da tela e reflexos em vários níveis.

Ray tracing de hardware em dispositivos móveis

A tecnologia de ray tracing de hardware inclui principalmente dois paradigmas de implementação: pipeline de ray tracing e consulta de raios.

O pipeline de ray tracing cria um pipeline completo em estágios de sombreador dedicados (geração de raios / interseção / sombreador de hit mais próximo). Embora seja possível alcançar um controle preciso de interação de raios, o pipeline de ray tracing exige uma configuração independente, o que aumenta a complexidade do desenvolvimento.

A consulta de raios, por outro lado, permite que as consultas de raios sejam iniciadas diretamente de shaders de computação ou fragmento tradicionais, tornando-a uma tecnologia principal para o rastreamento de raios em dispositivos móveis. Ao eliminar a necessidade de pipelines separados, a consulta de raios simplifica significativamente o processo de desenvolvimento e também tem três vantagens principais:

  1. Oferece compatibilidade com ambientes de computação heterogêneos e hardwares de ray tracing incompletos
  2. Suporte para invocação sob demanda de ray tracing em qualquer estágio de sombreamento
  3. Ao reduzir o uso de recursos, ele atende às restrições de largura de banda e potência das plataformas móveis e fornece uma base viável para efeitos avançados, como iluminação global dinâmica e reflexão em tempo real em jogos para dispositivos móveis.

O Diablo Immortal usa o Vulkan para aproveitar os recursos de ray tracing de hardware da GPU. O jogo calcula o caminho dos raios de luz pela cena em tempo real e considera propriedades de materiais complexos para atingir efeitos de reflexão inovadores em tempo real em dispositivos Android.

Figura 1. Cena com reflexão por ray tracing ativada.
Figura 2. Cena com a reflexão de ray-traced desativada.

Estrutura de aceleração

A estrutura de aceleração é o núcleo do rastreamento de raios de hardware. A estrutura de aceleração melhora muito a eficiência do teste de interseção de raios com a organização hierárquica de dados.

O sistema geralmente tem dois níveis: a estrutura de aceleração de nível superior (TLAS) e a estrutura de aceleração de nível inferior (BLAS):

  • O TLAS tem a função de gestor de cena. Ao registrar a matriz de transformação espacial (incluindo posição, rotação e escala) de todas as instâncias do BLAS, o TLAS realiza a organização global de cenas dinâmicas. Por exemplo, o TLAS permite que os desenvolvedores distribuam centenas de instâncias do mesmo modelo de árvore em diferentes posições e poses na cena. Assim, os desenvolvedores só precisam atualizar a matriz de transformação do objeto em movimento em cada frame, em vez de reconstruir a geometria.
  • BLAS como unidade base: responsável por codificar de maneira eficiente os detalhes geométricos de um único objeto 3D, o BLAS estabelece uma estrutura de índice espacial usando o algoritmo de hierarquia de volume de limite (BVH, na sigla em inglês) para que áreas irrelevantes possam ser puladas rapidamente durante a detecção de raios.

Esse design hierárquico permite que o pipeline de ray tracing forme uma cadeia de detecção eficiente de ray ==> TLAS (instância de objeto de peneira grossa) ==> BLAS (interseção exata).

A separação de modelos dinâmicos e estáticos é fundamental para minimizar o custo da construção da estrutura de aceleração:

  • Modelo estático: o BLAS só precisa ser criado uma vez na fase de inicialização e pode ser reutilizado diretamente no carregamento de cenas subsequentes. Para evitar o atraso no carregamento de cenas em grande escala, a tecnologia de pré-construção assíncrona de enquadramento pode ser usada para distribuir a tarefa de construção do BLAS para vários frames.
  • Modelo dinâmico
    • Orientado por animação esquelética: os dados de vértice com skin precisam ser computados em paralelo pelo compute shader em cada frame para gerar um novo buffer de vértice e acionar a atualização incremental do BLAS correspondente, o que evita a reconstrução completa para melhorar o desempenho.
    • Transformação de corpo rígido: se apenas transformações de translação/rotação/zoom estiverem envolvidas, não será necessário modificar o BLAS. Basta atualizar a matriz de transformação do mundo no TLAS e acionar o processo de atualização rápida do TLAS.

A reconstrução periódica é essencial para manter a eficiência da estrutura de aceleração em cenas dinâmicas de ray tracing. Quando objetos dinâmicos sofrem mudanças significativas na topologia geométrica, como deformação ou deslocamento de vértices em grande escala, a divisão espacial original pode falhar, reduzindo o desempenho da detecção de colisão durante a travessia de raio. Como resultado, uma reconstrução completa, em vez de uma atualização incremental, do BLAS/TLAS altamente dinâmico precisa ser acionada a cada N frames.

Por fim, para otimizar o desempenho da renderização de ray tracing, adote uma estratégia de construção dinâmica de TLAS com base na região visível do personagem: apenas os modelos dentro do limite do raio ativo do personagem são incluídos no TLAS para reduzir a sobrecarga principal do cálculo de interseção de raios.

Reflexos de traçado de raios

Os reflexos de raios traçados têm várias vantagens em relação a técnicas tradicionais, como reflexos no espaço da tela (SSR, na sigla em inglês) e reflexos planares, que são superfícies simples que projetam uma cena em uma dimensão. A reflexão com ray tracing simula fisicamente o caminho da luz, captura com precisão objetos dinâmicos dentro e fora da cena, oferece suporte a reflexões naturais de superfícies curvas e não planas e permite vários efeitos de luz difusa, como espelhos. Em contraste, o SSR é limitado às informações visíveis na tela, e as reflexões planas são propensas a erros visuais ou distorções em cenas complexas.

Figura 3. O reflexo das asas na piscina.
Figura 4. O reflexo do monstro.

A reflexão com ray tracing é semelhante ao SSR tradicional em princípio: a reflexão com ray tracing emite raios na direção da reflexão da linha de visão em uma base de pixel por pixel e calcula a interseção dos raios com os objetos da cena. O ponto de interseção retornado pela API de consulta de raios contém informações geométricas (incluindo ID de instância, índice de geometria e índice primitivo) e parâmetros de rasterização (coordenadas barycentric) no nível do triângulo, mas não contém dados de cor de pixel. A solução típica usa a tecnologia de vinculação de recursos sem vinculação para pré-compilar todos os parâmetros de textura e material da cena em uma matriz de índice global. Usando os identificadores geométricos retornados pela consulta de raio, as propriedades físicas do material correspondente (como mapa normal e rugosidade) podem ser pesquisadas e combinadas com a interpolação de coordenadas baricentrificadas para calcular as informações de sombreamento da superfície, e o valor de cor real da interseção pode ser reconstruído por rasterização.

No entanto, durante o processo de implementação, a equipe do Diablo Immortal descobriu dois problemas técnicos significativos:

  1. O modelo de iluminação foi forçado a ser unificado, o que entrou em conflito com os diversos sistemas de sombreamento acumulados na história do projeto e resultaria em uma incompatibilidade entre o material especular e o original.
  2. A variedade de formatos de vértice leva à degradação da eficiência de ramificação de instruções na etapa de rasterização, que é um problema importante no orçamento de desempenho apertado do dispositivo móvel.

A equipe do Diablo Immortal introduziu o buffer de visibilidade de forma inovadora para separar o processamento de geometria dos cálculos de sombreamento:

  • Fase de ray tracing: as informações de acerto de raios no nível do pixel são capturadas em tempo real com a consulta de raios. O identificador espacial 3D (InstanceID com PrimitiveIndex) do ponto de interseção é codificado em um ID de visibilidade compacto e gravado no buffer de espaço da tela.
  • Etapa de coloração: semelhante às operações realizadas por sombreadores de vértices e de pixels, os identificadores geométricos no buffer de visibilidade são analisados dinamicamente, as propriedades de vértice (como UVs e normais) e mapas de materiais baseados em física do modelo original são buscados, e os cálculos de sombreamento associados ao tipo de material são finalmente realizados.

Essa solução permite que os recursos de arte sejam conectados ao sistema de reflexão de ray tracing sem precisar modificar formatos de vértice ou shaders.

Etapas de renderização específicas

Passagem de consulta do Ray

Corresponde ao estágio de ray tracing e gera um buffer de visibilidade para reflexos no espaço da tela:

  • Color0
    • Formato: R32G32UInt
    • R = TriangleID, G = Barycentrics
Figura 5. Buffer de visibilidade.
  • Profundidade:
    • Formato: Depth32F
    • D = EncodeAsFloat(InstanceIdx, GeometryIdx)
    • O identificador de material da interseção é codificado em ponto flutuante de 32 bits e gravado no buffer de profundidade para o próximo estágio da técnica de detecção de correspondência de codificação de profundidade do material.
Figura 6. Profundidade codificada.

Em comparação com o compute shader, a consulta de raios no shader de pixel tem as seguintes vantagens:

  • Integração de pipeline: o pipeline é incorporado diretamente aos pipelines de renderização direta/adiada, mantendo a continuidade do estado do pipeline de renderização.
  • Otimização de largura de banda para dispositivos móveis: para a arquitetura baseada em blocos de dispositivos móveis, a compactação sem perdas no chip pode ser acionada quando os dados de acerto de raio são gravados em RenderTarget, reduzindo o consumo de largura de banda de memória em comparação com a saída de sombreador de computação tradicional para buffer.
  • Controle de quantidade de raios: as áreas não refletivas podem ser marcadas e rejeitadas por meio de uma fase de pré-cálculo em combinação com um teste de stencil.

Resolver cartão

Na fase de coloração (consulte Refleções com ray tracing), a equipe do Diablo Immortal conseguiu fazer a correspondência rápida de identificação usando a unidade de hardware do teste de profundidade e realizando a coloração de materiais em lotes sucessivos.

Para cada material, um cartão de desenho em tela cheia é emitido. O sombreador de vértice reconstroi dinamicamente o identificador codificado do material atual. Usando o Depth Equal Test, o identificador é comparado aos valores codificados no buffer de profundidade, e apenas os pixels cujos valores codificados correspondem exatamente são mantidos, ou seja, aqueles pixels que pertencem à instância de material atual. Os pixels retidos executam o sombreador de material correspondente.

Em seguida, a reprodução de material de alta precisão é implementada no sombreador de pixel:

  • Decodificação de dados de geometria: extrai o identificador de triângulo (MeshID + PrimitiveID) e as coordenadas baricentrizadas do buffer de visibilidade e carrega dinamicamente os atributos de vértice (posição, UV, normal etc.) do triângulo correspondente do buffer de vértice. Como cada modelo é sombreado como um material independente, recursos avançados, como vinculação, não são necessários.
  • Reconstrução de parâmetro de superfície: calcula as coordenadas UV na interseção usando a interpolação de coordenadas baricentrônicas. A rasterização de software é realizada para amostrar o mapa com base nos UVs interpolados.
  • Reutilização do cálculo de sombreamento: reutiliza diretamente o código de sombreador para manter a mesma lógica de material do pipeline de renderização principal.
Figura 7. Reflexão resolvida.

Por fim, os modelos que realmente participam do cálculo de reflexão representam apenas uma parte muito pequena da cena. Os dados de identificação do modelo de reflexão retornados pela GPU podem ser lidos de forma assíncrona para eliminar os modelos/materiais que não participam da reflexão, reduzindo efictivamente o número de chamadas de renderização (uma chamada de renderização ocorre quando materiais e uma malha são enviados para a GPU para renderização) no estágio de sombreamento.

Reflexão especular baseada na física

Para conseguir reflexos de alta fidelidade, as superfícies refletivas são classificadas como um destes três tipos de acordo com a rugosidade:

  1. Sem reflexão: os cálculos de reflexão para essas superfícies podem ser ignorados para economizar recursos. Se a superfície for muito áspera, o reflexo ficará desfocado e fraco, e a contribuição não será óbvia.
  2. Reflexão de espelho: como um espelho liso, a imagem refletida é nítida e não desfocada. Aponte a linha diretamente na direção do reflexo da linha de visão.
  3. Reflexão brilhante: a reflexão com uma certa rugosidade da superfície é simulada com base na amostragem de importância GGX, que pode levar em conta a eficiência computacional e a precisão física. A reflexão se desvia para a direção principal da reflexão especular ao emitir a linha, o que melhora a eficiência de amostragem da área de destaque.

Para alcançar uma qualidade de imagem utilizável com consumo de energia limitado, a equipe do Diablo Immortal adotou uma solução 1SPP+Denoiser. Ou seja, a equipe do Diablo Immortal coletou uma amostra por pixel e, em seguida, um algoritmo de redução de ruído temporal/espacial foi usado para suavizar a grande quantidade de ruído introduzida pela taxa de amostragem baixa.

A equipe do Diablo Immortal escolheu o Reflection Denoiser no AMD FidelityFX Denoiser, um denoiser de alto desempenho otimizado para reflexões de ray tracing e reflexões no espaço da tela. A principal vantagem do Reflection Denoiser é o algoritmo de redução de ruído híbrido espaço-temporal: ao mesclar o frame atual e os dados históricos do frame (com base na compensação de movimento), combinados com técnicas de filtragem espacial (como a filtragem de retenção de borda guiada por variância), o Reflection Denoiser elimina o ruído de forma eficiente e gera efeitos de reflexão suaves com uma amostragem muito baixa.

Para se adaptar às características dos pipelines de renderização autodesenvolvidos e atender às restrições de desempenho rigorosas de dispositivos móveis, a equipe do Diablo Immortal implementou a simplificação e a adaptação da arquitetura ao integrar o AMD FidelityFX Reflection Denoiser.

Ray tracing de alta fidelidade com Vulkan

O Diablo Immortal é executado em uma ampla variedade de dispositivos Android com suporte ao Vulkan, em que a equipe do Diablo Immortal aproveitou os recursos inovadores de rastreamento de raios de hardware de GPU. O Vulkan reduziu a sobrecarga e a fricção do desenvolvimento, facilitando o envio de conteúdo e jogabilidade de alta qualidade do Diablo Immortal para usuários do Android.