diff options
4 files changed, 70 insertions, 16 deletions
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index d2c3c96317..a52d21edb5 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -9832,6 +9832,28 @@ <key>Value</key> <real>0.4</real> </map> + <key>RenderTonemapMix</key> + <map> + <key>Comment</key> + <string>Mix between linear and tonemapped colors (0.0(Linear) - 1.0(Tonemapped)</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>F32</string> + <key>Value</key> + <real>1.0</real> + </map> + <key>RenderTonemapType</key> + <map> + <key>Comment</key> + <string>What tonemapper to use: 0 = Khronos Neutral, 1 = ACES</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>U32</string> + <key>Value</key> + <integer>0</integer> + </map> <key>ReplaySession</key> <map> <key>Comment</key> diff --git a/indra/newview/app_settings/shaders/class1/deferred/postDeferredGammaCorrect.glsl b/indra/newview/app_settings/shaders/class1/deferred/postDeferredGammaCorrect.glsl index 0673159ab7..befd2ae6da 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/postDeferredGammaCorrect.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/postDeferredGammaCorrect.glsl @@ -29,9 +29,7 @@ out vec4 frag_color; uniform sampler2D diffuseRect; -uniform float exposure; uniform float gamma; -uniform float aces_mix; uniform vec2 screen_res; in vec2 vary_fragcoord; diff --git a/indra/newview/app_settings/shaders/class1/deferred/postDeferredTonemap.glsl b/indra/newview/app_settings/shaders/class1/deferred/postDeferredTonemap.glsl index c16ab2f9c4..fc6d4d7727 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/postDeferredTonemap.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/postDeferredTonemap.glsl @@ -95,9 +95,33 @@ vec3 toneMapACES_Hill(vec3 color) return color; } +// Khronos Neutral tonemapping +// https://github.com/KhronosGroup/ToneMapping/tree/main +// Input color is non-negative and resides in the Linear Rec. 709 color space. +// Output color is also Linear Rec. 709, but in the [0, 1] range. +vec3 PBRNeutralToneMapping( vec3 color ) +{ + const float startCompression = 0.8 - 0.04; + const float desaturation = 0.15; + + float x = min(color.r, min(color.g, color.b)); + float offset = x < 0.08 ? x - 6.25 * x * x : 0.04; + color -= offset; + + float peak = max(color.r, max(color.g, color.b)); + if (peak < startCompression) return color; + + const float d = 1. - startCompression; + float newPeak = 1. - d * d / (peak + d - startCompression); + color *= newPeak / peak; + + float g = 1. - 1. / (desaturation * (peak - newPeak) + 1.); + return mix(color, newPeak * vec3(1, 1, 1), g); +} + uniform float exposure; -uniform float gamma; -uniform float aces_mix; +uniform float tonemap_mix; +uniform int tonemap_type; vec3 toneMap(vec3 color) { @@ -106,8 +130,20 @@ vec3 toneMap(vec3 color) color *= exposure * exp_scale; - // mix ACES and Linear here as a compromise to avoid over-darkening legacy content - color = mix(toneMapACES_Hill(color), color, aces_mix); + vec3 clamped_color = clamp(color.rgb, vec3(0.0), vec3(1.0)); + + switch(tonemap_type) + { + case 0: + color = PBRNeutralToneMapping(color); + break; + case 1: + color = toneMapACES_Hill(color); + break; + } + + // mix tonemapped and linear here to provide adjustment + color = mix(clamped_color, color, tonemap_mix); #endif return color; @@ -125,14 +161,6 @@ void debugExposure(inout vec3 color) } } -vec3 legacyGamma(vec3 color) -{ - vec3 c = 1. - clamp(color, vec3(0.), vec3(1.)); - c = 1. - pow(c, vec3(gamma)); // s/b inverted already CPU-side - - return c; -} - void main() { //this is the one of the rare spots where diffuseRect contains linear color values (not sRGB) diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 91ade0eef1..3b1da8668b 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -7087,10 +7087,16 @@ void LLPipeline::tonemap(LLRenderTarget* src, LLRenderTarget* dst) F32 e = llclamp(exposure(), 0.5f, 4.f); static LLStaticHashedString s_exposure("exposure"); - static LLStaticHashedString aces_mix("aces_mix"); + static LLStaticHashedString tonemap_mix("tonemap_mix"); + static LLStaticHashedString tonemap_type("tonemap_type"); shader.uniform1f(s_exposure, e); - shader.uniform1f(aces_mix, gEXRImage.notNull() ? 0.f : 0.3f); + + static LLCachedControl<U32> tonemap_type_setting(gSavedSettings, "RenderTonemapType", 0U); + shader.uniform1i(tonemap_type, tonemap_type_setting); + + static LLCachedControl<F32> tonemap_mix_setting(gSavedSettings, "RenderTonemapMix", 1.f); + shader.uniform1f(tonemap_mix, tonemap_mix_setting); mScreenTriangleVB->setBuffer(); mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); |