diff --git a/src/gl/renderer/gl_postprocess.cpp b/src/gl/renderer/gl_postprocess.cpp index 25050c22f..d06b94850 100644 --- a/src/gl/renderer/gl_postprocess.cpp +++ b/src/gl/renderer/gl_postprocess.cpp @@ -100,7 +100,26 @@ CVAR(Float, gl_lens_k, -0.12f, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) CVAR(Float, gl_lens_kcube, 0.1f, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) CVAR(Float, gl_lens_chromatic, 1.12f, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) -CVAR(Bool, gl_ssao, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) +CUSTOM_CVAR(Int, gl_fxaa, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) +{ + if (self < 0 || self >= FFXAAShader::Count) + { + self = 0; + } +} + +CUSTOM_CVAR(Int, gl_ssao, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) +{ + if (self < 0 || self > 3) + self = 0; +} + +CUSTOM_CVAR(Int, gl_ssao_portals, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) +{ + if (self < 0) + 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) @@ -110,14 +129,6 @@ CUSTOM_CVAR(Float, gl_ssao_blur_amount, 4.0f, 0) if (self < 0.1f) self = 0.1f; } -CUSTOM_CVAR(Int, gl_fxaa, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) -{ - if (self < 0 || self >= FFXAAShader::Count) - { - self = 0; - } -} - EXTERN_CVAR(Float, vid_brightness) EXTERN_CVAR(Float, vid_contrast) diff --git a/src/gl/renderer/gl_renderer.cpp b/src/gl/renderer/gl_renderer.cpp index ad9694175..5fa2de29d 100644 --- a/src/gl/renderer/gl_renderer.cpp +++ b/src/gl/renderer/gl_renderer.cpp @@ -123,7 +123,6 @@ FGLRenderer::FGLRenderer(OpenGLFrameBuffer *fb) mDepthBlurShader = nullptr; mSSAOShader = nullptr; mSSAOCombineShader = nullptr; - } void gl_LoadModels(); diff --git a/src/gl/scene/gl_scene.cpp b/src/gl/scene/gl_scene.cpp index 59d6e0987..b6120f940 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(); } @@ -476,6 +477,7 @@ void FGLRenderer::RenderTranslucent() void FGLRenderer::DrawScene(int drawmode) { static int recursion=0; + static int ssao_portals_available = 0; if (camera != nullptr) { @@ -493,8 +495,16 @@ 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; + // Decide if we need to do ssao for this scene + bool applySSAO = gl_ssao != 0 && FGLRenderBuffers::IsEnabled(); + switch (drawmode) + { + case DM_MAINVIEW: ssao_portals_available = gl_ssao_portals; break; + case DM_OFFSCREEN: ssao_portals_available = 0; applySSAO = false; break; + case DM_PORTAL: applySSAO = applySSAO && (ssao_portals_available > 0); ssao_portals_available--; break; + } + + // If SSAO is active, switch to gbuffer shaders and use the framebuffer with gbuffers 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..43adb5c0e 100644 --- a/src/gl/shaders/gl_ambientshader.cpp +++ b/src/gl/shaders/gl_ambientshader.cpp @@ -1,42 +1,24 @@ -/* -** gl_bloomshader.cpp -** Shaders used for screen space ambient occlusion -** -**--------------------------------------------------------------------------- -** Copyright 2016 Magnus Norddahl -** All rights reserved. -** -** Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions -** are met: -** -** 1. Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** 2. Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in the -** documentation and/or other materials provided with the distribution. -** 3. The name of the author may not be used to endorse or promote products -** derived from this software without specific prior written permission. -** 4. When not used as part of GZDoom or a GZDoom derivative, this code will be -** covered by the terms of the GNU Lesser General Public License as published -** by the Free Software Foundation; either version 2.1 of the License, or (at -** your option) any later version. -** 5. Full disclosure of the entire project's source code, except for third -** party libraries is mandatory. (NOTE: This clause is non-negotiable!) -** -** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR -** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, -** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -**--------------------------------------------------------------------------- -** -*/ +// +//--------------------------------------------------------------------------- +// +// Copyright(C) 2016 Magnus Norddahl +// All rights reserved. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this program. If not, see http://www.gnu.org/licenses/ +// +//-------------------------------------------------------------------------- +// #include "gl/system/gl_system.h" #include "files.h" @@ -74,32 +56,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 c1bc5c2fe..b7ac9e435 100644 --- a/src/gl/system/gl_cvars.h +++ b/src/gl/system/gl_cvars.h @@ -51,7 +51,8 @@ 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(Int, gl_ssao_portals) 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 48a809497..f29c9301c 100644 --- a/wadsrc/static/language.enu +++ b/wadsrc/static/language.enu @@ -2639,7 +2639,8 @@ GLPREFMNU_TONEMAP = "Tonemap Mode"; GLPREFMNU_BLOOM = "Bloom effect"; GLPREFMNU_LENS = "Lens distortion effect"; GLPREFMNU_FXAA = "FXAA Quality"; -GLPREFMNU_SSAO = "Ambient occlusion"; +GLPREFMNU_SSAO = "Ambient occlusion quality"; +GLPREFMNU_SSAO_PORTALS = "Portals with AO"; // Option Values OPTVAL_SMART = "Smart"; diff --git a/wadsrc/static/menudef.zz b/wadsrc/static/menudef.zz index 2672832e6..df0176269 100644 --- a/wadsrc/static/menudef.zz +++ b/wadsrc/static/menudef.zz @@ -58,6 +58,14 @@ OptionValue "FXAAQuality" 4, "$OPTVAL_EXTREME" } +OptionValue "SSAOModes" +{ + 0, "$OPTVAL_OFF" + 1, "$OPTVAL_LOW" + 2, "$OPTVAL_MEDIUM" + 3, "$OPTVAL_HIGH" +} + OptionValue "TextureFormats" { 0, "$OPTVAL_RGBA8" @@ -246,5 +254,6 @@ OptionMenu "GLPrefOptions" Option "$GLPREFMNU_BLOOM", gl_bloom, "OnOff" Option "$GLPREFMNU_LENS", gl_lens, "OnOff" Option "$GLPREFMNU_FXAA", gl_fxaa, "FXAAQuality" - Option "$GLPREFMNU_SSAO", gl_ssao, "OnOff" + Option "$GLPREFMNU_SSAO", gl_ssao, "SSAOModes" + Slider "$GLPREFMNU_SSAO_PORTALS", gl_ssao_portals, 0.0, 4.0, 1.0, 0 }