From 8da1b5c1b0be3e10656b961b7c5a452b9a3e1e2a Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 3 Jan 2019 09:24:22 +0100 Subject: [PATCH] - properly handle passing of the light flags. Since these can be changed on the placed light actor they have to be read from there, so this is now a pointer in FDynamicLight, just like the other properties that can be user-changed. Also did some cleanup on the interface so that external code doesn't need to dereference the lightflags pointer but can use utility functions for all flags. --- src/g_level.cpp | 2 + src/g_shared/a_dynlight.cpp | 6 +-- src/g_shared/a_dynlight.h | 43 ++++++++++---------- src/hwrenderer/dynlights/hw_dynlightdata.cpp | 8 +--- src/polyrenderer/scene/poly_model.cpp | 2 +- src/polyrenderer/scene/poly_plane.cpp | 2 +- src/polyrenderer/scene/poly_wall.cpp | 2 +- src/r_data/a_dynlightdata.cpp | 26 ++++++------ src/r_data/gldefs.cpp | 39 +++++++++++++----- src/swrenderer/line/r_walldraw.cpp | 2 +- src/swrenderer/plane/r_flatplane.cpp | 2 +- src/swrenderer/things/r_model.cpp | 2 +- src/tflags.h | 4 +- 13 files changed, 75 insertions(+), 65 deletions(-) diff --git a/src/g_level.cpp b/src/g_level.cpp index 03bf94cc8..962a68a31 100644 --- a/src/g_level.cpp +++ b/src/g_level.cpp @@ -78,6 +78,7 @@ #include "vm.h" #include "events.h" #include "i_music.h" +#include "a_dynlight.h" #include "gi.h" @@ -1532,6 +1533,7 @@ void G_InitLevelLocals () level.lightadditivesurfaces = info->lightadditivesurfaces < 0 ? gl_lightadditivesurfaces : !!info->lightadditivesurfaces; level.notexturefill = info->notexturefill < 0 ? gl_notexturefill : !!info->notexturefill; + FLightDefaults::SetAttenuationForLevel(); } //========================================================================== diff --git a/src/g_shared/a_dynlight.cpp b/src/g_shared/a_dynlight.cpp index 0273f07b5..4b3845fdc 100644 --- a/src/g_shared/a_dynlight.cpp +++ b/src/g_shared/a_dynlight.cpp @@ -133,11 +133,11 @@ void AttachLight(AActor *self) light->pSpotInnerAngle = &self->AngleVar(NAME_SpotInnerAngle); light->pSpotOuterAngle = &self->AngleVar(NAME_SpotOuterAngle); light->pPitch = &self->Angles.Pitch; + light->pLightFlags = (LightFlags*)&self->IntVar(NAME_lightflags); light->pArgs = self->args; light->specialf1 = DAngle(double(self->SpawnAngle)).Normalized360().Degrees; light->Sector = self->Sector; light->target = self; - light->lightflags.FromInt(self->IntVar(NAME_lightflags)); light->mShadowmapIndex = 1024; light->m_active = false; light->visibletoplayer = true; @@ -665,7 +665,7 @@ void FDynamicLight::CollectWithinRadius(const DVector3 &opos, FSection *section, } } } - shadowmapped = hitonesidedback && !(lightflags & LF_NOSHADOWMAP); + shadowmapped = hitonesidedback && !DontShadowmap(); } //========================================================================== @@ -886,7 +886,7 @@ CCMD(listlights) Printf("%s at (%f, %f, %f), color = 0x%02x%02x%02x, radius = %f %s %s", dl->target->GetClass()->TypeName.GetChars(), dl->X(), dl->Y(), dl->Z(), dl->GetRed(), dl->GetGreen(), dl->GetBlue(), - dl->radius, (dl->lightflags & LF_ATTENUATE)? "attenuated" : "", dl->shadowmapped? "shadowmapped" : ""); + dl->radius, dl->IsAttenuated()? "attenuated" : "", dl->shadowmapped? "shadowmapped" : ""); i++; shadowcount += dl->shadowmapped; diff --git a/src/g_shared/a_dynlight.h b/src/g_shared/a_dynlight.h index e22a51075..7b0c47956 100644 --- a/src/g_shared/a_dynlight.h +++ b/src/g_shared/a_dynlight.h @@ -47,6 +47,9 @@ enum LightFlag LF_SPOT = 64 }; +typedef TFlags LightFlags; +DEFINE_TFLAGS_OPERATORS(LightFlags) + //========================================================================== // // Light definitions @@ -64,15 +67,16 @@ public: int GetArg(int arg) { return m_Args[arg]; } uint8_t GetAttenuate() const { return m_attenuate; } void SetOffset(float* ft) { m_Pos.X = ft[0]; m_Pos.Z = ft[1]; m_Pos.Y = ft[2]; } - void SetSubtractive(bool subtract) { m_subtractive = subtract; } - void SetAdditive(bool add) { m_additive = add; } - void SetDontLightSelf(bool add) { m_dontlightself = add; } - void SetAttenuate(bool on) { m_attenuate = on; } - void SetHalo(bool halo) { m_halo = halo; } - void SetDontLightActors(bool on) { m_dontlightactors = on; } - void SetSpot(bool spot) { m_spot = spot; } + void SetSubtractive(bool subtract) { if (subtract) m_lightFlags |= LF_SUBTRACTIVE; else m_lightFlags &= ~LF_SUBTRACTIVE; } + void SetAdditive(bool add) { if (add) m_lightFlags |= LF_ADDITIVE; else m_lightFlags &= ~LF_ADDITIVE; } + void SetDontLightSelf(bool add) { if (add) m_lightFlags |= LF_DONTLIGHTSELF; else m_lightFlags &= ~LF_DONTLIGHTSELF; } + void SetAttenuate(bool on) { m_attenuate = on; if (on) m_lightFlags |= LF_ATTENUATE; else m_lightFlags &= ~LF_ATTENUATE; } + void SetDontLightActors(bool on) { if (on) m_lightFlags |= LF_DONTLIGHTACTORS; else m_lightFlags &= ~LF_DONTLIGHTACTORS; } + void SetNoShadowmap(bool on) { if (on) m_lightFlags |= LF_NOSHADOWMAP; else m_lightFlags &= ~LF_NOSHADOWMAP; } + void SetSpot(bool spot) { if (spot) m_lightFlags |= LF_SPOT; else m_lightFlags &= ~LF_SPOT; } void SetSpotInnerAngle(double angle) { m_spotInnerAngle = angle; } void SetSpotOuterAngle(double angle) { m_spotOuterAngle = angle; } + static void SetAttenuationForLevel(); void OrderIntensities() { @@ -90,11 +94,7 @@ protected: DVector3 m_Pos = { 0,0,0 }; ELightType m_type; int8_t m_attenuate = -1; - bool m_subtractive = false; - bool m_additive = false; - bool m_halo = false; - bool m_dontlightself = false; - bool m_dontlightactors = false; + LightFlags m_lightFlags = 0; bool m_swapped = false; bool m_spot = false; bool m_explicitPitch = false; @@ -149,11 +149,6 @@ protected: }; - -typedef TFlags LightFlags; -DEFINE_TFLAGS_OPERATORS(LightFlags) - - struct FLightNode { FLightNode ** prevTarget; @@ -180,7 +175,7 @@ struct FDynamicLight bool ShouldLightActor(AActor *check) { - return visibletoplayer && IsActive() && (!(lightflags & LF_DONTLIGHTSELF) || target != check) && !(lightflags&LF_DONTLIGHTACTORS); + return visibletoplayer && IsActive() && (!((*pLightFlags) & LF_DONTLIGHTSELF) || target != check) && !((*pLightFlags) & LF_DONTLIGHTACTORS); } void SetOffset(const DVector3 &pos) @@ -197,9 +192,13 @@ struct FDynamicLight int GetIntensity() const { return pArgs[LIGHT_INTENSITY]; } int GetSecondaryIntensity() const { return pArgs[LIGHT_SECONDARY_INTENSITY]; } - bool IsSubtractive() const { return !!(lightflags & LF_SUBTRACTIVE); } - bool IsAdditive() const { return !!(lightflags & LF_ADDITIVE); } - bool IsSpot() const { return !!(lightflags & LF_SPOT); } + bool IsSubtractive() const { return !!((*pLightFlags) & LF_SUBTRACTIVE); } + bool IsAdditive() const { return !!((*pLightFlags) & LF_ADDITIVE); } + bool IsSpot() const { return !!((*pLightFlags) & LF_SPOT); } + bool IsAttenuated() const { return !!((*pLightFlags) & LF_ATTENUATE); } + bool DontShadowmap() const { return !!((*pLightFlags) & LF_NOSHADOWMAP); } + bool DontLightSelf() const { return !!((*pLightFlags) & (LF_DONTLIGHTSELF|LF_DONTLIGHTACTORS)); } // dontlightactors implies dontlightself. + bool DontLightActors() const { return !!((*pLightFlags) & LF_DONTLIGHTACTORS); } void Deactivate() { m_active = false; } void Activate(); @@ -229,6 +228,7 @@ public: const DAngle *pSpotOuterAngle; const DAngle *pPitch; // This is to handle pitch overrides through GLDEFS, it can either point to the target's pitch or the light definition. const int *pArgs; + const LightFlags *pLightFlags; double specialf1; FDynamicLight *next, *prev; @@ -236,7 +236,6 @@ public: TObjPtr target; FLightNode * touching_sides; FLightNode * touching_sector; - LightFlags lightflags; float radius; // The maximum size the light can be with its current settings. float m_currentRadius; // The current light size. int m_tickCount; diff --git a/src/hwrenderer/dynlights/hw_dynlightdata.cpp b/src/hwrenderer/dynlights/hw_dynlightdata.cpp index e30f60cdb..5139b545d 100644 --- a/src/hwrenderer/dynlights/hw_dynlightdata.cpp +++ b/src/hwrenderer/dynlights/hw_dynlightdata.cpp @@ -42,8 +42,6 @@ thread_local FDynLightData lightdata; CVAR (Bool, gl_light_sprites, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG); CVAR (Bool, gl_light_particles, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG); -CVAR(Int, gl_attenuate, -1, 0); // This is mainly a debug option. - //========================================================================== // @@ -107,13 +105,9 @@ void FDynLightData::AddLightToList(int group, FDynamicLight * light, bool forceA } float shadowIndex = light->mShadowmapIndex + 1.0f; - bool attenuate; // Store attenuate flag in the sign bit of the float. - if (gl_attenuate == -1) attenuate = !!(light->lightflags & LF_ATTENUATE) || forceAttenuate; - else attenuate = !!gl_attenuate; - - if (attenuate) shadowIndex = -shadowIndex; + if (light->IsAttenuated() || forceAttenuate) shadowIndex = -shadowIndex; float lightType = 0.0f; float spotInnerAngle = 0.0f; diff --git a/src/polyrenderer/scene/poly_model.cpp b/src/polyrenderer/scene/poly_model.cpp index 08f21deb2..752552661 100644 --- a/src/polyrenderer/scene/poly_model.cpp +++ b/src/polyrenderer/scene/poly_model.cpp @@ -155,7 +155,7 @@ void PolyModelRenderer::AddLights(AActor *actor) { FDynamicLight *lightsource = addedLights[i]; - bool is_point_light = (lightsource->lightflags & LF_ATTENUATE) != 0; + bool is_point_light = lightsource->IsAttenuated(); uint32_t red = lightsource->GetRed(); uint32_t green = lightsource->GetGreen(); diff --git a/src/polyrenderer/scene/poly_plane.cpp b/src/polyrenderer/scene/poly_plane.cpp index 173628806..27a3f2efa 100644 --- a/src/polyrenderer/scene/poly_plane.cpp +++ b/src/polyrenderer/scene/poly_plane.cpp @@ -309,7 +309,7 @@ void RenderPolyPlane::SetDynLights(PolyRenderThread *thread, PolyDrawArgs &args, { if (cur_node->lightsource->IsActive()) { - bool is_point_light = (cur_node->lightsource->lightflags & LF_ATTENUATE) != 0; + bool is_point_light = cur_node->lightsource->IsAttenuated(); // To do: cull lights not touching subsector diff --git a/src/polyrenderer/scene/poly_wall.cpp b/src/polyrenderer/scene/poly_wall.cpp index 0d5d88ae4..1d04348ea 100644 --- a/src/polyrenderer/scene/poly_wall.cpp +++ b/src/polyrenderer/scene/poly_wall.cpp @@ -445,7 +445,7 @@ void RenderPolyWall::SetDynLights(PolyRenderThread *thread, PolyDrawArgs &args) { if (cur_node->lightsource->IsActive()) { - bool is_point_light = (cur_node->lightsource->lightflags & LF_ATTENUATE) != 0; + bool is_point_light = cur_node->lightsource->IsAttenuated(); // To do: cull lights not touching wall diff --git a/src/r_data/a_dynlightdata.cpp b/src/r_data/a_dynlightdata.cpp index b838f174e..acddbe906 100644 --- a/src/r_data/a_dynlightdata.cpp +++ b/src/r_data/a_dynlightdata.cpp @@ -76,14 +76,9 @@ void FLightDefaults::ApplyProperties(FDynamicLight * light) const light->lighttype = m_type; light->specialf1 = m_Param; light->pArgs = m_Args; - light->lightflags &= ~(LF_ADDITIVE | LF_SUBTRACTIVE | LF_DONTLIGHTSELF | LF_SPOT); - if (m_subtractive) light->lightflags |= LF_SUBTRACTIVE; - if (m_additive) light->lightflags |= LF_ADDITIVE; - if (m_dontlightself) light->lightflags |= LF_DONTLIGHTSELF; - if (m_dontlightactors) light->lightflags |= LF_DONTLIGHTACTORS; - if (m_spot) + light->pLightFlags = &m_lightFlags; + if (m_lightFlags & LF_SPOT) { - light->lightflags |= LF_SPOT; light->pSpotInnerAngle = &m_spotInnerAngle; light->pSpotOuterAngle = &m_spotOuterAngle; if (m_explicitPitch) light->pPitch = &m_pitch; @@ -103,16 +98,19 @@ void FLightDefaults::ApplyProperties(FDynamicLight * light) const if (light->m_currentRadius <= 0) light->m_currentRadius = 1; light->swapped = m_swapped; } - - switch (m_attenuate) - { - case 0: light->lightflags &= ~LF_ATTENUATE; break; - case 1: light->lightflags |= LF_ATTENUATE; break; - default: if (level.flags3 & LEVEL3_ATTENUATE) light->lightflags |= LF_ATTENUATE; else light->lightflags &= ~LF_ATTENUATE; break; - } light->SetOffset(m_Pos); // this must be the last thing to do. } +void FLightDefaults::SetAttenuationForLevel() +{ + for (auto ldef : LightDefaults) + { + if (ldef->m_attenuate == -1) + { + if (level.flags3 & LEVEL3_ATTENUATE) ldef->m_lightFlags |= LF_ATTENUATE; else ldef->m_lightFlags &= ~LF_ATTENUATE; + } + } +} //========================================================================== // diff --git a/src/r_data/gldefs.cpp b/src/r_data/gldefs.cpp index 3b8a5cf90..054e299cd 100644 --- a/src/r_data/gldefs.cpp +++ b/src/r_data/gldefs.cpp @@ -138,6 +138,7 @@ static const char *LightTags[]= "attenuate", "dontlightactors", "spot", + "noshadowmap", nullptr }; @@ -160,7 +161,8 @@ enum { LIGHTTAG_DONTLIGHTSELF, LIGHTTAG_ATTENUATE, LIGHTTAG_DONTLIGHTACTORS, - LIGHTTAG_SPOT + LIGHTTAG_SPOT, + LIGHTTAG_NOSHADOWMAP, }; //========================================================================== @@ -444,8 +446,11 @@ class GLDefsParser case LIGHTTAG_ADDITIVE: defaults->SetAdditive(ParseInt(sc) != 0); break; - case LIGHTTAG_HALO: - defaults->SetHalo(ParseInt(sc) != 0); + case LIGHTTAG_HALO: // old development garbage + ParseInt(sc); + break; + case LIGHTTAG_NOSHADOWMAP: + defaults->SetNoShadowmap(ParseInt(sc) != 0); break; case LIGHTTAG_DONTLIGHTSELF: defaults->SetDontLightSelf(ParseInt(sc) != 0); @@ -537,8 +542,11 @@ class GLDefsParser case LIGHTTAG_SUBTRACTIVE: defaults->SetSubtractive(ParseInt(sc) != 0); break; - case LIGHTTAG_HALO: - defaults->SetHalo(ParseInt(sc) != 0); + case LIGHTTAG_HALO: // old development garbage + ParseInt(sc); + break; + case LIGHTTAG_NOSHADOWMAP: + defaults->SetNoShadowmap(ParseInt(sc) != 0); break; case LIGHTTAG_DONTLIGHTSELF: defaults->SetDontLightSelf(ParseInt(sc) != 0); @@ -633,8 +641,11 @@ class GLDefsParser case LIGHTTAG_SUBTRACTIVE: defaults->SetSubtractive(ParseInt(sc) != 0); break; - case LIGHTTAG_HALO: - defaults->SetHalo(ParseInt(sc) != 0); + case LIGHTTAG_HALO: // old development garbage + ParseInt(sc); + break; + case LIGHTTAG_NOSHADOWMAP: + defaults->SetNoShadowmap(ParseInt(sc) != 0); break; case LIGHTTAG_DONTLIGHTSELF: defaults->SetDontLightSelf(ParseInt(sc) != 0); @@ -728,8 +739,11 @@ class GLDefsParser case LIGHTTAG_SUBTRACTIVE: defaults->SetSubtractive(ParseInt(sc) != 0); break; - case LIGHTTAG_HALO: - defaults->SetHalo(ParseInt(sc) != 0); + case LIGHTTAG_HALO: // old development garbage + ParseInt(sc); + break; + case LIGHTTAG_NOSHADOWMAP: + defaults->SetNoShadowmap(ParseInt(sc) != 0); break; case LIGHTTAG_DONTLIGHTSELF: defaults->SetDontLightSelf(ParseInt(sc) != 0); @@ -820,8 +834,11 @@ class GLDefsParser case LIGHTTAG_SUBTRACTIVE: defaults->SetSubtractive(ParseInt(sc) != 0); break; - case LIGHTTAG_HALO: - defaults->SetHalo(ParseInt(sc) != 0); + case LIGHTTAG_HALO: // old development garbage + ParseInt(sc); + break; + case LIGHTTAG_NOSHADOWMAP: + defaults->SetNoShadowmap(ParseInt(sc) != 0); break; case LIGHTTAG_DONTLIGHTSELF: defaults->SetDontLightSelf(ParseInt(sc) != 0); diff --git a/src/swrenderer/line/r_walldraw.cpp b/src/swrenderer/line/r_walldraw.cpp index 457129352..ecc143906 100644 --- a/src/swrenderer/line/r_walldraw.cpp +++ b/src/swrenderer/line/r_walldraw.cpp @@ -385,7 +385,7 @@ namespace swrenderer float lz = (float)lightZ; // Precalculate the constant part of the dot here so the drawer doesn't have to. - bool is_point_light = (cur_node->lightsource->lightflags & LF_ATTENUATE) != 0; + bool is_point_light = cur_node->lightsource->IsAttenuated(); float lconstant = lx * lx + ly * ly; float nlconstant = is_point_light ? lx * drawerargs.dc_normal.X + ly * drawerargs.dc_normal.Y : 0.0f; diff --git a/src/swrenderer/plane/r_flatplane.cpp b/src/swrenderer/plane/r_flatplane.cpp index b7f82b5f4..11f8fef86 100644 --- a/src/swrenderer/plane/r_flatplane.cpp +++ b/src/swrenderer/plane/r_flatplane.cpp @@ -236,7 +236,7 @@ namespace swrenderer float lz = (float)lightZ - drawerargs.dc_viewpos.Z; // Precalculate the constant part of the dot here so the drawer doesn't have to. - bool is_point_light = (cur_node->lightsource->lightflags & LF_ATTENUATE) != 0; + bool is_point_light = cur_node->lightsource->IsAttenuated(); float lconstant = ly * ly + lz * lz; float nlconstant = is_point_light ? lz * drawerargs.dc_normal.Z : 0.0f; diff --git a/src/swrenderer/things/r_model.cpp b/src/swrenderer/things/r_model.cpp index b3235057e..c7cda6025 100644 --- a/src/swrenderer/things/r_model.cpp +++ b/src/swrenderer/things/r_model.cpp @@ -196,7 +196,7 @@ namespace swrenderer { FDynamicLight *lightsource = addedLights[i]; - bool is_point_light = (lightsource->lightflags & LF_ATTENUATE) != 0; + bool is_point_light = lightsource->IsAttenuated(); uint32_t red = lightsource->GetRed(); uint32_t green = lightsource->GetGreen(); diff --git a/src/tflags.h b/src/tflags.h index 96ba53fb5..18c2becaf 100644 --- a/src/tflags.h +++ b/src/tflags.h @@ -52,8 +52,8 @@ public: typedef T EnumType; typedef TT IntType; - TFlags(){} - TFlags (const Self& other) : Value (other.GetValue()) {} + TFlags() = default; + TFlags(const Self& other) = default; TFlags (T value) : Value (static_cast (value)) {} // This allows initializing the flagset with 0, as 0 implicitly converts into a null pointer.