HDR: Improve exposure and bloom handling
This commit is contained in:
parent
526491790e
commit
467468ef3a
9 changed files with 138 additions and 37 deletions
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
27
Shaders/HDR/exposure-include.frag
Normal file
27
Shaders/HDR/exposure-include.frag
Normal 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);
|
||||
}
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
|
Loading…
Add table
Reference in a new issue