diff options
author | Jonathan "Geenz" Goodman <geenz@lindenlab.com> | 2023-07-12 18:58:15 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-07-12 18:58:15 -0700 |
commit | 880a1ee695f0d6b57c081c9a04d406712c17f058 (patch) | |
tree | b83d918400925f2b8dc504d0033ef42d5c6a09b8 /indra | |
parent | f6369a2f2246cf3828078f2c89736398e9f29869 (diff) | |
parent | 66283201301b0e55336f4b20407fed811acdc739 (diff) |
Merge pull request #275 from secondlife/SL-19567
SL-19567: Mitigate glow banding
Diffstat (limited to 'indra')
-rw-r--r-- | indra/llrender/llshadermgr.cpp | 3 | ||||
-rw-r--r-- | indra/llrender/llshadermgr.h | 1 | ||||
-rw-r--r-- | indra/newview/app_settings/settings.xml | 33 | ||||
-rw-r--r-- | indra/newview/app_settings/shaders/class1/effects/glowExtractF.glsl | 15 | ||||
-rw-r--r-- | indra/newview/llviewercontrol.cpp | 3 | ||||
-rw-r--r-- | indra/newview/llviewershadermgr.cpp | 11 | ||||
-rw-r--r-- | indra/newview/pipeline.cpp | 24 | ||||
-rw-r--r-- | indra/newview/pipeline.h | 1 |
8 files changed, 86 insertions, 5 deletions
diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp index 75d6ef6c46..22940dc703 100644 --- a/indra/llrender/llshadermgr.cpp +++ b/indra/llrender/llshadermgr.cpp @@ -1300,8 +1300,9 @@ void LLShaderMgr::initAttribsAndUniforms() mReservedUniforms.push_back("warmthAmount"); mReservedUniforms.push_back("glowStrength"); mReservedUniforms.push_back("glowDelta"); + mReservedUniforms.push_back("glowNoiseMap"); - llassert(mReservedUniforms.size() == LLShaderMgr::GLOW_DELTA+1); + llassert(mReservedUniforms.size() == LLShaderMgr::GLOW_NOISE_MAP+1); mReservedUniforms.push_back("minimum_alpha"); diff --git a/indra/llrender/llshadermgr.h b/indra/llrender/llshadermgr.h index 46f352aa58..ac4b393fb7 100644 --- a/indra/llrender/llshadermgr.h +++ b/indra/llrender/llshadermgr.h @@ -131,6 +131,7 @@ public: GLOW_WARMTH_AMOUNT, // "warmthAmount" GLOW_STRENGTH, // "glowStrength" GLOW_DELTA, // "glowDelta" + GLOW_NOISE_MAP, // "glowNoiseMap" MINIMUM_ALPHA, // "minimum_alpha" EMISSIVE_BRIGHTNESS, // "emissive_brightness" diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 09eda2534c..8e5e092250 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -9340,6 +9340,17 @@ <key>Value</key> <integer>0</integer> </map> + <key>RenderPostProcessingHDR</key> + <map> + <key>Comment</key> + <string>Enable HDR for post processing buffer</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> <key>RenderMaxOpenGLVersion</key> <map> <key>Comment</key> @@ -10155,6 +10166,17 @@ <key>Value</key> <integer>9</integer> </map> + <key>RenderGlowHDR</key> + <map> + <key>Comment</key> + <string>Enable HDR for glow map</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> <key>RenderGlowStrength</key> <map> <key>Comment</key> @@ -10203,6 +10225,17 @@ <key>Value</key> <real>1.3</real> </map> + <key>RenderGlowNoise</key> + <map> + <key>Comment</key> + <string>Enables glow noise (dithering). Reduces banding from glow in certain cases.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <real>1</real> + </map> <key>DisableAllRenderTypes</key> <map> <key>Comment</key> diff --git a/indra/newview/app_settings/shaders/class1/effects/glowExtractF.glsl b/indra/newview/app_settings/shaders/class1/effects/glowExtractF.glsl index 7a5e14566b..b5437d43d2 100644 --- a/indra/newview/app_settings/shaders/class1/effects/glowExtractF.glsl +++ b/indra/newview/app_settings/shaders/class1/effects/glowExtractF.glsl @@ -28,6 +28,10 @@ out vec4 frag_color; uniform sampler2D diffuseMap; +#if HAS_NOISE +uniform sampler2D glowNoiseMap; +uniform vec2 screen_res; +#endif uniform float minLuminance; uniform float maxExtractAlpha; uniform vec3 lumWeights; @@ -44,7 +48,16 @@ void main() float lum = smoothstep(minLuminance, minLuminance+1.0, dot(col.rgb, lumWeights ) ); float warmth = smoothstep(minLuminance, minLuminance+1.0, max(col.r * warmthWeights.r, max(col.g * warmthWeights.g, col.b * warmthWeights.b)) ); - frag_color.rgb = col.rgb; +#if HAS_NOISE + float TRUE_NOISE_RES = 128; // See mTrueNoiseMap + // *NOTE: Usually this is vary_fragcoord not vary_texcoord0, but glow extraction is in screen space + vec3 glow_noise = texture(glowNoiseMap, vary_texcoord0.xy * (screen_res / TRUE_NOISE_RES)).xyz; + // Dithering. Reduces banding effects in the reduced precision glow buffer. + float NOISE_DEPTH = 64.0; + col.rgb += glow_noise / NOISE_DEPTH; + col.rgb = max(col.rgb, vec3(0)); +#endif + frag_color.rgb = col.rgb; frag_color.a = max(col.a, mix(lum, warmth, warmthAmount) * maxExtractAlpha); } diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp index aae4409167..9f4287c23d 100644 --- a/indra/newview/llviewercontrol.cpp +++ b/indra/newview/llviewercontrol.cpp @@ -700,6 +700,7 @@ void settings_setup_listeners() setting_setup_signal_listener(gSavedSettings, "RenderUIBuffer", handleWindowResized); setting_setup_signal_listener(gSavedSettings, "RenderDepthOfField", handleReleaseGLBufferChanged); setting_setup_signal_listener(gSavedSettings, "RenderFSAASamples", handleReleaseGLBufferChanged); + setting_setup_signal_listener(gSavedSettings, "RenderPostProcessingHDR", handleReleaseGLBufferChanged); setting_setup_signal_listener(gSavedSettings, "RenderSpecularResX", handleLUTBufferChanged); setting_setup_signal_listener(gSavedSettings, "RenderSpecularResY", handleLUTBufferChanged); setting_setup_signal_listener(gSavedSettings, "RenderSpecularExponent", handleLUTBufferChanged); @@ -708,6 +709,8 @@ void settings_setup_listeners() setting_setup_signal_listener(gSavedSettings, "RenderGlow", handleReleaseGLBufferChanged); setting_setup_signal_listener(gSavedSettings, "RenderGlow", handleSetShaderChanged); setting_setup_signal_listener(gSavedSettings, "RenderGlowResolutionPow", handleReleaseGLBufferChanged); + setting_setup_signal_listener(gSavedSettings, "RenderGlowHDR", handleReleaseGLBufferChanged); + setting_setup_signal_listener(gSavedSettings, "RenderGlowNoise", handleSetShaderChanged); setting_setup_signal_listener(gSavedSettings, "RenderGammaFull", handleSetShaderChanged); setting_setup_signal_listener(gSavedSettings, "RenderVolumeLODFactor", handleVolumeLODChanged); setting_setup_signal_listener(gSavedSettings, "RenderAvatarLODFactor", handleAvatarLODChanged); diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp index 4559d71d6d..82b16d67bd 100644 --- a/indra/newview/llviewershadermgr.cpp +++ b/indra/newview/llviewershadermgr.cpp @@ -898,11 +898,20 @@ BOOL LLViewerShaderMgr::loadShadersEffects() if (success) { - gGlowExtractProgram.mName = "Glow Extract Shader (Post)"; + const bool use_glow_noise = gSavedSettings.getBOOL("RenderGlowNoise"); + const std::string glow_noise_label = use_glow_noise ? " (+Noise)" : ""; + + gGlowExtractProgram.mName = llformat("Glow Extract Shader (Post)%s", glow_noise_label.c_str()); gGlowExtractProgram.mShaderFiles.clear(); gGlowExtractProgram.mShaderFiles.push_back(make_pair("effects/glowExtractV.glsl", GL_VERTEX_SHADER)); gGlowExtractProgram.mShaderFiles.push_back(make_pair("effects/glowExtractF.glsl", GL_FRAGMENT_SHADER)); gGlowExtractProgram.mShaderLevel = mShaderLevel[SHADER_EFFECT]; + + if (use_glow_noise) + { + gGlowExtractProgram.addPermutation("HAS_NOISE", "1"); + } + success = gGlowExtractProgram.createShader(NULL, NULL); if (!success) { diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 0c767e7767..d50e671e05 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -157,6 +157,7 @@ S32 LLPipeline::RenderGlowResolutionPow; S32 LLPipeline::RenderGlowIterations; F32 LLPipeline::RenderGlowWidth; F32 LLPipeline::RenderGlowStrength; +bool LLPipeline::RenderGlowNoise; bool LLPipeline::RenderDepthOfField; bool LLPipeline::RenderDepthOfFieldInEditMode; F32 LLPipeline::CameraFocusTransitionTime; @@ -517,6 +518,7 @@ void LLPipeline::init() connectRefreshCachedSettingsSafe("RenderGlowIterations"); connectRefreshCachedSettingsSafe("RenderGlowWidth"); connectRefreshCachedSettingsSafe("RenderGlowStrength"); + connectRefreshCachedSettingsSafe("RenderGlowNoise"); connectRefreshCachedSettingsSafe("RenderDepthOfField"); connectRefreshCachedSettingsSafe("RenderDepthOfFieldInEditMode"); connectRefreshCachedSettingsSafe("CameraFocusTransitionTime"); @@ -840,7 +842,9 @@ bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples) mSceneMap.allocate(resX, resY, GL_RGB, true); } - mPostMap.allocate(resX, resY, GL_RGBA); + const bool post_hdr = gSavedSettings.getBOOL("RenderPostProcessingHDR"); + const U32 post_color_fmt = post_hdr ? GL_RGBA16F : GL_RGBA; + mPostMap.allocate(resX, resY, post_color_fmt); //HACK make screenbuffer allocations start failing after 30 seconds if (gSavedSettings.getBOOL("SimulateFBOFailure")) @@ -1005,6 +1009,7 @@ void LLPipeline::refreshCachedSettings() RenderGlowIterations = gSavedSettings.getS32("RenderGlowIterations"); RenderGlowWidth = gSavedSettings.getF32("RenderGlowWidth"); RenderGlowStrength = gSavedSettings.getF32("RenderGlowStrength"); + RenderGlowNoise = gSavedSettings.getBOOL("RenderGlowNoise"); RenderDepthOfField = gSavedSettings.getBOOL("RenderDepthOfField"); RenderDepthOfFieldInEditMode = gSavedSettings.getBOOL("RenderDepthOfFieldInEditMode"); CameraFocusTransitionTime = gSavedSettings.getF32("CameraFocusTransitionTime"); @@ -1163,9 +1168,11 @@ void LLPipeline::createGLBuffers() // allocate screen space glow buffers const U32 glow_res = llmax(1, llmin(512, 1 << gSavedSettings.getS32("RenderGlowResolutionPow"))); + const bool glow_hdr = gSavedSettings.getBOOL("RenderGlowHDR"); + const U32 glow_color_fmt = glow_hdr ? GL_RGBA16F : GL_RGBA; for (U32 i = 0; i < 3; i++) { - mGlow[i].allocate(512, glow_res, GL_RGBA); + mGlow[i].allocate(512, glow_res, glow_color_fmt); } allocateScreenBuffer(resX, resY); @@ -6882,6 +6889,19 @@ void LLPipeline::generateGlow(LLRenderTarget* src) warmthWeights.mV[2]); gGlowExtractProgram.uniform1f(LLShaderMgr::GLOW_WARMTH_AMOUNT, warmthAmount); + if (RenderGlowNoise) + { + S32 channel = gGlowExtractProgram.enableTexture(LLShaderMgr::GLOW_NOISE_MAP); + if (channel > -1) + { + gGL.getTexUnit(channel)->bindManual(LLTexUnit::TT_TEXTURE, mTrueNoiseMap); + gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT); + } + gGlowExtractProgram.uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, + mGlow[2].getWidth(), + mGlow[2].getHeight()); + } + { LLGLEnable blend_on(GL_BLEND); diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h index 961a55330a..c0559ce83b 100644 --- a/indra/newview/pipeline.h +++ b/indra/newview/pipeline.h @@ -1001,6 +1001,7 @@ public: static S32 RenderGlowIterations; static F32 RenderGlowWidth; static F32 RenderGlowStrength; + static bool RenderGlowNoise; static bool RenderDepthOfField; static bool RenderDepthOfFieldInEditMode; static F32 CameraFocusTransitionTime; |