1
0
Fork 0

HDR: Improve exposure and bloom handling

This commit is contained in:
Fernando García Liñán 2021-07-31 16:52:10 +02:00
parent 526491790e
commit 467468ef3a
9 changed files with 138 additions and 37 deletions

View file

@ -1,11 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<PropertyList>
<name>Effects/HDR/bloom-threshold</name>
<parameters>
<exposure-compensation>
<use>/sim/rendering/hdr/exposure-compensation</use>
</exposure-compensation>
<bloom-threshold><use>/sim/rendering/hdr/bloom-threshold</use></bloom-threshold>
</parameters>
<technique n="1">
<pass>
<program>
<vertex-shader>Shaders/HDR/trivial.vert</vertex-shader>
<fragment-shader>Shaders/HDR/bloom-threshold.frag</fragment-shader>
<fragment-shader>Shaders/HDR/exposure-include.frag</fragment-shader>
</program>
<uniform>
<name>hdr_tex</name>
@ -17,6 +24,16 @@
<type>sampler-2d</type>
<value type="int">1</value>
</uniform>
<uniform>
<name>exposure_compensation</name>
<type>float</type>
<value><use>exposure-compensation</use></value>
</uniform>
<uniform>
<name>bloom_threshold</name>
<type>float</type>
<value><use>bloom-threshold</use></value>
</uniform>
</pass>
</technique>
</PropertyList>

View file

@ -1,11 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<PropertyList>
<name>Effects/HDR/postprocess</name>
<parameters>
<exposure-compensation>
<use>/sim/rendering/hdr/exposure-compensation</use>
</exposure-compensation>
<bloom-magnitude><use>/sim/rendering/hdr/bloom-magnitude</use></bloom-magnitude>
<debug-ev100><use>/sim/rendering/hdr/debug/display-ev100</use></debug-ev100>
</parameters>
<technique n="1">
<pass>
<program>
<vertex-shader>Shaders/HDR/trivial.vert</vertex-shader>
<fragment-shader>Shaders/HDR/postprocess.frag</fragment-shader>
<fragment-shader>Shaders/HDR/exposure-include.frag</fragment-shader>
</program>
<uniform>
<name>hdr_tex</name>
@ -22,6 +30,21 @@
<type>sampler-2d</type>
<value type="int">4</value>
</uniform>
<uniform>
<name>exposure_compensation</name>
<type>float</type>
<value><use>exposure-compensation</use></value>
</uniform>
<uniform>
<name>bloom_magnitude</name>
<type>float</type>
<value><use>bloom-magnitude</use></value>
</uniform>
<uniform>
<name>debug_ev100</name>
<type>bool</type>
<value><use>debug-ev100</use></value>
</uniform>
</pass>
</technique>
</PropertyList>

View file

@ -13,7 +13,7 @@ const float TAU = 4.0;
void main()
{
float prevLum = texelFetch(prev_lum_tex, ivec2(0), 0).r;
float currentLum = exp2(textureLod(current_lum_tex, vec2(0.5), 10.0).r);
float currentLum = exp(textureLod(current_lum_tex, vec2(0.5), 10.0).r);
adaptedLum = prevLum + (currentLum - prevLum) *
(1.0 - exp(-osg_DeltaFrameTime * TAU));
}

View file

@ -7,17 +7,18 @@ in vec2 texCoord;
uniform sampler2D hdr_tex;
uniform sampler2D lum_tex;
uniform float bloom_threshold;
vec3 applyExposure(vec3 color, float avgLuminance, float threshold);
void main()
{
vec3 hdrColor = texture(hdr_tex, texCoord).rgb;
float avgLuminance = texture(lum_tex, texCoord).r;
// XXX: Maybe we should actually control the EV compensation value itself
// instead of hardcoding a factor?
float exposure = 1.0 / (200.0 * avgLuminance);
hdrColor *= exposure;
float avgLuminance = texelFetch(lum_tex, ivec2(0), 0).r;
if (dot(hdrColor, vec3(0.333)) <= 0.001)
vec3 exposedHdrColor = applyExposure(hdrColor, avgLuminance, bloom_threshold);
if (dot(exposedHdrColor, vec3(0.333)) <= 0.001)
fragColor = vec3(0.0);
else
fragColor = hdrColor;
fragColor = exposedHdrColor;
}

View file

@ -0,0 +1,27 @@
#version 330 core
uniform float exposure_compensation;
const float one_over_log10 = 1.0 / log(10.0);
float log10(float x)
{
return one_over_log10 * log(x);
}
// Custom exposure curve based on the one proposed on
// 'Perceptual Effects in Real-time Tone Mapping'.
// http://resources.mpi-inf.mpg.de/hdr/peffects/krawczyk05sccg.pdf
float keyValue(float L)
{
return 0.82 - 2.0 / (log10(L + 0.84) + 2.6);
}
vec3 applyExposure(vec3 color, float avgLuminance, float threshold)
{
avgLuminance = max(avgLuminance, 0.001);
float linearExposure = keyValue(avgLuminance) / avgLuminance;
float exposure = log2(max(linearExposure, 0.0001));
exposure += exposure_compensation - threshold;
return color * exp2(exposure);
}

View file

@ -9,5 +9,5 @@ uniform sampler2D hdr_tex;
void main()
{
vec3 hdrColor = texture(hdr_tex, texCoord).rgb;
luminance = log2(max(dot(hdrColor, vec3(0.299, 0.587, 0.114)), 0.0001));
luminance = log(max(dot(hdrColor, vec3(0.299, 0.587, 0.114)), 0.0001));
}

View file

@ -10,51 +10,74 @@ uniform sampler2D bloom_tex;
uniform vec2 fg_BufferSize;
const float BLOOM_INTENSITY = 1.0;
const float EXPOSURE_THRESHOLD = 0.0;
uniform float bloom_magnitude;
uniform bool debug_ev100;
vec3 applyExposure(vec3 color, float avgLuminance, float threshold);
vec3 getDebugColor(float value)
{
float level = value*3.14159265/2.0;
vec3 col;
col.r = sin(level);
col.g = sin(level*2.0);
col.b = cos(level);
return col;
}
vec3 debugEV100(vec3 hdr, float avgLuminance)
{
float level;
if (texCoord.y < 0.05) {
const float w = 0.001;
if (texCoord.x >= (0.5 - w) && texCoord.x <= (0.5 + w))
return vec3(1.0);
return getDebugColor(texCoord.x);
}
float luminance = max(dot(hdr, vec3(0.299, 0.587, 0.114)), 0.0001);
float ev100 = log2(luminance * 8.0);
float norm = ev100 / 12.0 + 0.5;
return getDebugColor(norm);
}
const float a = 2.51;
const float b = 0.03;
const float c = 2.43;
const float d = 0.59;
const float e = 0.14;
vec3 ACESFilm(vec3 x)
{
const float a = 2.51;
const float b = 0.03;
const float c = 2.43;
const float d = 0.59;
const float e = 0.14;
return clamp((x*(a*x+b))/(x*(c*x+d)+e), 0.0, 1.0);
}
float log10(float x)
vec3 encodeSRGB(vec3 linearRGB)
{
return (1.0 / log(10.0)) * log(x);
}
float autokey(float lum)
{
return 1.03 - 2.0 / (2.0 + log10(lum + 1.0));
vec3 a = 12.92 * linearRGB;
vec3 b = 1.055 * pow(linearRGB, vec3(1.0 / 2.4)) - 0.055;
vec3 c = step(vec3(0.0031308), linearRGB);
return mix(a, b, c);
}
void main()
{
vec3 hdrColor = texture(hdr_tex, texCoord).rgb;
float avgLuminance = texelFetch(lum_tex, ivec2(0), 0).r;
avgLuminance = max(avgLuminance, 0.001);
// Auto-expose
float linearExposure = autokey(avgLuminance) / avgLuminance;
float exposure = log2(max(linearExposure, 0.0001));
exposure -= EXPOSURE_THRESHOLD;
hdrColor *= exp2(exposure);
// Exposure
vec3 exposedHdrColor = applyExposure(hdrColor, avgLuminance, 0.0);
if (debug_ev100) {
fragColor = vec4(debugEV100(exposedHdrColor, avgLuminance), 1.0);
return;
}
// Tonemap
vec3 color = ACESFilm(hdrColor);
vec3 color = ACESFilm(exposedHdrColor);
// Gamma correction
color = pow(color, vec3(1.0/2.2));
color = encodeSRGB(color);
// Apply bloom
// Bloom
vec3 bloom = texture(bloom_tex, texCoord).rgb;
bloom *= BLOOM_INTENSITY;
color += bloom;
color += bloom.rgb * bloom_magnitude;
fragColor = vec4(color, 1.0);
}

View file

@ -19,6 +19,7 @@ uniform float tile_width;
uniform float tile_height;
vec2 encodeNormal(vec3 n);
vec3 decodeSRGB(vec3 screenRGB);
void main()
{
@ -45,10 +46,11 @@ void main()
vec3 texel = texture(atlas, vec3(st, lc)).rgb;
gbuffer0.rgb = pow(texel, vec3(2.2)); // Gamma correction
gbuffer0.rgb = decodeSRGB(texel) * color.rgb;
gbuffer0.a = 1.0;
gbuffer1 = encodeNormal(normalVS);
gbuffer2 = vec4(0.0, 0.9, 0.0, 0.0);
float specularity = clamp(dot(specular.rgb, vec3(0.333)), 0.0, 1.0);
gbuffer2 = vec4(0.0, 1.0-specularity, 0.0, 0.0);
}

View file

@ -382,6 +382,14 @@ Started September 2000 by David Megginson, david@megginson.com
<available type="bool" userarchive="n">false</available>
<enabled type="bool" userarchive="y">true</enabled>
</pilot-model>
<hdr>
<debug>
<display-ev100 type="bool">false</display-ev100>
</debug>
<exposure-compensation type="float">0.0</exposure-compensation>
<bloom-magnitude type="float">1.0</bloom-magnitude>
<bloom-threshold type="float">6.0</bloom-threshold>
</hdr>
</rendering>
<model-hz type="int">120</model-hz>
<sound>