Como a renderização de jogos em 3D funciona: iluminação e sombras

A implementação da grande maioria dos efeitos visuais nos jogos modernos depende do uso criterioso de iluminação e sombras. Sem eles, os jogos seriam chatos e sem vida. Na quarta parte da análise da renderização de jogos 3D, focaremos no que está acontecendo no mundo 3D, juntamente com o processamento de vértices e o mapeamento de texturas. Mais uma vez, precisaremos de muita matemática, além de um sólido entendimento dos conceitos básicos da óptica.

Parte 1: processamento de vértices

Parte 2: rasterização e rastreamento de raios

Parte 3: texturização e filtragem de texturas

Lembre-se do passado


Anteriormente, examinamos os principais aspectos do movimento e processamento de objetos em cenas, sua conversão do espaço tridimensional em uma grade plana de pixels, bem como maneiras de sobrepor texturas nesses objetos. Por muitos anos, essas operações foram uma parte essencial do processo de renderização, e podemos ver isso retornando em 1993 e lançando o Doom da id Software.


Pelos padrões modernos, o uso de luz e sombra nesse jogo era muito primitivo: as fontes de luz não eram levadas em consideração, cada superfície com base em seus vértices recebia um valor geral de cor ou o valor da luz ambiente . Todos os sinais de sombras foram criados graças ao uso astuto de texturas e à escolha da cor do ambiente.

Não havia sombras porque não eram tarefa dos programadores: o PC da época era um processador de 66 MHz (ou seja, 0,066 GHz!), Um disco rígido de 40 MB e uma placa gráfica de 512 kilobytes com recursos 3D mínimos. Avanço rápido 23: na famosa reinicialização da série, vemos uma história completamente diferente.


Muitas tecnologias foram usadas para renderizar esse quadro , que possui estágios como oclusão ambiental do espaço na tela, mapeamento de profundidade antes da passagem, filtros de desfoque bokeh, operadores de correção de tom e assim por diante. O cálculo da iluminação e do sombreamento de cada superfície é realizado dinamicamente: eles mudam constantemente, dependendo das condições ambientais e das ações do jogador.

Como qualquer operação de renderização em 3D exige matemática (um monte de cálculos!), É melhor começarmos com o que acontece nos bastidores de qualquer jogo moderno.

Iluminação matemática


Para implementar tudo corretamente, precisamos simular com precisão o comportamento da luz ao interagir com várias superfícies. É curioso que, pela primeira vez, esse problema tenha sido resolvido no século 18 por um homem chamado Johann Heinrich Lambert.

Em 1760, um cientista suíço lançou um livro chamado Photometria . Nele, ele descreveu as regras fundamentais do comportamento da luz; o mais notável deles foi o seguinte - a superfície emite luz (por reflexão ou como fonte de luz) de modo que o brilho da luz emitida varie dependendo do cosseno do ângulo entre a superfície normal e o observador.


Esta regra simples lançou as bases para a chamada iluminação difusa . Este é um modelo matemático usado para calcular a cor de uma superfície, dependendo de suas propriedades físicas (por exemplo, sua cor e grau de reflexão da luz) e a localização da fonte de luz.

Na renderização em 3D, isso requer muita informação, o que é mais fácil de imaginar na forma de um esquema desse tipo:


Vemos muitas setas na imagem, esses são vetores e os seguintes vetores são necessários para calcular a cor:

  • 3 vetores para posição de vértice, fonte de luz e câmera olhando a cena
  • 2 vetores para as direções da fonte de luz e da câmera do ponto de vista do vértice
  • 1 vetor normal
  • 1 meio vetor (está sempre no meio entre os vetores de direção da iluminação e da câmera)

Eles são calculados no estágio de processamento dos vértices do processo de renderização e a equação que une todos eles (chamada de modelo de Lambert) tem a forma:


Ou seja, a cor do vértice sob iluminação difusa é calculada multiplicando a cor da superfície, a cor da fonte de luz e o produto escalar dos vetores normais do vértice e a direção da luz com os coeficientes de atenuação e projeção. Esta operação é realizada para cada fonte de luz na cena, daí o símbolo da soma no início da equação.

Os vetores nesta equação (e tudo o que vemos abaixo) são normalizados (como mostrado pelos ícones acima de cada vetor). O vetor normalizado mantém sua direção original e seu comprimento diminui para um valor unitário (ou seja, igual a 1 unidade de medida).

Os valores de cor da superfície e da fonte de luz são números RGBA padrão (vermelho, verde, azul e transparência alfa). Eles podem ser inteiros (por exemplo, INT8 para cada canal de cores), mas quase sempre são números de ponto flutuante (por exemplo, FP32). O coeficiente de atenuação determina como o nível de iluminação diminui ao se afastar da fonte e é calculado por outra equação:


Os termos A C , A L e A Q são coeficientes diferentes (constante, linear, quadrático) que descrevem como a distância afeta o nível de iluminação. Todos eles são definidos pelos programadores ao criar um mecanismo de renderização. Em cada API gráfica, isso é implementado à sua maneira, mas coeficientes são introduzidos ao codificar o tipo de fonte de luz.

Antes de considerarmos o último coeficiente (floodlight), é importante notar que na renderização em 3D existem essencialmente três tipos de fontes de luz: ponto, direcional e spotlight.


As fontes pontuais emitem luz uniformemente em todas as direções, e as fontes direcionais emitem luz em apenas uma direção (do ponto de vista da matemática, essa é apenas uma fonte pontual, remota a uma distância infinita). Os holofotes são fontes direcionais complexas, pois emitem luz na forma de um cone. A maneira como a luz varia no corpo do cone determina o tamanho das partes interna e externa do cone.

E sim, para o coeficiente do holofote, há outra equação:


O valor do coeficiente do projetor é 1 (ou seja, a fonte não é um projetor) ou 0 (se o vértice estiver fora da direção do cone) ou algum valor calculado entre os dois. Os ângulos φ (phi) e θ (theta) especificam as dimensões da parte interna / externa do cone do refletor.

Dois vetores: L dcs e L dir (inverso à direção da câmera e à direção do foco) são usados ​​para determinar se o cone do vértice está tocando.

Agora devemos lembrar que tudo isso é necessário para calcular o valor da iluminação difusa, e todas essas operações devem ser realizadas para cadaa fonte de iluminação na cena ou pelo menos para cada fonte que o programador desejasse considerar. Muitas dessas equações são executadas por APIs gráficas, mas também podem ser feitas manualmente se os codificadores precisarem de mais controle sobre a imagem.

No entanto, no mundo real, de fato, há um número infinito de fontes de luz: cada superfície reflete a iluminação; portanto, todas elas afetam a iluminação geral da cena. Mesmo à noite, há iluminação de fundo, seja estrelas e planetas ou luz espalhada na atmosfera.

Para simular isso, outro valor de iluminação é calculado: iluminação ambiente .


Essa equação é mais simples do que para iluminação difusa, porque as direções não são necessárias. Aqui, é realizada uma multiplicação simples de vários coeficientes:

  • C SA - cor da iluminação da superfície
  • C GA - destaque a cor da cena 3D global
  • C LA - cor da iluminação de todas as fontes de luz na cena

Vale a pena notar que a atenuação e os coeficientes do projetor são novamente utilizados, bem como a soma de todas as fontes de luz.

Portanto, temos iluminação de fundo e levamos em conta a iluminação difusa de fontes de luz de várias superfícies do mundo 3D. Mas o modelo Lambert funciona apenas para materiais que refletem a iluminação de sua superfície em todas as direções; objetos feitos de vidro ou metal criam outro tipo de reflexão chamado especular ; Naturalmente, há uma equação para ele também!


As partes individuais desta fórmula já devem lhe ser familiares: temos dois valores da cor do espelho (um para a superfície - C S , o outro para a luz - C LS ), bem como os fatores usuais de atenuação e inundação.

Como a reflexão especular é muito focada e direcionada, dois vetores são usados ​​para determinar o brilho da iluminação especular: o vértice normal e o semi-vetor. O coeficiente p é chamado de poder da reflexão especular ; é um número que determina o brilho da reflexão, dependendo das propriedades do material da superfície. À medida que p aumenta, o efeito de espelho se torna mais brilhante, mas mais focado e menor.

O último elemento a ser considerado é o mais simples, porque é apenas um número. Chama-se iluminação emissiva e é aplicada a objetos que são uma fonte direta de iluminação, ou seja, a uma chama, uma lanterna ou o sol.

Isso significa que agora temos um número e três conjuntos de equações para calcular a cor do vértice da superfície, levando em consideração a iluminação de fundo (ambiente), bem como a interação entre diferentes fontes de luz e as propriedades do material da superfície (difusa e especular). Os programadores podem escolher apenas um ou combinar os quatro simplesmente dobrando-os.


Visualmente, a combinação fica assim:


As equações consideradas por nós são aplicadas por APIs gráficas (por exemplo, Direct3D e OpenGL) usando suas funções padrão, mas para cada tipo de iluminação existem algoritmos alternativos. Por exemplo, a iluminação difusa pode ser implementada usando o modelo Oren-Nayyar , que é mais adequado para superfícies muito rugosas do que o modelo Lambert.

A equação de reflexão de espelho pode ser substituída por modelos que levam em consideração o fato de que superfícies muito lisas, como vidro ou metal, ainda são ásperas, mas em um nível microscópico. Tais modelos, chamados algoritmos de micro faceta , à custa da complexidade matemática, fornecem imagens mais realistas.

Qualquer que seja o modelo usado, todos eles são bastante aprimorados ao aumentar a frequência de sua aplicação na cena 3D.

Cálculos de vértice ou pixel por pixel


Quando examinamos o processamento e a rasterização de vértices , vimos que os resultados de todos os cálculos complicados de iluminação realizados para cada vértice deveriam ser interpolados sobre a superfície entre os vértices. Isso ocorre porque as propriedades associadas ao material da superfície são armazenadas dentro dos vértices; quando o mundo 3D é compactado em uma grade de pixels 2D, os pixels permanecem apenas onde estava o vértice.


O restante dos pixels precisa transmitir informações sobre a cor dos vértices, para que as cores se misturem corretamente na superfície. Em 1971, Henri Gouraud , então estudante de pós-graduação da Universidade de Utah, propôs um método agora chamado Gouraud Shading .

Seu método era computacionalmente rápido e por muitos anos se tornou o padrão de fato , mas ele também teve problemas. Ele não conseguia interpolar corretamente a iluminação do espelho e, se o objeto era composto por um pequeno número de primitivas, a mistura entre as primitivas parecia errônea.

Uma solução para esse problema foi proposta em 1973 por Bui Tyong Fong, que também trabalhou na Universidade de Utah. Em seu artigo de pesquisa, Fong demonstrou uma técnica para interpolar as normais dos vértices em superfícies rasterizadas. Isso significava que os modelos dispersos e especulares funcionariam corretamente para cada pixel e podemos ver isso claramente nos gráficos on-line de computador de David Eck e no tutorial WebGL.

As esferas de carbono mostradas abaixo são coloridas com o mesmo modelo de iluminação, mas os cálculos com a mão esquerda são executados verticalmente, seguidos pelo sombreamento de Gouraud para interpolá-las por toda a superfície. Para a esfera à direita, os cálculos são feitos pixel por pixel, e a diferença é óbvia.


As imagens estáticas não transmitem todas as melhorias trazidas pelo sombreamento em relação a Phong , mas você pode executar independentemente a demo on - line do Ek e assistir à animação.

No entanto, Fong não parou por aí e, alguns anos depois, publicou outro artigo de pesquisa no qual mostrava como cálculos separados para reflexão ambiental, difusa e especular podem ser realizados com uma simples equação:


Aqui temos que entender seriamente! Os valores indicados pela letra k são as constantes de reflexão para as reflexões ambiente, difusa e especular. Cada um deles é uma fração do tipo correspondente de luz refletida a partir da magnitude da luz incidente; Valores de C que vimos nas equações acima (valores de cores do material da superfície para cada tipo de iluminação).

O vetor R é o vetor de "reflexão perfeita" - a direção na qual a luz refletida se moveria se a superfície fosse perfeitamente lisa; é calculado usando a superfície normal e o vetor de luz incidente. O vetor C é o vetor de direção da câmera; e R e C são normalizados.

Finalmente, existe a última constante na equação: o valor de α determina o grau de brilho da superfície. Quanto mais suave o material (ou seja, quanto mais se assemelha a vidro ou metal), maior o número.

Essa equação é geralmente chamada de modelo de reflexão de Phong . No momento de sua pesquisa, essa proposta era radical, porque exigia recursos computacionais sérios. Uma versão simplificada do modelo foi criada por Jim Blinn , substituindo a parte da fórmula de R e C para H e N (vetor de meia distância e superfície normal). O valor de R deve ser calculado para cada fonte de luz e para cada pixel no quadro, eH é suficiente para calcular uma vez para cada fonte e para toda a cena. Hoje, o

modelo de reflexão Blinn-Fong é o sistema de iluminação padrão e é usado por padrão no Direct3D, OpenGL, Vulkan, etc.

Existem muitos outros modelos matemáticos, especialmente agora que as GPUs podem processar pixels em shaders longos e complexos; juntas, essas fórmulas são chamadas de funções bidirecionais de refletância / distribuição de transmissão (BRDF / BTFD); eles são a base para colorir todos os pixels no monitor quando jogamos jogos 3D modernos.

No entanto, até agora consideramos apenas superfícies refletindo a luz: materiais translúcidos transmitem luz, enquanto os raios de luz são refratados. E algumas superfícies. por exemplo, a água reflete e transmite luz em graus variados.

Levamos a iluminação a um novo nível


Vamos dar uma olhada no jogo Ubisoft Assassin's Creed: Odyssey 2018 , no qual o jogador costuma navegar na água, tanto em rios rasos quanto no fundo do mar.


Madeira pintada, metal, cordas, tecido e água - tudo isso reflete e refrata a luz usando vários cálculos.Para

a renderização mais realista da água, mantendo uma velocidade suficiente do jogo, os programadores da Ubisoft usaram todo um conjunto de truques. A superfície da água é iluminada pelo trio familiar de luz ambiente, difusa e especular, mas elas são complementadas por características interessantes.

O primeiro deles é frequentemente usado para gerar as propriedades refletivas da água - são reflexões do espaço da tela (SSR). Essa técnica renderiza a cena, mas as cores dos pixels dependem da profundidade de cada pixel, ou seja, da distância dele até a câmera. A profundidade é armazenada no chamado buffer de profundidade. Em seguida, o quadro é renderizado novamente com toda a iluminação e textura usuais, mas a cena é salva como textura de renderização e não como um buffer pronto que é transmitido ao monitor.

Depois disso, a marcha dos raios é realizada . Para isso, os raios são emitidos pela câmera e as distâncias são definidas ao longo do curso do feixe. O código verifica a profundidade do feixe em relação aos pixels no buffer de profundidade. Se eles tiverem o mesmo valor, o código verifica o pixel normal para ver se ele é direcionado para a câmera e, se houver, o mecanismo procura o pixel correspondente na textura de renderização. Em seguida, outro conjunto de instruções inverte a posição do pixel para que ele seja refletido corretamente na cena.


A ordem SSR usada no mecanismo Frostbite da EA.

Além disso, a luz é dispersa durante o movimento dentro dos materiais e, para materiais como água ou couro, outro truque chamado de dispersão sub-superficial (SSS) é usado. Não o explicaremos em detalhes, mas você pode ler como é usado para criar resultados surpreendentes na apresentação da Nvidia de 2014 .


Demonstração de 2013 do FaceWorks da Nvidia ( link )

Vamos voltar à água de Assassin's Creed: a implementação do SSS é quase imperceptível aqui e, devido a razões de velocidade, não é muito usada. Nos jogos anteriores da série AC, a Ubisoft usava SSS falso , mas no último jogo seu uso é mais complicado, mas ainda não é tão grande quanto vimos na demo da Nvidia.

Para alterar os valores de iluminação na superfície da água, são executados procedimentos adicionais que simulam corretamente os efeitos da profundidade devido a uma alteração na transparência, dependendo da distância da costa. E quando a câmera olha para a água perto da costa, ainda mais algoritmos são usados ​​para levar em consideração cáusticos e refração.

Os resultados são impressionantes:


Assassin's Creed: Odyssey - renderizando água em toda a sua glória.

Vimos a água, mas e o movimento da luz no ar? Partículas de poeira, umidade e outros elementos também levam à dispersão da luz. Como resultado, os raios de luz recebem volume e não permanecem apenas um conjunto de raios diretos.

O tópico da iluminação volumétrica pode ser estendido para uma dúzia de artigos, portanto, falaremos sobre como o jogo Rise of the Tomb Raider lida com ele . No vídeo abaixo, há apenas uma fonte principal de iluminação - o sol brilhando através da abertura do prédio.


Para criar um volume de luz, o mecanismo de jogo pega a pirâmide de visibilidade da câmera (veja abaixo) e a divide exponencialmente em 64 partes. Em seguida, cada fatia é rasterizada em grades com um tamanho de 160 x 94 elementos e todos esses dados são salvos na textura de renderização tridimensional do formato FP32. Como as texturas geralmente são bidimensionais, os "pixels" do volume da pirâmide são chamados voxels .


Para um bloco de 4 x 4 x 4 voxel, os sombreadores computacionais determinam quais fontes de luz ativas afetam esse volume e depois gravam essas informações em outra textura de renderização tridimensional. Então, para estimar a "densidade" total da luz dentro do bloco de voxel, é usada uma fórmula complexa chamada função de espalhamento de Hengy-Greenstein .

Em seguida, o mecanismo executa vários outros shaders para refinar os dados, após o que a marcha dos raios é realizada ao longo das fatias da pirâmide com o acúmulo de valores de densidade de luz. A Eidos-Montréal afirma que no Xbox One todas essas operações levam aproximadamente 0,8 milissegundos!

Embora essa técnica não seja usada em todos os jogos, os jogadores esperam ver uma cobertura volumétrica em quase todos os jogos 3D populares lançados hoje, especialmente em jogos de tiro em primeira pessoa e jogos de ação e aventura.


A iluminação volumétrica usada na sequela de Rise of the Tomb Raider de 2018.

Inicialmente, essa técnica de iluminação era chamada de "raios divinos" ou, como são chamados em termos científicos, "raios crepusculares" . Um dos primeiros jogos em que foi usado foi o primeiro Crysis da Crytek, lançado em 2007.

No entanto, essa não era a verdadeira iluminação volumétrica - o processo incluía a renderização inicial da cena na forma de um buffer de profundidade, que era usado como uma máscara - outro buffer no qual as cores dos pixels ficavam mais escuras quanto mais próximas da câmera.

Esse buffer de máscara foi amostrado várias vezes e o shader coletou amostras e as misturou desfocando juntas. O resultado desta operação foi misturado com a cena final:


O progresso das placas gráficas nos últimos 12 anos foi tremendo. As GPUs mais poderosas na época do lançamento do Crysis eram a Nvidia GeForce 8800 Ultra . A GPU mais rápida e moderna - a GeForce RTX 2080 Ti tem mais de 30 vezes mais poder de computação, 14 vezes mais memória e 6 vezes mais largura de banda.

Com todo esse poder computacional, os jogos modernos podem fornecer muito mais precisão gráfica e velocidade geral, apesar da maior complexidade da renderização.


“Raios Divinos” em The Division 2 da Ubisoft

Mas, na verdade, esse efeito demonstra que, apesar da importância da iluminação correta para a precisão visual, a ausência de luz é realmente ainda mais importante .

Essência da sombra


Vamos começar uma nova seção do artigo com o jogo Shadow of the Tomb Raider . Na imagem abaixo, todas as opções gráficas relacionadas às sombras estão desativadas; à direita, eles estão incluídos. A diferença é enorme, certo?


Como as sombras se formam naturalmente no mundo real, os jogos nos quais são implementadas incorretamente nunca parecerão corretos. Nossos cérebros estão acostumados a usar sombras como suporte visual para criar uma sensação de profundidade, localização e movimento relativos. Mas fazê-lo em um jogo em 3D é surpreendentemente difícil, ou pelo menos difícil, fazer certo.

Vamos começar com o pato. Aqui ela está se movendo pelo campo, e os raios do sol a alcançam e estão corretamente bloqueados.


Uma das primeiras maneiras de implementar a sombra na cena foi adicionar uma sombra "pontual" sob o modelo. Isso é completamente irreal, porque a forma da sombra não corresponde à forma do objeto que a projeta; no entanto, essa abordagem é rápida e fácil de criar.

Os primeiros jogos em 3D, por exemplo, o primeiro Tomb Raider de 1996, usaram esse método porque o hardware da época, por exemplo, Sega Saturn e Sony PlayStation, não podia oferecer nada melhor. Esse método pintou um conjunto simples de primitivas logo acima da superfície em que o modelo se move e as sombreava; desenho na parte inferior de uma textura simples também foi usado.


Outro dos primeiros métodos foi projetar sombras . Nesse caso, a primitiva que emite uma sombra foi projetada em um plano que contém o piso. Parte dos cálculos matemáticos necessários para isso foi criada por Jim Blinn no final dos anos 80. Padrões modernos, esse é um processo simples e funciona melhor para objetos estáticos simples.


Mas, graças à otimização, a projeção de sombra forneceu a criação dos primeiros exemplos dignos de sombras dinâmicas, por exemplo, no jogo de 1999 Kingpin: Life of Crime by Interplay. Como podemos ver na imagem abaixo, apenas personagens animados (até ratos!) Têm sombras, mas isso é melhor do que pontos simples.


Os problemas mais sérios com essa abordagem são: (a) a perfeita opacidade da sombra e (b) o método de projeção emite a sombra em uma superfície plana (por exemplo, no solo).

Esses problemas podem ser resolvidos aplicando uma parcela de transparência ao colorir a primitiva projetada e executar várias projeções para cada personagem, mas os recursos de hardware para PC do final dos anos 90 não conseguiam lidar com a renderização adicional.

Tecnologia moderna para criar sombras


Uma maneira mais precisa de implementar sombras foi proposta muito antes, já em 1977. Enquanto trabalhava na Universidade de Austin (Texas), Franklin Crowe escreveu um artigo de pesquisa no qual ele propôs várias técnicas usando volumes de sombra.

Em termos gerais, eles podem ser descritos da seguinte forma: o processo determina quais primitivas são direcionadas para a fonte de luz; suas costelas estão esticadas até um avião. Embora isso seja muito semelhante à projeção de sombras, a diferença importante é que o volume criado de sombras é usado para verificar se o pixel está dentro / fora do volume. Graças a essas informações, sombras podem ser emitidas em todas as superfícies, não apenas no chão.

Essa técnica foi aprimorada em 1991 por Tim Heidmann, que trabalhou emGráficos de silicone . Mark Kilgard se envolveu em seu desenvolvimento adicional em 1999 , e o método que consideraremos foi criado em 2000 por John Carmack, da id Software (embora o método de Carmack tenha sido aberto independentemente dois anos antes por Bilodo e Songa, da Creative Labs; isso levou a que Carmack foi forçado a mudar seu código para evitar problemas legais).

Essa abordagem requer renderização de vários quadros (chamada renderização multipass - um processo muito caro no início dos anos 90 que é usado em toda parte hoje) e um conceito chamado buffer de estêncil .

Ao contrário dos buffers de frame e profundidades, não é criado pela cena 3D si - este tampão é uma matriz de valores iguais em todas as dimensões (isto é resolução em x e y ) sob a forma de uma quadrícula. Os valores armazenados nele são usados ​​para informar ao mecanismo de renderização o que fazer com cada pixel no buffer do quadro.

O exemplo mais simples de usar esse buffer é usar como uma máscara:


O método com o volume de sombras é realizado aproximadamente da seguinte maneira:

  • Renderizamos a cena no buffer de quadro, mas usamos apenas a iluminação ambiente (também incluímos todos os valores de emissão se o pixel contiver uma fonte de luz)
  • , , ( (back-face culling)). (, ) . (.. «») - .
  • , (front-face culling) -, .
  • , , -.

Esses buffers de estêncil e volumes de sombra (comumente chamados sombras de estêncil) foram usados ​​no jogo Doom 3 id Software de 2004 :


Observe que a superfície em que o personagem está caminhando ainda é visível através da sombra? Esta é a primeira vantagem sobre a projeção de sombra. Além disso, essa abordagem permite levar em consideração a distância da fonte de luz (como resultado, sombras mais fracas são obtidas) e projetar sombras em qualquer superfície (incluindo o próprio personagem).

Mas essa técnica tem sérias desvantagens, a mais notável delas é que as bordas da sombra são completamente dependentes do número de primitivas usadas para criar o objeto que projeta a sombra. Além disso, a passagem múltipla está associada a muitas operações de leitura / gravação na memória local, e é por isso que o uso de sombras de estêncil é bastante caro em termos de desempenho.

Além disso, há um limite no número de volumes de sombra, que pode ser verificado usando o buffer de estêncil, porque todas as APIs gráficas alocam nele um número bastante pequeno de bits (geralmente apenas 8). No entanto, devido ao custo computacional das sombras do estêncil, esse problema geralmente não surge.

Há outro problema - as próprias sombras estão longe de serem realistas. Por quê? Como todas as fontes de luz - lâmpadas, chamas abertas, lanternas e o Sol - não são pontos únicos no espaço, ou seja, eles emitem luz de alguma área. Mesmo no caso mais simples mostrado abaixo, as sombras reais raramente têm arestas bem definidas.


A região mais escura das sombras é chamada de sombra total (umbra); A penumbra é sempre uma sombra mais clara, e a borda entre as duas é frequentemente borrada (porque geralmente existem muitas fontes de luz). É difícil modelar isso com buffers e volumes de estêncil, pois as sombras criadas são armazenadas em uma forma incorreta para que possam ser processadas. O mapeamento de sombras vem em socorro !

O procedimento básico foi desenvolvido em 1978 por Lance Williams . É bem simples:

  • Para cada fonte de luz, renderizamos a cena do ponto de vista dessa fonte, criando uma textura especial das profundidades (ou seja, sem cor, iluminação, textura, etc.). A resolução desse buffer não precisa ser igual ao tamanho do quadro final, mas quanto maior, melhor.
  • , ( x,y z) , .
  • : , .

Obviamente, esse é outro procedimento de várias passagens, mas a última etapa pode ser executada usando sombreadores de pixel, para que a verificação de profundidade e os cálculos de iluminação subsequentes sejam combinados em uma única passagem. E como todo o processo de criação de sombras não depende do número de primitivas usadas, é muito mais rápido do que usar o buffer de estêncil e o volume de sombras.

Infelizmente, a técnica básica descrita acima gera todos os tipos de artefatos visuais (por exemplo, alias de perspectiva , "acne sombria" , "peter panning"), muitos dos quais relacionados à resolução e tamanho de bit da textura de profundidade. Todas as GPUs e APIs gráficas têm limitações semelhantes às texturas; portanto, um conjunto inteiro de técnicas adicionais foi criado para resolver esses problemas.

Um dos benefícios do uso de texturas para obter informações detalhadas é que as GPUs podem amostrá-las e filtrá-las muito rapidamente e de várias maneiras diferentes. Em 2005, a Nvidia demonstrou um método de amostragem de textura que poderia resolver alguns dos problemas visuais causados ​​pelo sombreamento padrão. Além disso, ele proporcionou um certo grau de suavidade nas bordas das sombras; Essa técnica é chamada de filtragem mais próxima da porcentagem .


Na mesma época, a Futuremark demonstrou o uso de mapas de sombra em cascata (CSM) no 3DMark06 . Esta é uma técnica na qual para cada fonte de luz são criadas várias texturas de profundidade com diferentes resoluções. Texturas de alta resolução são usadas perto da fonte e inferiores - a uma distância da fonte. O resultado são transições de sombra mais suaves na cena sem distorção.

Essa técnica foi aprimorada por Donnelly e Loritzen em 2006 em seu procedimento de mapeamento de sombra de variância (VSM), bem como pela Intel em 2010 em seu algoritmo de distribuição de amostra (SDSM).


Usando o SDSM no Shadow of the Tomb Raider

Para melhorar a imagem, os desenvolvedores de jogos geralmente usam todo um arsenal de técnicas de sombreamento, mas a principal delas continua sendo o mapeamento de sombras. No entanto, ele pode ser aplicado apenas a um pequeno número de fontes de luz ativas, porque se você tentar modelá-lo para cada superfície que reflita ou emita luz, a taxa de quadros cairá catastroficamente.

Felizmente, existe uma técnica conveniente que funciona com qualquer objeto. Dá a impressão de uma diminuição no brilho da iluminação atingindo o objeto (devido ao fato de ele ou outros objetos bloquearem um pouco a luz). Esse recurso é chamado de oclusão ambiental.e ela tem muitas versões. Alguns deles são especialmente projetados por fabricantes de hardware, por exemplo, a AMD criou o HDAO ( oclusão ambiental de alta definição ) e a Nvidia possui HBAO + ( oclusão ambiental baseada no horizonte ).

Qualquer que seja a versão usada, ela é aplicada após a cena ser totalmente renderizada, portanto, é classificada como um efeito de pós-processamento . De fato, para cada pixel é calculado o quanto a vemos na cena (mais sobre isso aqui e aqui ) comparando o valor da profundidade do pixel com os pixels ao redor no ponto correspondente no buffer de profundidade (que, novamente, é armazenado como textura).

A amostragem do buffer de profundidade e o cálculo da cor final do pixel desempenham um papel importante para garantir a qualidade da oclusão do ambiente; como no caso de sombreamento, todas as versões de oclusão ambiental para sua operação adequada exigem que o programador configure e ajuste cuidadosamente o código, dependendo da situação.


Shadow of the Tomb Raider sem AO (esquerda) e com HBAO + (direita)

No entanto, quando implementado adequadamente, esse efeito visual deixa uma impressão profunda. Na imagem acima, preste atenção nas mãos, abacaxis e bananas da pessoa, bem como na grama e vegetação circundantes. As alterações de cor do HBAO + pixel são bem menores, mas agora todos os objetos parecem melhor incorporados ao ambiente (à esquerda, parece que uma pessoa está pendurada acima do solo).

Se você selecionar qualquer um dos últimos jogos discutidos neste artigo, a lista de técnicas de renderização usadas neles ao processar iluminação e sombras terá o comprimento do próprio artigo. E embora nem todos os novos jogos em 3D possuam todas essas tecnologias, os mecanismos universais de jogos como o Unreal permitem que você os habilite opcionalmente, e os kits de ferramentas (por exemplo, empresas da Nvidia) fornecem um código pronto para ser inserido no jogo. Isso prova que eles não são métodos ultramodernos altamente especializados - que eram de propriedade dos melhores programadores, agora estão disponíveis para qualquer pessoa.

Não podemos concluir este artigo sobre iluminação e sombras sem mencionar o traçado de raios. Já falamos sobre esse processo nesta série de artigos, mas o nível atual de desenvolvimento de tecnologiarequer tolerar uma taxa de quadros baixa e despesas graves em dinheiro.

No entanto, a tecnologia é suportada pelos consoles de próxima geração Microsoft e Sony, o que significa que, nos próximos anos, seu uso se tornará outra ferramenta padrão para desenvolvedores de todo o mundo que buscam melhorar a qualidade visual dos jogos. Basta dar uma olhada no que Remedy conseguiu alcançar em seu último jogo de Controle :


Percorremos um longo caminho desde sombras falsas em texturas e iluminação ambiente simples!

Isso não é tudo


No artigo, tentamos falar sobre os cálculos e técnicas matemáticas fundamentais usados ​​nos jogos 3D, que os tornam o mais realista possível. Também examinamos as tecnologias subjacentes à modelagem da interação da luz com objetos e materiais. Mas tudo isso foi apenas a ponta do iceberg.

Por exemplo, pulamos tópicos como iluminação de economia de energia, reflexo de lente, floração, renderização altamente dinâmica, transferência de brilho, correção de tom, neblina, aberração cromática, mapeamento de fótons, cáusticos, radiosidade - esta lista continua. Um breve estudo exigiria mais 3-4 artigos.

All Articles