diff --git a/src/gl/renderer/gl_postprocess.cpp b/src/gl/renderer/gl_postprocess.cpp index 3b94fd8cc..2fcfe245a 100644 --- a/src/gl/renderer/gl_postprocess.cpp +++ b/src/gl/renderer/gl_postprocess.cpp @@ -99,7 +99,12 @@ CVAR(Float, gl_lens_k, -0.12f, 0) CVAR(Float, gl_lens_kcube, 0.1f, 0) CVAR(Float, gl_lens_chromatic, 1.12f, 0) -CVAR(Bool, gl_ssao, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) +CUSTOM_CVAR(Int, gl_ssao, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) +{ + if (self < 0 || self > 3) + self = 0; +} + CVAR(Float, gl_ssao_strength, 0.7, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) CVAR(Bool, gl_ssao_debug, false, 0) CVAR(Float, gl_ssao_bias, 0.5f, 0) diff --git a/src/gl/scene/gl_scene.cpp b/src/gl/scene/gl_scene.cpp index 59d6e0987..3efd22155 100644 --- a/src/gl/scene/gl_scene.cpp +++ b/src/gl/scene/gl_scene.cpp @@ -158,10 +158,11 @@ void FGLRenderer::Set3DViewport(bool mainview) { if (mainview && mBuffers->Setup(mScreenViewport.width, mScreenViewport.height, mSceneViewport.width, mSceneViewport.height)) { - mBuffers->BindSceneFB(gl_ssao); + bool useSSAO = (gl_ssao != 0); + mBuffers->BindSceneFB(useSSAO); GLenum buffers[] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1 }; - glDrawBuffers(gl_ssao ? 2 : 1, buffers); - gl_RenderState.SetPassType(gl_ssao ? GBUFFER_PASS : NORMAL_PASS); + glDrawBuffers(useSSAO ? 2 : 1, buffers); + gl_RenderState.SetPassType(useSSAO ? GBUFFER_PASS : NORMAL_PASS); gl_RenderState.Apply(); } @@ -494,7 +495,7 @@ void FGLRenderer::DrawScene(int drawmode) GLRenderer->mClipPortal = NULL; // this must be reset before any portal recursion takes place. // If SSAO is active, switch to gbuffer shaders and use the gbuffer framebuffer - bool applySSAO = gl_ssao && FGLRenderBuffers::IsEnabled() && drawmode == DM_MAINVIEW; + bool applySSAO = gl_ssao != 0 && FGLRenderBuffers::IsEnabled() && drawmode == DM_MAINVIEW; if (applySSAO) { GLenum buffers[] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1 }; diff --git a/src/gl/shaders/gl_ambientshader.cpp b/src/gl/shaders/gl_ambientshader.cpp index 4fa5b0e01..7d0e26a6a 100644 --- a/src/gl/shaders/gl_ambientshader.cpp +++ b/src/gl/shaders/gl_ambientshader.cpp @@ -74,32 +74,47 @@ void FLinearDepthShader::Bind(bool multisample) void FSSAOShader::Bind() { - if (!mShader) + auto &shader = mShader[gl_ssao]; + if (!shader) { - const char *defines = R"( - #define USE_RANDOM_TEXTURE - #define RANDOM_TEXTURE_WIDTH 4.0 - #define NUM_DIRECTIONS 8.0 - #define NUM_STEPS 4.0 - )"; - - mShader.Compile(FShaderProgram::Vertex, "shaders/glsl/screenquad.vp", "", 330); - mShader.Compile(FShaderProgram::Fragment, "shaders/glsl/ssao.fp", defines, 330); - mShader.SetFragDataLocation(0, "FragColor"); - mShader.Link("shaders/glsl/ssao"); - mShader.SetAttribLocation(0, "PositionInProjection"); - DepthTexture.Init(mShader, "DepthTexture"); - RandomTexture.Init(mShader, "RandomTexture"); - UVToViewA.Init(mShader, "UVToViewA"); - UVToViewB.Init(mShader, "UVToViewB"); - InvFullResolution.Init(mShader, "InvFullResolution"); - NDotVBias.Init(mShader, "NDotVBias"); - NegInvR2.Init(mShader, "NegInvR2"); - RadiusToScreen.Init(mShader, "RadiusToScreen"); - AOMultiplier.Init(mShader, "AOMultiplier"); - AOStrength.Init(mShader, "AOStrength"); + shader.Compile(FShaderProgram::Vertex, "shaders/glsl/screenquad.vp", "", 330); + shader.Compile(FShaderProgram::Fragment, "shaders/glsl/ssao.fp", GetDefines(gl_ssao), 330); + shader.SetFragDataLocation(0, "FragColor"); + shader.Link("shaders/glsl/ssao"); + shader.SetAttribLocation(0, "PositionInProjection"); + DepthTexture.Init(shader, "DepthTexture"); + RandomTexture.Init(shader, "RandomTexture"); + UVToViewA.Init(shader, "UVToViewA"); + UVToViewB.Init(shader, "UVToViewB"); + InvFullResolution.Init(shader, "InvFullResolution"); + NDotVBias.Init(shader, "NDotVBias"); + NegInvR2.Init(shader, "NegInvR2"); + RadiusToScreen.Init(shader, "RadiusToScreen"); + AOMultiplier.Init(shader, "AOMultiplier"); + AOStrength.Init(shader, "AOStrength"); } - mShader.Bind(); + shader.Bind(); +} + +FString FSSAOShader::GetDefines(int mode) +{ + int numDirections, numSteps; + switch (gl_ssao) + { + default: + case LowQuality: numDirections = 2; numSteps = 4; break; + case MediumQuality: numDirections = 4; numSteps = 4; break; + case HighQuality: numDirections = 8; numSteps = 4; break; + } + + FString defines; + defines.Format(R"( + #define USE_RANDOM_TEXTURE + #define RANDOM_TEXTURE_WIDTH 4.0 + #define NUM_DIRECTIONS %d.0 + #define NUM_STEPS %d.0 + )", numDirections, numSteps); + return defines; } void FDepthBlurShader::Bind(bool vertical) diff --git a/src/gl/shaders/gl_ambientshader.h b/src/gl/shaders/gl_ambientshader.h index f36b10625..704729b24 100644 --- a/src/gl/shaders/gl_ambientshader.h +++ b/src/gl/shaders/gl_ambientshader.h @@ -39,7 +39,18 @@ public: FBufferedUniform1f AOStrength; private: - FShaderProgram mShader; + enum Quality + { + Off, + LowQuality, + MediumQuality, + HighQuality, + NumQualityModes + }; + + FString GetDefines(int mode); + + FShaderProgram mShader[NumQualityModes]; }; class FDepthBlurShader diff --git a/src/gl/system/gl_cvars.h b/src/gl/system/gl_cvars.h index 97bd0b46c..845f0dd22 100644 --- a/src/gl/system/gl_cvars.h +++ b/src/gl/system/gl_cvars.h @@ -50,7 +50,7 @@ EXTERN_CVAR(Bool, gl_lens) EXTERN_CVAR(Float, gl_lens_k) EXTERN_CVAR(Float, gl_lens_kcube) EXTERN_CVAR(Float, gl_lens_chromatic) -EXTERN_CVAR(Bool, gl_ssao) +EXTERN_CVAR(Int, gl_ssao) EXTERN_CVAR(Float, gl_ssao_strength) EXTERN_CVAR(Bool, gl_ssao_debug) EXTERN_CVAR(Float, gl_ssao_bias) diff --git a/wadsrc/static/language.enu b/wadsrc/static/language.enu index 197e262f5..fae6d871b 100644 --- a/wadsrc/static/language.enu +++ b/wadsrc/static/language.enu @@ -2167,6 +2167,9 @@ NETMNU_TICBALANCE = "Latency balancing"; // Option Values OPTVAL_OFF = "Off"; OPTVAL_ON = "On"; +OPTVAL_LOW = "Low"; +OPTVAL_MEDIUM = "Medium"; +OPTVAL_HIGH = "High"; OPTVAL_MALE = "Male"; OPTVAL_FEMALE = "Female"; OPTVAL_OTHER = "Other"; @@ -2633,7 +2636,7 @@ GLPREFMNU_MULTISAMPLE = "Multisample"; GLPREFMNU_TONEMAP = "Tonemap Mode"; GLPREFMNU_BLOOM = "Bloom effect"; GLPREFMNU_LENS = "Lens distortion effect"; -GLPREFMNU_SSAO = "Ambient occlusion"; +GLPREFMNU_SSAO = "Ambient occlusion quality"; // Option Values OPTVAL_SMART = "Smart"; diff --git a/wadsrc/static/menudef.zz b/wadsrc/static/menudef.zz index 68523ea83..8b742ceff 100644 --- a/wadsrc/static/menudef.zz +++ b/wadsrc/static/menudef.zz @@ -42,6 +42,14 @@ OptionValue "TonemapModes" 5, "$OPTVAL_PALETTE" } +OptionValue "SSAOModes" +{ + 0, "$OPTVAL_OFF" + 1, "$OPTVAL_LOW" + 2, "$OPTVAL_MEDIUM" + 3, "$OPTVAL_HIGH" +} + OptionValue "TextureFormats" { 0, "$OPTVAL_RGBA8" @@ -226,5 +234,5 @@ OptionMenu "GLPrefOptions" Option "$GLPREFMNU_TONEMAP", gl_tonemap, "TonemapModes" Option "$GLPREFMNU_BLOOM", gl_bloom, "OnOff" Option "$GLPREFMNU_LENS", gl_lens, "OnOff" - Option "$GLPREFMNU_SSAO", gl_ssao, "OnOff" + Option "$GLPREFMNU_SSAO", gl_ssao, "SSAOModes" }