Exposición local dinámica

Hola Habr! Les presento la traducción del artículo "Exposición local dinámica" de John Chapman.

imagen

En este artículo, presentaré un par de ideas sobre la exposición dinámica local en el renderizado HDR. Bart Wronsky ya tiene un excelente artículo sobre este tema y le recomiendo leerlo de inmediato si aún no lo ha hecho; Las ideas aquí se basan, en mayor medida, en su artículo. Al final, incluí algunos otros excelentes enlaces.

Rango dinámico bajo / alto


En los viejos tiempos (1990), los juegos se representaban directamente en el formato LDR (rango dinámico estrecho) mostrado (espacio gamma, 8 bits). Era simple y barato, pero, por otro lado, interfirió significativamente con la creación de una imagen verdaderamente fotorrealista.

Actualmente, especialmente con el advenimiento de PBR (renderizado basado en la física), los juegos se representan con un rango dinámico gigantesco en el espacio lineal con mayor precisión. Con este movimiento, el verdadero problema llega al fotorrealismo: ¿cómo podemos mostrar una imagen HDR en LDR ?

Exposición global a automóviles


El enfoque estándar para el control de exposición automático es medir el brillo promedio (o promedio logarítmico) de la escena, opcionalmente con una función de peso que prefiere valores cercanos al centro de la imagen. Esto se puede hacer de manera muy eficiente mediante la reducción paralela o disminuyendo la resolución repetidamente en el mapa MIP del búfer de luminancia . El último enfoque tiene algunas ventajas, que discutiré en la siguiente sección.

El brillo promedio se convierte posteriormente en el valor de exposición, por ejemplo, calculando el recíproco del brillo máximo permitido de la escena:

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)); 

Obtenido del estándar ISO para calcular la velocidad en función de la saturación; para una explicación completa, ver (3)

Dado que el brillo promedio potencial es inestable en condiciones dinámicas, generalmente se suaviza con el tiempo utilizando la función de histéresis exponencial (2) :

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

Comentario del traductor
Esta función debe aplicarse en el brillo de la textura de reducción de muestreo del sombreador y solo durante el cálculo del último nivel de mip (1x1). Además se escribirá sobre esto, pero en mi opinión es fácil pasarlo por alto.

Debido a su naturaleza global, este método adolece de sombras o reflejos severos en áreas de la imagen en las que hay una desviación del brillo promedio:

imagen

Aunque esto corresponde a la capacidad del ojo para adaptarse a los cambios en los niveles de luz, el efecto general está bastante lejos de lo que realmente percibimos en el mundo real.

AE local


Si generamos un brillo medio con disminución de muestreo , tenemos acceso a niveles de mip más bajos del buffer de luminancia (4) para obtener un brillo promedio local.

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

Tenga en cuenta que para que esto funcione, la histéresis debe aplicarse solo en el último paso (al grabar un nivel de mip 1x1), de lo contrario habrá artefactos.

En teoría, esta es una gran idea: cada área de la imagen puede tener una buena exposición, a la vez que contrasta con las áreas vecinas. Sin embargo, en la práctica, se obtiene un resultado desagradable:

imagen

Los más desagradables son los "halos" de bloque que se encuentran en áreas con alto contraste:

imagen

Sin embargo, se pueden suavizar filtrando previamente el tampón de luminancia o simplemente utilizando un muestreo bicúbico:

imagen

Todavía se ve asqueroso, pero ya está mejor.

El muestreo de diferentes niveles de mipmap en luminancia cambia el radio del halo. Este parámetro es útil para controlar la "apariencia" general del resultado, así como para minimizar el efecto de halo, aunque debido a una disminución general en el contraste (se convierte en un filtro de borde) o la pérdida de la localidad del control de exposición:

imagen

Aún así, suavizar las imágenes fantasma no es suficiente. El resultado no es en absoluto natural; parece un estilo extremo de "foto HDR", a diferencia de lo que ve una persona. Sin embargo, combinando valores globales y locales, podemos obtener lo mejor de ambos 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 

imagen

Al cambiar el factor de mezcla, puede ajustar la exposición local para que, como resultado, minimice los artefactos y maximice el realismo percibido:

imagen

Relación de mezcla automática


El ajuste manual de la relación de mezcla es normal en situaciones en las que tenemos control absoluto de la posición de la cámara, la iluminación, etc. Sin embargo, en muchos casos (por ejemplo, juegos al aire libre con un cambio dinámico de día y de noche), este nivel de control simplemente no es posible. En este caso, sería bueno generar el factor de mezcla automáticamente.

En la imagen de abajo tenemos un amplio rango dinámico; en su mayoría valores de brillo medio-bajo y varias áreas con alta intensidad (cielo en las ventanas):

imagen

Sin exposición local, se pierde el color del cielo. En este caso, me gustaría una gran relación de mezcla :

imagen

Ahora considere la imagen a continuación, que tiene un pequeño rango dinámico principalmente con un alto valor de brillo:

imagen

En este caso, aplicar exposición local reduce demasiado el brillo de las áreas "brillantes":

imagen

Los datos de observación insinuaron un método simple de mezclar valores locales y globales : si la diferencia entre el brillo promedio y máximo de la escena es mayor, entonces el coeficiente de mezcla de la exposición local debería ser mayor. La generación del brillo máximo de la escena se puede hacer trivialmente durante el cálculo del brillo, utilizando histéresis para suavizar el resultado de la misma manera que para el valor promedio. Por lo tanto, podemos expandir el fragmento de código anterior de la siguiente manera:

 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 

Tenga en cuenta que uLocalExposureMax apareció en nuestra entrada para controlar el grado máximo absoluto de influencia de la exposición local. Obtuve un buen 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; 


Conclusión


El enfoque descrito anteriormente impone algunas limitaciones sobre cuándo es necesario medir el brillo de una escena. Por lo general, la medición se realiza inmediatamente después del paso de la iluminación para evitar la adaptación de efectos de partículas , floración , etc. Sin embargo, cuando se usa el brillo local, es importante que el valor real que participa en la exposición se presente en el mapa de luminancia . Esto significa que se debe realizar una medición de brillo inmediatamente antes de aplicar la exposición. Si esto es inaceptable, entonces la solución es generar brillo local por separado de los valores promedio y máximo.

Aunque creo que usar el brillo local y global de la escena juntos es el enfoque "correcto" para crear una imagen equilibrada y de aspecto natural, la calidad del resultado es obviamente subjetiva. El hecho de que dicho método sea adecuado para un juego en particular depende completamente del contenido y del estilo visual deseado. Me interesaría escuchar otras ideas al respecto.

Referencias


  1. Mapeo de tonos localizado (Bart Wronski)
  2. Implementación de una cámara con base física (Padraic Hennessy)
  3. Traslado de Frostbite a PBR (Sébastien Lagarde, et al.)
  4. Una mirada más cercana a Tonemapping (Matt Pettineo)
  5. La importancia de ser lineal (Larry Gritz, et al.)
  6. Técnicas avanzadas y optimización de tuberías de color HDR / VDR (Timothy Lottes)

Imágenes HDR tomadas del archivo sIBL .

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


All Articles