- 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.
This commit is contained in:
Christoph Oelckers 2019-01-03 09:24:22 +01:00
parent da735c0e87
commit 8da1b5c1b0
13 changed files with 75 additions and 65 deletions

View file

@ -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();
}
//==========================================================================

View file

@ -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;

View file

@ -47,6 +47,9 @@ enum LightFlag
LF_SPOT = 64
};
typedef TFlags<LightFlag> 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<LightFlag> 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<AActor *> 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;

View file

@ -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;

View file

@ -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();

View file

@ -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

View file

@ -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

View file

@ -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;
}
}
}
//==========================================================================
//

View file

@ -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);

View file

@ -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;

View file

@ -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;

View file

@ -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();

View file

@ -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<TT> (value)) {}
// This allows initializing the flagset with 0, as 0 implicitly converts into a null pointer.