diff --git a/src/gl/dynlights/gl_shadowmap.cpp b/src/gl/dynlights/gl_shadowmap.cpp index 1585aec82..0f493b751 100644 --- a/src/gl/dynlights/gl_shadowmap.cpp +++ b/src/gl/dynlights/gl_shadowmap.cpp @@ -82,6 +82,23 @@ ADD_STAT(shadowmap) return out; } +CUSTOM_CVAR(Int, gl_shadowmap_quality, 128, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) +{ + switch (self) + { + case 32: + case 64: + case 128: + case 256: + case 512: + case 1024: + break; + default: + self = 128; + break; + } +} + void FShadowMap::Update() { UpdateCycles.Reset(); @@ -102,11 +119,12 @@ void FShadowMap::Update() GLRenderer->mBuffers->BindShadowMapFB(); GLRenderer->mShadowMapShader->Bind(); + GLRenderer->mShadowMapShader->ShadowmapQuality.Set(gl_shadowmap_quality); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, mLightList); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, mNodesBuffer); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, mLinesBuffer); - glViewport(0, 0, SHADOWMAP_QUALITY, 1024); + glViewport(0, 0, gl_shadowmap_quality, 1024); GLRenderer->RenderScreenQuad(); const auto &viewport = GLRenderer->mScreenViewport; diff --git a/src/gl/dynlights/gl_shadowmap.h b/src/gl/dynlights/gl_shadowmap.h index d6a68198c..281936f80 100644 --- a/src/gl/dynlights/gl_shadowmap.h +++ b/src/gl/dynlights/gl_shadowmap.h @@ -8,10 +8,6 @@ class ADynamicLight; struct level_info_t; -// This constant must match the same constant in shadowmap.fp -//#define SHADOWMAP_QUALITY 1024 -#define SHADOWMAP_QUALITY 128 - class FShadowMap { public: diff --git a/src/gl/renderer/gl_renderbuffers.cpp b/src/gl/renderer/gl_renderbuffers.cpp index fbc8294b1..d60045f3e 100644 --- a/src/gl/renderer/gl_renderbuffers.cpp +++ b/src/gl/renderer/gl_renderbuffers.cpp @@ -81,6 +81,7 @@ FGLRenderBuffers::~FGLRenderBuffers() ClearBloom(); ClearExposureLevels(); ClearAmbientOcclusion(); + ClearShadowMap(); } void FGLRenderBuffers::ClearScene() @@ -759,18 +760,27 @@ void FGLRenderBuffers::BindShadowMapTexture(int texunit) glBindTexture(GL_TEXTURE_2D, mShadowMapTexture); } +void FGLRenderBuffers::ClearShadowMap() +{ + DeleteFrameBuffer(mShadowMapFB); + DeleteTexture(mShadowMapTexture); + mCurrentShadowMapSize = 0; +} + void FGLRenderBuffers::CreateShadowMap() { - if (mShadowMapTexture != 0) + if (mShadowMapTexture != 0 && gl_shadowmap_quality == mCurrentShadowMapSize) return; + ClearShadowMap(); + GLint activeTex, textureBinding, frameBufferBinding; glGetIntegerv(GL_ACTIVE_TEXTURE, &activeTex); glActiveTexture(GL_TEXTURE0); glGetIntegerv(GL_TEXTURE_BINDING_2D, &textureBinding); glGetIntegerv(GL_FRAMEBUFFER_BINDING, &frameBufferBinding); - mShadowMapTexture = Create2DTexture("ShadowMap", GL_R32F, SHADOWMAP_QUALITY, 1024); + mShadowMapTexture = Create2DTexture("ShadowMap", GL_R32F, gl_shadowmap_quality, 1024); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); @@ -781,6 +791,8 @@ void FGLRenderBuffers::CreateShadowMap() glBindTexture(GL_TEXTURE_2D, textureBinding); glActiveTexture(activeTex); glBindFramebuffer(GL_FRAMEBUFFER, frameBufferBinding); + + mCurrentShadowMapSize = gl_shadowmap_quality; } //========================================================================== diff --git a/src/gl/renderer/gl_renderbuffers.h b/src/gl/renderer/gl_renderbuffers.h index 5df3bcca0..c6aec6286 100644 --- a/src/gl/renderer/gl_renderbuffers.h +++ b/src/gl/renderer/gl_renderbuffers.h @@ -87,6 +87,7 @@ private: void ClearBloom(); void ClearExposureLevels(); void ClearAmbientOcclusion(); + void ClearShadowMap(); void CreateScene(int width, int height, int samples, bool needsSceneTextures); void CreatePipeline(int width, int height); void CreateBloom(int width, int height); @@ -140,6 +141,7 @@ private: // Shadow map texture GLuint mShadowMapTexture = 0; GLuint mShadowMapFB = 0; + int mCurrentShadowMapSize = 0; static bool FailedCreate; static bool BuffersActive; diff --git a/src/gl/shaders/gl_shadowmapshader.cpp b/src/gl/shaders/gl_shadowmapshader.cpp index 674d0a04f..8b81d386a 100644 --- a/src/gl/shaders/gl_shadowmapshader.cpp +++ b/src/gl/shaders/gl_shadowmapshader.cpp @@ -40,6 +40,7 @@ void FShadowMapShader::Bind() mShader.SetFragDataLocation(0, "FragColor"); mShader.Link("shaders/glsl/shadowmap"); mShader.SetAttribLocation(0, "PositionInProjection"); + ShadowmapQuality.Init(mShader, "ShadowmapQuality"); } mShader.Bind(); } diff --git a/src/gl/shaders/gl_shadowmapshader.h b/src/gl/shaders/gl_shadowmapshader.h index 7d01f9974..309dccb52 100644 --- a/src/gl/shaders/gl_shadowmapshader.h +++ b/src/gl/shaders/gl_shadowmapshader.h @@ -8,6 +8,8 @@ class FShadowMapShader public: void Bind(); + FBufferedUniform1f ShadowmapQuality; + private: FShaderProgram mShader; }; diff --git a/src/gl/system/gl_cvars.h b/src/gl/system/gl_cvars.h index b7122b01c..51ab642de 100644 --- a/src/gl/system/gl_cvars.h +++ b/src/gl/system/gl_cvars.h @@ -27,6 +27,7 @@ EXTERN_CVAR (Bool, gl_lights_checkside); EXTERN_CVAR (Bool, gl_light_sprites); EXTERN_CVAR (Bool, gl_light_particles); EXTERN_CVAR (Bool, gl_light_shadowmap); +EXTERN_CVAR (Int, gl_shadowmap_quality); EXTERN_CVAR(Int, gl_fogmode) EXTERN_CVAR(Int, gl_lightmode) diff --git a/wadsrc/static/shaders/glsl/shadowmap.fp b/wadsrc/static/shaders/glsl/shadowmap.fp index 9e4efdd4e..47696aa74 100644 --- a/wadsrc/static/shaders/glsl/shadowmap.fp +++ b/wadsrc/static/shaders/glsl/shadowmap.fp @@ -3,8 +3,9 @@ in vec2 TexCoord; out vec4 FragColor; // This constant must match the same constant in gl_shadowmap.h -// #define SHADOWMAP_QUALITY 1024 -#define SHADOWMAP_QUALITY 128 +// #define ShadowmapQuality 1024 +//#define ShadowmapQuality 128 +uniform float ShadowmapQuality; struct GPUNode { @@ -144,12 +145,12 @@ void main() if (radius > 0.0) { vec2 pixelpos; - switch (int(gl_FragCoord.x) / int(SHADOWMAP_QUALITY/4)) + switch (int(gl_FragCoord.x) / int(ShadowmapQuality/4.0)) { - case 0: pixelpos = vec2((gl_FragCoord.x - float(SHADOWMAP_QUALITY/8)) / float(SHADOWMAP_QUALITY/8), 1.0); break; - case 1: pixelpos = vec2(1.0, (gl_FragCoord.x - float(SHADOWMAP_QUALITY/4 + SHADOWMAP_QUALITY/8)) / float(SHADOWMAP_QUALITY/8)); break; - case 2: pixelpos = vec2(-(gl_FragCoord.x - float(SHADOWMAP_QUALITY/2 + SHADOWMAP_QUALITY/8)) / float(SHADOWMAP_QUALITY/8), -1.0); break; - case 3: pixelpos = vec2(-1.0, -(gl_FragCoord.x - float(SHADOWMAP_QUALITY*3/4 + SHADOWMAP_QUALITY/8)) / float(SHADOWMAP_QUALITY/8)); break; + case 0: pixelpos = vec2((gl_FragCoord.x - float(ShadowmapQuality/8.0)) / float(ShadowmapQuality/8.0), 1.0); break; + case 1: pixelpos = vec2(1.0, (gl_FragCoord.x - float(ShadowmapQuality/4.0 + ShadowmapQuality/8.0)) / float(ShadowmapQuality/8.0)); break; + case 2: pixelpos = vec2(-(gl_FragCoord.x - float(ShadowmapQuality/2.0 + ShadowmapQuality/8.0)) / float(ShadowmapQuality/8.0), -1.0); break; + case 3: pixelpos = vec2(-1.0, -(gl_FragCoord.x - float(ShadowmapQuality*3.0/4.0 + ShadowmapQuality/8.0)) / float(ShadowmapQuality/8.0)); break; } pixelpos = lightpos + pixelpos * radius;