Exposição local dinâmica

Olá Habr! Apresento a você a tradução do artigo “Exposição Local Dinâmica” de John Chapman.

imagem

Neste artigo, apresentarei algumas idéias sobre a exposição local dinâmica na renderização HDR. Bart Wronsky já tem um excelente artigo sobre esse assunto e eu recomendo a leitura imediata, se você ainda não o fez; as idéias aqui são, em maior medida, baseadas em seu artigo. No final, incluí alguns outros ótimos links.

Faixa dinâmica baixa / alta


Nos bons velhos tempos (anos 90), os jogos eram renderizados diretamente no formato LDR (faixa dinâmica estreita) exibido (espaço gama, 8 bits). Era simples e barato, mas, por outro lado, interferiu significativamente na criação de uma imagem verdadeiramente fotorrealista.

Atualmente, especialmente com o advento da PBR (renderização com base física), os jogos são renderizados com faixa dinâmica gigantesca no espaço linear com maior precisão. Com esse movimento, o verdadeiro problema vem do fotorrealismo: como podemos exibir uma imagem HDR no LDR ?

Exposição Auto Global


A abordagem padrão para o controle automático da exposição é medir o brilho médio (ou logarítmico médio) da cena, opcionalmente com uma função de peso que prefere valores próximos ao centro da imagem. Isso pode ser feito de maneira muito eficiente, usando redução paralela ou downsampling repetidamente no mapa mip do buffer de luminância . A última abordagem tem algumas vantagens, que discutirei na próxima seção.

O brilho médio é subsequentemente convertido para o valor da exposição, por exemplo, calculando o inverso do brilho máximo permitido da cena:

float Lavg = exp(textureLod(txLuminance, uv, 99.0).x); float ev100 = log2(Lavg * 100.0 / 12.5); ev100 -= uExposureCompensation; // optional manual bias float exposure = 1.0 / (1.2 * exp2(ev100)); 

Obtido do padrão ISO para calcular a velocidade com base na saturação; para obter uma explicação completa, consulte (3)

Como o brilho médio potencial é instável sob condições dinâmicas, geralmente é suavizado ao longo do tempo usando a função de histerese exponencial (2) :

 Lavg = Lavg + (Lnew - Lavg) * (1.0 - exp(uDeltaTime * -uRate)); 

Comentário do tradutor
Essa função precisa ser aplicada no brilho da textura de redução da amostra do shader e apenas durante o cálculo do último nível de mip (1x1). Além disso, será escrito sobre isso, mas, na minha opinião, é fácil ignorar.

Devido à sua natureza global, esse método sofre sombreamento intenso ou realces de áreas da imagem nas quais há um desvio do brilho médio:

imagem

Embora isso corresponda à capacidade do olho de se adaptar às mudanças nos níveis de luz, o efeito geral está muito longe do que realmente percebemos no mundo real.

AE local


Se gerarmos brilho médio com downsampling , teremos acesso a níveis mip mais baixos de buffer de luminância (4) para obter brilho médio local.

 float Lavg = exp(textureLod(txLuminance, uv, uLuminanceLod).x; 

Observe que, para que isso funcione, a histerese deve ser aplicada apenas na última etapa (ao gravar um nível mip 1x1), caso contrário, haverá artefatos.

Em teoria, é uma ótima idéia: cada área da imagem pode ter uma boa exposição, enquanto contrasta com as áreas vizinhas. No entanto, na prática, é obtido um resultado repugnante:

imagem

Os mais desagradáveis ​​são os halos de blocos encontrados em áreas com alto contraste:

imagem

No entanto, eles podem ser suavizados pré-filtrando o buffer de luminância ou simplesmente usando amostragem bicúbica:

imagem

Ainda parece nojento, mas já melhor.

A amostragem de diferentes níveis do mipmap na luminância altera o raio do halo. Este parâmetro é útil para controlar a “aparência” geral do resultado, bem como para minimizar o efeito halo, embora devido a uma diminuição geral no contraste (se torne um filtro de borda) ou a perda da localidade do controle de exposição:

imagem

Ainda, suavizar fantasmas não é suficiente. O resultado não é de todo natural; parece extremo estilo "foto HDR", diferente do que uma pessoa vê. No entanto, combinando valores globais e locais, podemos obter o melhor dos dois mundos:

 float Llocal = exp(textureLod(txLuminance, uv, uLuminanceLod).x; float Lglobal = exp(textureLod(txLuminance, uv, 99.0).x; float L = mix(Lglobal, Llocal, uLocalExposureRatio); // .. use L to compute the final exposure scale as before 

imagem

Alterando o fator de mistura, você pode ajustar a exposição local para, como resultado, minimizar artefatos e maximizar o realismo percebido:

imagem

Relação de mistura automática


O ajuste manual da taxa de mixagem é normal em situações em que temos controle absoluto da posição da câmera, iluminação, etc. No entanto, em muitos casos (por exemplo, jogos ao ar livre com uma mudança dinâmica de dia e noite), esse nível de controle simplesmente não é possível. Nesse caso, seria bom gerar o fator de mix automaticamente.

Na imagem abaixo, temos uma ampla faixa dinâmica; principalmente valores de brilho médio-baixo e várias áreas com alta intensidade (céu nas janelas):

imagem

Sem exposição local, a cor do céu é perdida. Nesse caso, eu gostaria de uma grande proporção de mistura :

imagem

Agora considere a imagem abaixo, que possui uma pequena faixa dinâmica, principalmente com um alto valor de brilho:

imagem

Nesse caso, a aplicação da exposição local reduz muito o brilho das áreas "brilhantes":

imagem

Os dados de observação sugeriram um método simples de misturar valores locais e globais : se a diferença entre o brilho médio e máximo da cena for maior, o coeficiente de mistura da exposição local deve ser maior. A geração do brilho máximo da cena pode ser feita trivialmente durante o cálculo do brilho, usando a histerese para suavizar o resultado da mesma maneira que para o valor médio. Portanto, podemos expandir o fragmento de código anterior da seguinte maneira:

 float Llocal = exp(textureLod(txLuminance, uv, uLuminanceLod).x; float Lglobal = exp(textureLod(txLuminance, uv, 99.0).x; // average in x float Lmax = exp(textureLod(txLuminance, uv, 99.0).y; // max in y float Lratio = min(saturate(abs(Lmax - Lglobal) / Lmax), uLocalExposureMax); float L = mix(Lglobal, Llocal, Lratio); // .. use L to compute the final exposure scale as before 

Observe que uLocalExposureMax apareceu em nossa entrada para controlar o grau máximo absoluto de influência da exposição local. Eu obtive um bom resultado uLocalExposureMax <0.3 .

Código final
 float Llocal = exp(textureLod(txLuminance, uv, uLuminanceLod).x; float Lglobal = exp(textureLod(txLuminance, uv, 99.0).x; // average in x float Lmax = exp(textureLod(txLuminance, uv, 99.0).y; // max in y float Lratio = min(saturate(abs(Lmax - Lglobal) / Lmax), uLocalExposureMax); float L = mix(Lglobal, Llocal, Lratio); float ev100 = log2(L * 100.0 / 12.5); ev100 -= uExposureCompensation; // optional manual bias float exposure = 1.0 / (1.2 * exp2(ev100)); vec3 result = hdrColor * exposure; result += bloom; //etc outColor.rgb = result; 


Conclusão


A abordagem descrita acima impõe algumas limitações sobre quando é necessário medir o brilho de uma cena. Normalmente, a medição é realizada imediatamente após a passagem da iluminação para evitar a adaptação dos efeitos das partículas , bloom , etc. No entanto, quando o brilho local é usado, é importante que o valor real que participa da exposição seja apresentado no mapa de luminância . Isso significa que uma medição de brilho precisa ser feita imediatamente antes de aplicar a exposição. Se isso for inaceitável, a solução é gerar o brilho local separadamente dos valores médio e máximo.

Embora eu ache que usar o brilho local e global da cena juntos seja a abordagem "certa" para criar uma imagem equilibrada e com aparência natural, a qualidade do resultado é obviamente subjetiva. A adequação desse método a um jogo em particular depende inteiramente do conteúdo e do estilo visual desejado. Eu estaria interessado em ouvir outras idéias a esse respeito.

Referências


  1. Mapeamento de tom localizado (Bart Wronski)
  2. Implementando uma Câmera com Base Física (Padraic Hennessy)
  3. Movendo Frostbite para PBR (Sébastien Lagarde, et al.)
  4. Um olhar mais atento sobre o mapeamento de tons (Matt Pettineo)
  5. A importância de ser linear (Larry Gritz, et al.)
  6. Técnicas avançadas e otimização de dutos de cores HDR / VDR (Timothy Lottes)

Imagens HDR tiradas do sIBL Archive .

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


All Articles