From 9073fb850133b705a999204b1e35a073d09a0199 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20Lu=C3=ADs=20Vaz=20Silva?= Date: Thu, 2 Jan 2025 12:26:49 -0300 Subject: [PATCH] add shadowMinQuality property and gl_light_shadow_max_quality CVar --- .../rendering/hwrenderer/data/hw_cvars.cpp | 5 +++++ src/common/rendering/hwrenderer/data/hw_cvars.h | 1 + src/doomdata.h | 2 ++ src/maploader/udmf.cpp | 6 ++++++ src/namedef_custom.h | 2 ++ src/playsim/a_dynlight.cpp | 3 ++- src/playsim/a_dynlight.h | 6 ++++++ src/playsim/p_mobj.cpp | 6 ++++++ src/r_data/a_dynlightdata.cpp | 1 + src/r_data/gldefs.cpp | 17 +++++++++++++++++ src/rendering/hwrenderer/hw_entrypoint.cpp | 2 +- wadsrc/static/shaders/scene/light_shadow.glsl | 4 ++++ .../static/zscript/actors/shared/dynlights.zs | 3 +++ wadsrc_lights/static/filter/doom.id/gldefs.txt | 5 +++++ 14 files changed, 61 insertions(+), 2 deletions(-) diff --git a/src/common/rendering/hwrenderer/data/hw_cvars.cpp b/src/common/rendering/hwrenderer/data/hw_cvars.cpp index cdf7cdd63..cd8b72d40 100644 --- a/src/common/rendering/hwrenderer/data/hw_cvars.cpp +++ b/src/common/rendering/hwrenderer/data/hw_cvars.cpp @@ -139,6 +139,11 @@ CUSTOM_CVAR(Int, gl_light_shadow_filter, 1, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) if (self < 0 || self > 8) self = 1; } +CUSTOM_CVAR(Int, gl_light_shadow_max_quality, 1, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) +{ + if (self < 0 || self > 4) self = 1; // default medium, 0 = low, 1 = medium, 2 = high, 3 = ultra +} + CUSTOM_CVAR(Int, gl_shadowmap_quality, 512, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) { switch (self) diff --git a/src/common/rendering/hwrenderer/data/hw_cvars.h b/src/common/rendering/hwrenderer/data/hw_cvars.h index 5190401bb..aeeb33c9d 100644 --- a/src/common/rendering/hwrenderer/data/hw_cvars.h +++ b/src/common/rendering/hwrenderer/data/hw_cvars.h @@ -16,6 +16,7 @@ EXTERN_CVAR (Bool, gl_light_sprites); EXTERN_CVAR (Bool, gl_light_particles); EXTERN_CVAR (Int, gl_light_shadows); EXTERN_CVAR (Int, gl_light_shadow_filter); +EXTERN_CVAR (Int, gl_light_shadow_max_quality); EXTERN_CVAR (Int, gl_shadowmap_quality); EXTERN_CVAR(Int, gl_fogmode) diff --git a/src/doomdata.h b/src/doomdata.h index c59c6af01..f827b1d83 100644 --- a/src/doomdata.h +++ b/src/doomdata.h @@ -388,6 +388,8 @@ struct FMapThing bool LightNoShadowMap; bool LightDontLightActors; bool LightDontLightMap; + bool LightHasShadowMinQuality; + int LightShadowMinQuality; }; diff --git a/src/maploader/udmf.cpp b/src/maploader/udmf.cpp index e6cd8b105..9aeee6ce9 100644 --- a/src/maploader/udmf.cpp +++ b/src/maploader/udmf.cpp @@ -519,6 +519,7 @@ public: th->Health = 1; th->FloatbobPhase = -1; th->SoftShadowRadius = -1.0; + th->LightShadowMinQuality = 1; // default medium, 0 = low, 1 = medium, 2 = high, 3 = ultra sc.MustGetToken('{'); while (!sc.CheckToken('}')) { @@ -812,6 +813,11 @@ public: th->LightDontLightMap = CheckBool(key); break; + case NAME_light_shadowminquality: + th->LightHasShadowMinQuality = true; + th->LightShadowMinQuality = std::clamp(CheckInt(key), 0, 4); + break; + case NAME_lm_suncolor: CHECK_N(Zd | Zdt) if (CheckInt(key) < 0 || CheckInt(key) > 0xFFFFFF) diff --git a/src/namedef_custom.h b/src/namedef_custom.h index 32a88a055..0410a27e5 100644 --- a/src/namedef_custom.h +++ b/src/namedef_custom.h @@ -324,6 +324,7 @@ xx(SoftShadowRadius) xx(LightLinearity) xx(lightflags) xx(lighttype) +xx(shadowMinQuality) xx(InternalDynamicLight) xx(_a_chase_default) xx(MapMarker) @@ -876,6 +877,7 @@ xx(light_linearity) xx(light_noshadowmap) xx(light_dontlightactors) xx(light_dontlightmap) +xx(light_shadowminquality) xx(skew_bottom_type) xx(skew_middle_type) diff --git a/src/playsim/a_dynlight.cpp b/src/playsim/a_dynlight.cpp index 4c278c0df..48f1b3582 100644 --- a/src/playsim/a_dynlight.cpp +++ b/src/playsim/a_dynlight.cpp @@ -160,6 +160,7 @@ void AttachLight(AActor *self) light->pSpotOuterAngle = &self->AngleVar(NAME_SpotOuterAngle); light->pPitch = &self->Angles.Pitch; light->pLightFlags = (LightFlags*)&self->IntVar(NAME_lightflags); + light->shadowMinQuality = std::clamp(self->IntVar(NAME_shadowMinQuality), 0, 4); light->pArgs = self->args; light->pSoftShadowRadius = &self->FloatVar(NAME_SoftShadowRadius); light->pLinearity = &self->FloatVar(NAME_LightLinearity); @@ -778,7 +779,7 @@ void FDynamicLight::CollectWithinRadius(const DVector3 &opos, FSection *section, } } } - shadowmapped = hitonesidedback && !DontShadowmap(); + shadowmapped = hitonesidedback && !DontShadowmap() && shadowMinQuality <= gl_light_shadow_max_quality; } //========================================================================== diff --git a/src/playsim/a_dynlight.h b/src/playsim/a_dynlight.h index e1587cbbb..e40fa56ab 100644 --- a/src/playsim/a_dynlight.h +++ b/src/playsim/a_dynlight.h @@ -80,6 +80,10 @@ public: void SetDontLightMap(bool on) { if (on) m_lightFlags |= LF_DONTLIGHTMAP; else m_lightFlags &= ~LF_DONTLIGHTMAP; } void SetTrace(bool on) { if (on) m_lightFlags |= LF_TRACE; else m_lightFlags &= ~LF_TRACE; } void SetNoShadowmap(bool on) { if (on) m_lightFlags |= LF_NOSHADOWMAP; else m_lightFlags &= ~LF_NOSHADOWMAP; } + void SetShadowMinQuality(int quality) + { + shadowMinQuality = quality; + } void SetSpot(bool spot) { if (spot) m_lightFlags |= LF_SPOT; else m_lightFlags &= ~LF_SPOT; } void SetSpotInnerAngle(double angle) { m_spotInnerAngle = DAngle::fromDeg(angle); } void SetSpotOuterAngle(double angle) { m_spotOuterAngle = DAngle::fromDeg(angle); } @@ -133,6 +137,7 @@ protected: DAngle m_pitch = nullAngle; double SoftShadowRadius = 5.0; double Linearity = 0.0; + int shadowMinQuality = 1; // default medium, 0 = low, 1 = medium, 2 = high, 3 = ultra friend FSerializer &Serialize(FSerializer &arc, const char *key, FLightDefaults &value, FLightDefaults *def); }; @@ -291,6 +296,7 @@ public: int m_tickCount; int m_lastUpdate; int mShadowmapIndex; + int shadowMinQuality; bool m_active; bool wasactive; bool visibletoplayer; diff --git a/src/playsim/p_mobj.cpp b/src/playsim/p_mobj.cpp index 1a400a65a..67eb47715 100644 --- a/src/playsim/p_mobj.cpp +++ b/src/playsim/p_mobj.cpp @@ -6246,6 +6246,12 @@ AActor *FLevelLocals::SpawnMapThing (FMapThing *mthing, int position) { mobj->IntVar(NAME_lightflags) |= LF_DONTLIGHTMAP; } + + if (mthing->LightHasShadowMinQuality) + { + mobj->IntVar(NAME_shadowMinQuality) = mthing->LightShadowMinQuality; + } + } mobj->CallBeginPlay (); diff --git a/src/r_data/a_dynlightdata.cpp b/src/r_data/a_dynlightdata.cpp index e12febf58..471a5e67b 100644 --- a/src/r_data/a_dynlightdata.cpp +++ b/src/r_data/a_dynlightdata.cpp @@ -156,6 +156,7 @@ void FLightDefaults::ApplyProperties(FDynamicLight * light) const light->swapped = m_swapped; } light->SetOffset(m_Pos); // this must be the last thing to do. + light->shadowMinQuality = shadowMinQuality; } void FLightDefaults::SetAttenuationForLevel(bool yes) diff --git a/src/r_data/gldefs.cpp b/src/r_data/gldefs.cpp index 35dc221ab..1ef9bd18a 100644 --- a/src/r_data/gldefs.cpp +++ b/src/r_data/gldefs.cpp @@ -192,6 +192,7 @@ static const char *LightTags[]= "dontlightothers", "dontlightmap", "trace", + "shadowminquality", nullptr }; @@ -219,6 +220,7 @@ enum { LIGHTTAG_DONTLIGHTOTHERS, LIGHTTAG_DONTLIGHTMAP, LIGHTTAG_TRACE, + LIGHTTAG_SHADOW_MINQUALITY, }; //========================================================================== @@ -528,6 +530,9 @@ class GLDefsParser case LIGHTTAG_TRACE: defaults->SetTrace(ParseInt(sc) != 0); break; + case LIGHTTAG_SHADOW_MINQUALITY: + defaults->SetShadowMinQuality(ParseInt(sc)); + break; case LIGHTTAG_SPOT: { float innerAngle = ParseFloat(sc); @@ -633,6 +638,9 @@ class GLDefsParser case LIGHTTAG_TRACE: defaults->SetTrace(ParseInt(sc) != 0); break; + case LIGHTTAG_SHADOW_MINQUALITY: + defaults->SetShadowMinQuality(ParseInt(sc)); + break; case LIGHTTAG_SPOT: { float innerAngle = ParseFloat(sc); @@ -741,6 +749,9 @@ class GLDefsParser case LIGHTTAG_TRACE: defaults->SetTrace(ParseInt(sc) != 0); break; + case LIGHTTAG_SHADOW_MINQUALITY: + defaults->SetShadowMinQuality(ParseInt(sc)); + break; case LIGHTTAG_SPOT: { float innerAngle = ParseFloat(sc); @@ -848,6 +859,9 @@ class GLDefsParser case LIGHTTAG_TRACE: defaults->SetTrace(ParseInt(sc) != 0); break; + case LIGHTTAG_SHADOW_MINQUALITY: + defaults->SetShadowMinQuality(ParseInt(sc)); + break; case LIGHTTAG_SPOT: { float innerAngle = ParseFloat(sc); @@ -952,6 +966,9 @@ class GLDefsParser case LIGHTTAG_TRACE: defaults->SetTrace(ParseInt(sc) != 0); break; + case LIGHTTAG_SHADOW_MINQUALITY: + defaults->SetShadowMinQuality(ParseInt(sc)); + break; case LIGHTTAG_SPOT: { float innerAngle = ParseFloat(sc); diff --git a/src/rendering/hwrenderer/hw_entrypoint.cpp b/src/rendering/hwrenderer/hw_entrypoint.cpp index a231a332b..83e78e30f 100644 --- a/src/rendering/hwrenderer/hw_entrypoint.cpp +++ b/src/rendering/hwrenderer/hw_entrypoint.cpp @@ -90,7 +90,7 @@ void CollectLights(FLevelLocals* Level) } else { - light->mShadowmapIndex = 1024; + light->mShadowmapIndex = 16000000; } } diff --git a/wadsrc/static/shaders/scene/light_shadow.glsl b/wadsrc/static/shaders/scene/light_shadow.glsl index a0b54a922..b7be3719e 100644 --- a/wadsrc/static/shaders/scene/light_shadow.glsl +++ b/wadsrc/static/shaders/scene/light_shadow.glsl @@ -84,6 +84,10 @@ float traceShadow(vec4 lightpos, float softShadowRadius) float shadowAttenuation(vec4 lightpos, float lightcolorA, float softShadowRadius) { + float shadowIndex = abs(lightcolorA) - 1.0; + if (shadowIndex >= 16000000.0) + return 1.0; // No shadowmap available for this light + if (lightpos.w > 1000000.0) return 1.0; // Sunlight return traceShadow(lightpos, softShadowRadius); diff --git a/wadsrc/static/zscript/actors/shared/dynlights.zs b/wadsrc/static/zscript/actors/shared/dynlights.zs index 2cd64c09c..f10652c07 100644 --- a/wadsrc/static/zscript/actors/shared/dynlights.zs +++ b/wadsrc/static/zscript/actors/shared/dynlights.zs @@ -6,9 +6,11 @@ class DynamicLight : Actor double LightLinearity; // used for Inverse-square falloff lights private int lighttype; private int lightflags; + int ShadowMinQuality; property SpotInnerAngle: SpotInnerAngle; property SpotOuterAngle: SpotOuterAngle; + property ShadowMinQuality: ShadowMinQuality; flagdef subtractive: lightflags, 0; flagdef additive: lightflags, 1; @@ -72,6 +74,7 @@ class DynamicLight : Actor RenderRadius -1; DynamicLight.SpotInnerAngle 10; DynamicLight.SpotOuterAngle 25; + DynamicLight.ShadowMinQuality 1; // default medium, 0 = low, 1 = medium, 2 = high, 3 = ultra +NOBLOCKMAP +NOGRAVITY +FIXMAPTHINGPOS diff --git a/wadsrc_lights/static/filter/doom.id/gldefs.txt b/wadsrc_lights/static/filter/doom.id/gldefs.txt index 5bb91c32f..bb611ca8e 100644 --- a/wadsrc_lights/static/filter/doom.id/gldefs.txt +++ b/wadsrc_lights/static/filter/doom.id/gldefs.txt @@ -81,6 +81,7 @@ pointlight PLASMABALL color 0.5 0.5 1.0 size 84 attenuate 1 + shadowminquality 4 } flickerlight PLASMA_X1 @@ -90,6 +91,7 @@ flickerlight PLASMA_X1 secondarySize 108 chance 0.4 attenuate 1 + shadowminquality 4 } flickerlight PLASMA_X2 @@ -99,6 +101,7 @@ flickerlight PLASMA_X2 secondarySize 132 chance 0.4 attenuate 1 + shadowminquality 4 } flickerlight PLASMA_X3 @@ -108,6 +111,7 @@ flickerlight PLASMA_X3 secondarySize 108 chance 0.4 attenuate 1 + shadowminquality 4 } flickerlight PLASMA_X4 @@ -117,6 +121,7 @@ flickerlight PLASMA_X4 secondarySize 24 chance 0.4 attenuate 1 + shadowminquality 4 } object PlasmaBall