diff --git a/src/gl/dynlights/gl_dynlight1.cpp b/src/gl/dynlights/gl_dynlight1.cpp index 4037545aa..26f42d7a2 100644 --- a/src/gl/dynlights/gl_dynlight1.cpp +++ b/src/gl/dynlights/gl_dynlight1.cpp @@ -59,6 +59,7 @@ CVAR (Bool, gl_attachedlights, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG); CVAR (Bool, gl_lights_checkside, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG); CVAR (Bool, gl_light_sprites, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG); CVAR (Bool, gl_light_particles, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG); +CVAR (Bool, gl_light_shadowmap, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG); //========================================================================== // diff --git a/src/gl/dynlights/gl_shadowmap.cpp b/src/gl/dynlights/gl_shadowmap.cpp index d43738f85..9a23e4114 100644 --- a/src/gl/dynlights/gl_shadowmap.cpp +++ b/src/gl/dynlights/gl_shadowmap.cpp @@ -26,6 +26,7 @@ #include "gl/dynlights/gl_dynlight.h" #include "gl/system/gl_interface.h" #include "gl/system/gl_debug.h" +#include "gl/system/gl_cvars.h" #include "gl/renderer/gl_renderer.h" #include "gl/renderer/gl_postprocessstate.h" #include "gl/renderer/gl_renderbuffers.h" @@ -67,6 +68,9 @@ void FShadowMap::Update() { + if (!IsEnabled()) + return; + UploadAABBTree(); UploadLights(); @@ -97,12 +101,25 @@ void FShadowMap::Update() bool FShadowMap::ShadowTest(ADynamicLight *light, const DVector3 &pos) { - if (mAABBTree) + if (IsEnabled() && mAABBTree) return mAABBTree->RayTest(light->Pos(), pos) >= 1.0f; else return true; } +bool FShadowMap::IsEnabled() const +{ + return gl_light_shadowmap && !!(gl.flags & RFL_SHADER_STORAGE_BUFFER); +} + +int FShadowMap::ShadowMapIndex(ADynamicLight *light) +{ + if (IsEnabled()) + return mLightToShadowmap[light]; + else + return 1024; +} + void FShadowMap::UploadLights() { mLights.Clear(); diff --git a/src/gl/dynlights/gl_shadowmap.h b/src/gl/dynlights/gl_shadowmap.h index da63b37e7..e2b5b371f 100644 --- a/src/gl/dynlights/gl_shadowmap.h +++ b/src/gl/dynlights/gl_shadowmap.h @@ -20,11 +20,14 @@ public: void Update(); // Return the assigned shadow map index for a given light - int ShadowMapIndex(ADynamicLight *light) { return mLightToShadowmap[light]; } + int ShadowMapIndex(ADynamicLight *light); // Test if a world position is in shadow relative to the specified light and returns false if it is bool ShadowTest(ADynamicLight *light, const DVector3 &pos); + // Returns true if gl_light_shadowmap is enabled and supported by the hardware + bool IsEnabled() const; + private: // Upload the AABB-tree to the GPU void UploadAABBTree(); diff --git a/src/gl/shaders/gl_shader.cpp b/src/gl/shaders/gl_shader.cpp index d36f4c4fa..9cb5e9aab 100644 --- a/src/gl/shaders/gl_shader.cpp +++ b/src/gl/shaders/gl_shader.cpp @@ -105,6 +105,11 @@ bool FShader::Load(const char * name, const char * vert_prog_lump, const char * vp_comb << "#define USE_QUAD_DRAWER\n"; } + if (!!(gl.flags & RFL_SHADER_STORAGE_BUFFER)) + { + vp_comb << "#define SUPPORTS_SHADOWMAPS\n"; + } + vp_comb << defines << i_data.GetString().GetChars(); FString fp_comb = vp_comb; diff --git a/src/gl/system/gl_cvars.h b/src/gl/system/gl_cvars.h index 3b425d261..b7122b01c 100644 --- a/src/gl/system/gl_cvars.h +++ b/src/gl/system/gl_cvars.h @@ -26,6 +26,7 @@ EXTERN_CVAR (Bool, gl_attachedlights); 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_fogmode) EXTERN_CVAR(Int, gl_lightmode) diff --git a/wadsrc/static/language.enu b/wadsrc/static/language.enu index 55477ee2e..5f7b9f600 100644 --- a/wadsrc/static/language.enu +++ b/wadsrc/static/language.enu @@ -2656,6 +2656,7 @@ GLLIGHTMNU_LIGHTDEFS = "Enable light definitions"; GLLIGHTMNU_CLIPLIGHTS = "Clip lights"; GLLIGHTMNU_LIGHTSPRITES = "Lights affect sprites"; GLLIGHTMNU_LIGHTPARTICLES = "Lights affect particles"; +GLLIGHTMNU_LIGHTSHADOWMAP = "Light shadowmaps"; // OpenGL Preferences GLPREFMNU_TITLE = "OPENGL PREFERENCES"; diff --git a/wadsrc/static/menudef.zz b/wadsrc/static/menudef.zz index 84ddb9448..054c5ac67 100644 --- a/wadsrc/static/menudef.zz +++ b/wadsrc/static/menudef.zz @@ -226,6 +226,7 @@ OptionMenu "GLLightOptions" Option "$GLLIGHTMNU_CLIPLIGHTS", gl_lights_checkside, "YesNo" Option "$GLLIGHTMNU_LIGHTSPRITES", gl_light_sprites, "YesNo" Option "$GLLIGHTMNU_LIGHTPARTICLES", gl_light_particles, "YesNo" + Option "$GLLIGHTMNU_LIGHTSHADOWMAP", gl_light_shadowmap, "YesNo" } OptionMenu "GLPrefOptions" diff --git a/wadsrc/static/shaders/glsl/main.fp b/wadsrc/static/shaders/glsl/main.fp index c3ef1f5d6..b6bb0d9b0 100644 --- a/wadsrc/static/shaders/glsl/main.fp +++ b/wadsrc/static/shaders/glsl/main.fp @@ -139,6 +139,8 @@ float R_DoomLightingEquation(float light) // //=========================================================================== +#ifdef SUPPORTS_SHADOWMAPS + float sampleShadowmap(vec2 lightpos, vec2 testpos, float v) { float u; @@ -173,6 +175,9 @@ float sampleShadowmap(vec2 lightpos, vec2 testpos, float v) float shadowmapAttenuation(vec4 lightpos, float shadowIndex) { + if (shadowIndex <= -1024.0 || shadowIndex >= 1024.0) + return 1.0; // No shadowmap available for this light + float v = (abs(shadowIndex) + 0.5) / 1024.0; vec2 dir = (pixelpos.xz - lightpos.xz); vec2 normal = normalize(vec2(-dir.y, dir.x)); @@ -184,6 +189,8 @@ float shadowmapAttenuation(vec4 lightpos, float shadowIndex) return sum / PCF_COUNT; } +#endif + //=========================================================================== // // Standard lambertian diffuse light calculation @@ -206,7 +213,9 @@ float diffuseContribution(vec3 lightDirection, vec3 normal) float pointLightAttenuation(vec4 lightpos, float shadowIndex) { float attenuation = max(lightpos.w - distance(pixelpos.xyz, lightpos.xyz),0.0) / lightpos.w; +#ifdef SUPPORTS_SHADOWMAPS attenuation *= shadowmapAttenuation(lightpos, shadowIndex); +#endif if (shadowIndex >= 0.0) // Sign bit is the attenuated light flag { return attenuation;