mirror of
https://github.com/ZDoom/gzdoom-gles.git
synced 2025-01-31 04:20:34 +00:00
- rewrote dynamic lights to not use actors for the internal representation and made DynamicLight a purely scripted class.
This should be less of a drag on the playsim than having each light a separate actor. A quick check with ZDCMP2 showed that the light processing time was reduced to 1/3rd from 0.5 ms to 0.17 ms per tic. It's also one native actor class less. # Conflicts: # src/g_shared/a_dynlight.cpp # src/g_shared/a_dynlight.h # src/hwrenderer/dynlights/hw_dynlightdata.cpp # src/hwrenderer/dynlights/hw_dynlightdata.h # src/hwrenderer/scene/hw_renderhacks.cpp # src/namedef.h # src/scripting/thingdef_data.cpp # src/swrenderer/line/r_walldraw.cpp # Conflicts: # src/d_main.cpp # src/g_levellocals.h # src/g_shared/a_dynlight.cpp # src/g_shared/a_dynlight.h # src/gl/dynlights/gl_dynlight.h # src/gl/dynlights/gl_dynlight1.cpp # src/gl/scene/gl_spritelight.cpp # src/gl/scene/gl_walls.cpp # src/hwrenderer/dynlights/hw_shadowmap.cpp # src/hwrenderer/dynlights/hw_shadowmap.h # src/hwrenderer/scene/hw_flats.cpp # src/p_setup.cpp
This commit is contained in:
parent
08c75efb10
commit
f261ec7d53
33 changed files with 459 additions and 438 deletions
|
@ -53,6 +53,7 @@ struct FBlockNode;
|
|||
struct FPortalGroupArray;
|
||||
struct visstyle_t;
|
||||
class FLightDefaults;
|
||||
struct FDynamicLight;
|
||||
//
|
||||
// NOTES: AActor
|
||||
//
|
||||
|
@ -1235,7 +1236,7 @@ public:
|
|||
DVector3 Prev;
|
||||
DRotator PrevAngles;
|
||||
int PrevPortalGroup;
|
||||
TArray<TObjPtr<AActor*> > AttachedLights;
|
||||
TArray<FDynamicLight *> AttachedLights;
|
||||
|
||||
// When was this actor spawned?
|
||||
int SpawnTime;
|
||||
|
@ -1489,13 +1490,11 @@ public:
|
|||
|
||||
int ApplyDamageFactor(FName damagetype, int damage) const;
|
||||
int GetModifiedDamage(FName damagetype, int damage, bool passive);
|
||||
|
||||
void DeleteAttachedLights();
|
||||
static void DeleteAllAttachedLights();
|
||||
static void RecreateAllAttachedLights();
|
||||
|
||||
bool hasmodel;
|
||||
|
||||
size_t PropagateMark();
|
||||
};
|
||||
|
||||
class FActorIterator
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
#include <type_traits>
|
||||
#include "doomtype.h"
|
||||
#include "i_system.h"
|
||||
#include "vectors.h"
|
||||
|
||||
class PClass;
|
||||
class PType;
|
||||
|
@ -238,6 +239,7 @@ public:
|
|||
inline PalEntry &ColorVar(FName field);
|
||||
inline FName &NameVar(FName field);
|
||||
inline double &FloatVar(FName field);
|
||||
inline DAngle &AngleVar(FName field);
|
||||
inline FString &StringVar(FName field);
|
||||
template<class T> T*& PointerVar(FName field);
|
||||
|
||||
|
@ -456,6 +458,11 @@ inline double &DObject::FloatVar(FName field)
|
|||
return *(double*)ScriptVar(field, nullptr);
|
||||
}
|
||||
|
||||
inline DAngle &DObject::AngleVar(FName field)
|
||||
{
|
||||
return *(DAngle*)ScriptVar(field, nullptr);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline T *&DObject::PointerVar(FName field)
|
||||
{
|
||||
|
|
|
@ -43,6 +43,8 @@
|
|||
#include "vm.h"
|
||||
#include "c_dispatch.h"
|
||||
#include "v_text.h"
|
||||
#include "g_levellocals.h"
|
||||
#include "a_dynlight.h"
|
||||
|
||||
|
||||
static int ThinkCount;
|
||||
|
@ -620,6 +622,13 @@ void DThinker::RunThinkers ()
|
|||
count += TickThinkers(&FreshThinkers[i], &Thinkers[i]);
|
||||
}
|
||||
} while (count != 0);
|
||||
|
||||
for (auto light = level.lights; light;)
|
||||
{
|
||||
auto next = light->next;
|
||||
light->Tick();
|
||||
light = next;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -640,6 +649,19 @@ void DThinker::RunThinkers ()
|
|||
}
|
||||
} while (count != 0);
|
||||
|
||||
// Also profile the internal dynamic lights, even though they are not implemented as thinkers.
|
||||
auto &prof = Profiles[NAME_InternalDynamicLight];
|
||||
prof.timer.Clock();
|
||||
for (auto light = level.lights; light;)
|
||||
{
|
||||
prof.numcalls++;
|
||||
auto next = light->next;
|
||||
light->Tick();
|
||||
light = next;
|
||||
}
|
||||
prof.timer.Unclock();
|
||||
|
||||
|
||||
struct SortedProfileInfo
|
||||
{
|
||||
const char* className;
|
||||
|
|
|
@ -170,6 +170,8 @@ struct FLevelLocals : public FLevelData
|
|||
float pixelstretch;
|
||||
float MusicVolume;
|
||||
|
||||
FDynamicLight *lights;
|
||||
|
||||
bool IsJumpingAllowed() const;
|
||||
bool IsCrouchingAllowed() const;
|
||||
bool IsFreelookAllowed() const;
|
||||
|
|
|
@ -75,7 +75,11 @@
|
|||
#include "c_cvars.h"
|
||||
#include "gl/system//gl_interface.h"
|
||||
#include "vm.h"
|
||||
#include "memarena.h"
|
||||
|
||||
static FMemArena DynLightArena(sizeof(FDynamicLight) * 200);
|
||||
static TArray<FDynamicLight*> FreeList;
|
||||
static FRandom randLight;
|
||||
|
||||
CUSTOM_CVAR (Bool, gl_lights, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOINITCALL)
|
||||
{
|
||||
|
@ -88,7 +92,7 @@ CVAR (Bool, gl_attachedlights, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG);
|
|||
//==========================================================================
|
||||
//
|
||||
//==========================================================================
|
||||
DEFINE_CLASS_PROPERTY(type, S, DynamicLight)
|
||||
DEFINE_SCRIPTED_PROPERTY(type, S, DynamicLight)
|
||||
{
|
||||
PROP_STRING_PARM(str, 0);
|
||||
static const char * ltype_names[]={
|
||||
|
@ -99,105 +103,143 @@ DEFINE_CLASS_PROPERTY(type, S, DynamicLight)
|
|||
|
||||
int style = MatchString(str, ltype_names);
|
||||
if (style < 0) I_Error("Unknown light type '%s'", str);
|
||||
defaults->lighttype = ltype_values[style];
|
||||
defaults->IntVar(NAME_lighttype) = ltype_values[style];
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// Actor classes
|
||||
//
|
||||
// For flexibility all functionality has been packed into a single class
|
||||
// which is controlled by flags
|
||||
//
|
||||
//==========================================================================
|
||||
IMPLEMENT_CLASS(ADynamicLight, false, false)
|
||||
|
||||
DEFINE_FIELD(ADynamicLight, SpotInnerAngle)
|
||||
DEFINE_FIELD(ADynamicLight, SpotOuterAngle)
|
||||
|
||||
static FRandom randLight;
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// Base class
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
void ADynamicLight::Serialize(FSerializer &arc)
|
||||
static FDynamicLight *GetLight()
|
||||
{
|
||||
Super::Serialize (arc);
|
||||
auto def = static_cast<ADynamicLight*>(GetDefault());
|
||||
arc("lightflags", lightflags, def->lightflags)
|
||||
("lighttype", lighttype, def->lighttype)
|
||||
("tickcount", m_tickCount, def->m_tickCount)
|
||||
("currentradius", m_currentRadius, def->m_currentRadius)
|
||||
("spotinnerangle", SpotInnerAngle, def->SpotInnerAngle)
|
||||
("spotouterangle", SpotOuterAngle, def->SpotOuterAngle);
|
||||
|
||||
if (lighttype == PulseLight)
|
||||
arc("lastupdate", m_lastUpdate, def->m_lastUpdate)
|
||||
("cycler", m_cycler, def->m_cycler);
|
||||
|
||||
// Remap the old flags.
|
||||
if (SaveVersion < 4552)
|
||||
FDynamicLight *ret;
|
||||
if (FreeList.Size())
|
||||
{
|
||||
lightflags = 0;
|
||||
if (flags4 & MF4_MISSILEEVENMORE) lightflags |= LF_SUBTRACTIVE;
|
||||
if (flags4 & MF4_MISSILEMORE) lightflags |= LF_ADDITIVE;
|
||||
if (flags4 & MF4_SEESDAGGERS) lightflags |= LF_DONTLIGHTSELF;
|
||||
if (flags4 & MF4_INCOMBAT) lightflags |= LF_ATTENUATE;
|
||||
if (flags4 & MF4_STANDSTILL) lightflags |= LF_NOSHADOWMAP;
|
||||
if (flags4 & MF4_EXTREMEDEATH) lightflags |= LF_DONTLIGHTACTORS;
|
||||
flags4 &= ~(MF4_SEESDAGGERS); // this flag is dangerous and must be cleared. The others do not matter.
|
||||
FreeList.Pop(ret);
|
||||
}
|
||||
else ret = (FDynamicLight*)DynLightArena.Alloc(sizeof(FDynamicLight));
|
||||
memset(ret, 0, sizeof(*ret));
|
||||
ret->next = level.lights;
|
||||
level.lights = ret;
|
||||
if (ret->next) ret->next->prev = ret;
|
||||
ret->visibletoplayer = true;
|
||||
ret->mShadowmapIndex = 1024;
|
||||
ret->Pos.X = -10000000; // not a valid coordinate.
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// Attaches a dynamic light descriptor to a dynamic light actor.
|
||||
// Owned lights do not use this function.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void AttachLight(AActor *self)
|
||||
{
|
||||
auto light = GetLight();
|
||||
|
||||
light->pSpotInnerAngle = &self->AngleVar(NAME_SpotInnerAngle);
|
||||
light->pSpotOuterAngle = &self->AngleVar(NAME_SpotOuterAngle);
|
||||
light->pPitch = &self->Angles.Pitch;
|
||||
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;
|
||||
light->lighttype = (uint8_t)self->IntVar(NAME_lighttype);
|
||||
self->AttachedLights.Push(light);
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION_NATIVE(ADynamicLight, AttachLight, AttachLight)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(AActor);
|
||||
AttachLight(self);
|
||||
return 0;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void ActivateLight(AActor *self)
|
||||
{
|
||||
for (auto l : self->AttachedLights) l->Activate();
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION_NATIVE(ADynamicLight, ActivateLight, ActivateLight)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(AActor);
|
||||
ActivateLight(self);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void DeactivateLight(AActor *self)
|
||||
{
|
||||
for (auto l : self->AttachedLights) l->Activate();
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION_NATIVE(ADynamicLight, DeactivateLight, DeactivateLight)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(AActor);
|
||||
DeactivateLight(self);
|
||||
return 0;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
static void SetOffset(AActor *self, double x, double y, double z)
|
||||
{
|
||||
for (auto l : self->AttachedLights)
|
||||
{
|
||||
l->SetOffset(DVector3(x, y, z));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ADynamicLight::PostSerialize()
|
||||
DEFINE_ACTION_FUNCTION_NATIVE(ADynamicLight, SetOffset, SetOffset)
|
||||
{
|
||||
Super::PostSerialize();
|
||||
// The default constructor which is used for creating objects before deserialization will not set this variable.
|
||||
// It needs to be true for all placed lights.
|
||||
visibletoplayer = true;
|
||||
mShadowmapIndex = 1024;
|
||||
LinkLight();
|
||||
PARAM_SELF_PROLOGUE(AActor);
|
||||
PARAM_FLOAT(x);
|
||||
PARAM_FLOAT(y);
|
||||
PARAM_FLOAT(z);
|
||||
SetOffset(self, x, y, z);
|
||||
return 0;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// [TS]
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
void ADynamicLight::BeginPlay()
|
||||
|
||||
void FDynamicLight::ReleaseLight()
|
||||
{
|
||||
//Super::BeginPlay();
|
||||
ChangeStatNum(STAT_DLIGHT);
|
||||
|
||||
specialf1 = DAngle(double(SpawnAngle)).Normalized360().Degrees;
|
||||
visibletoplayer = true;
|
||||
mShadowmapIndex = 1024;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// [TS]
|
||||
//
|
||||
//==========================================================================
|
||||
void ADynamicLight::PostBeginPlay()
|
||||
{
|
||||
Super::PostBeginPlay();
|
||||
|
||||
if (!(SpawnFlags & MTF_DORMANT))
|
||||
{
|
||||
Activate (NULL);
|
||||
}
|
||||
|
||||
subsector = R_PointInSubsector(Pos());
|
||||
assert(prev != nullptr || this == level.lights);
|
||||
if (prev != nullptr) prev->next = next;
|
||||
else level.lights = next;
|
||||
if (next != nullptr) next->prev = prev;
|
||||
prev = nullptr;
|
||||
FreeList.Push(this);
|
||||
Printf("Releasing %p\n", this);
|
||||
}
|
||||
|
||||
|
||||
|
@ -206,21 +248,19 @@ void ADynamicLight::PostBeginPlay()
|
|||
// [TS]
|
||||
//
|
||||
//==========================================================================
|
||||
void ADynamicLight::Activate(AActor *activator)
|
||||
void FDynamicLight::Activate()
|
||||
{
|
||||
//Super::Activate(activator);
|
||||
flags2&=~MF2_DORMANT;
|
||||
|
||||
m_currentRadius = float(args[LIGHT_INTENSITY]);
|
||||
m_active = true;
|
||||
m_currentRadius = float(GetIntensity());
|
||||
m_tickCount = 0;
|
||||
|
||||
if (lighttype == PulseLight)
|
||||
{
|
||||
float pulseTime = float(specialf1 / TICRATE);
|
||||
|
||||
|
||||
m_lastUpdate = level.maptime;
|
||||
if (!swapped) m_cycler.SetParams(float(args[LIGHT_SECONDARY_INTENSITY]), float(args[LIGHT_INTENSITY]), pulseTime);
|
||||
else m_cycler.SetParams(float(args[LIGHT_INTENSITY]), float(args[LIGHT_SECONDARY_INTENSITY]), pulseTime);
|
||||
if (!swapped) m_cycler.SetParams(float(GetSecondaryIntensity()), float(GetIntensity()), pulseTime);
|
||||
else m_cycler.SetParams(float(GetIntensity()), float(GetSecondaryIntensity()), pulseTime);
|
||||
m_cycler.ShouldCycle(true);
|
||||
m_cycler.SetCycleType(CYCLE_Sin);
|
||||
m_currentRadius = float(m_cycler.GetVal());
|
||||
|
@ -234,28 +274,26 @@ void ADynamicLight::Activate(AActor *activator)
|
|||
// [TS]
|
||||
//
|
||||
//==========================================================================
|
||||
void ADynamicLight::Deactivate(AActor *activator)
|
||||
void FDynamicLight::Tick()
|
||||
{
|
||||
//Super::Deactivate(activator);
|
||||
flags2|=MF2_DORMANT;
|
||||
}
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// [TS]
|
||||
//
|
||||
//==========================================================================
|
||||
void ADynamicLight::Tick()
|
||||
{
|
||||
if (IsOwned())
|
||||
if (!target)
|
||||
{
|
||||
if (!target || !target->state)
|
||||
delete this;
|
||||
return;
|
||||
}
|
||||
|
||||
if (owned)
|
||||
{
|
||||
if (!target->state)
|
||||
{
|
||||
this->Destroy();
|
||||
delete this;
|
||||
return;
|
||||
}
|
||||
if (target->flags & MF_UNMORPHED)
|
||||
{
|
||||
m_active = false;
|
||||
return;
|
||||
}
|
||||
if (target->flags & MF_UNMORPHED) return;
|
||||
visibletoplayer = target->IsVisibleToPlayer(); // cache this value for the renderer to speed up calculations.
|
||||
}
|
||||
|
||||
|
@ -278,25 +316,23 @@ void ADynamicLight::Tick()
|
|||
|
||||
case FlickerLight:
|
||||
{
|
||||
int rnd = randLight();
|
||||
float pct = float(specialf1 / 360.f);
|
||||
|
||||
m_currentRadius = float(args[LIGHT_INTENSITY + (rnd >= pct * 255)]);
|
||||
int rnd = randLight(360);
|
||||
m_currentRadius = float((rnd >= int(specialf1))? GetIntensity() : GetSecondaryIntensity());
|
||||
break;
|
||||
}
|
||||
|
||||
case RandomFlickerLight:
|
||||
{
|
||||
int flickerRange = args[LIGHT_SECONDARY_INTENSITY] - args[LIGHT_INTENSITY];
|
||||
int flickerRange = GetSecondaryIntensity() - GetIntensity();
|
||||
float amt = randLight() / 255.f;
|
||||
|
||||
if (m_tickCount > specialf1)
|
||||
{
|
||||
m_tickCount = 0;
|
||||
}
|
||||
if (m_tickCount++ == 0 || m_currentRadius > args[LIGHT_SECONDARY_INTENSITY])
|
||||
if (m_tickCount++ == 0 || m_currentRadius > GetSecondaryIntensity())
|
||||
{
|
||||
m_currentRadius = float(args[LIGHT_INTENSITY] + (amt * flickerRange));
|
||||
m_currentRadius = float(GetIntensity() + (amt * flickerRange));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -314,14 +350,14 @@ void ADynamicLight::Tick()
|
|||
|
||||
case RandomColorFlickerLight:
|
||||
{
|
||||
int flickerRange = args[LIGHT_SECONDARY_INTENSITY] - args[LIGHT_INTENSITY];
|
||||
int flickerRange = GetSecondaryIntensity() - GetIntensity();
|
||||
float amt = randLight() / 255.f;
|
||||
|
||||
m_tickCount++;
|
||||
|
||||
if (m_tickCount > specialf1)
|
||||
{
|
||||
m_currentRadius = args[LIGHT_INTENSITY] + (amt * flickerRange);
|
||||
m_currentRadius = GetIntensity() + (amt * flickerRange);
|
||||
m_tickCount = 0;
|
||||
}
|
||||
break;
|
||||
|
@ -331,7 +367,7 @@ void ADynamicLight::Tick()
|
|||
case SectorLight:
|
||||
{
|
||||
float intensity;
|
||||
float scale = args[LIGHT_SCALE] / 8.f;
|
||||
float scale = GetIntensity() / 8.f;
|
||||
|
||||
if (scale == 0.f) scale = 1.f;
|
||||
|
||||
|
@ -343,7 +379,7 @@ void ADynamicLight::Tick()
|
|||
}
|
||||
|
||||
case PointLight:
|
||||
m_currentRadius = float(args[LIGHT_INTENSITY]);
|
||||
m_currentRadius = float(GetIntensity());
|
||||
break;
|
||||
}
|
||||
if (m_currentRadius <= 0) m_currentRadius = 1;
|
||||
|
@ -358,45 +394,37 @@ void ADynamicLight::Tick()
|
|||
//
|
||||
//
|
||||
//==========================================================================
|
||||
void ADynamicLight::UpdateLocation()
|
||||
void FDynamicLight::UpdateLocation()
|
||||
{
|
||||
double oldx= X();
|
||||
double oldy= Y();
|
||||
double oldradius= radius;
|
||||
float intensity;
|
||||
float oldradius = radius;
|
||||
|
||||
if (IsActive())
|
||||
{
|
||||
if (target)
|
||||
{
|
||||
DAngle angle = target->Angles.Yaw;
|
||||
double s = angle.Sin();
|
||||
double c = angle.Cos();
|
||||
AActor *target = this->target; // perform the read barrier only once.
|
||||
|
||||
DVector3 pos = target->Vec3Offset(m_off.X * c + m_off.Y * s, m_off.X * s - m_off.Y * c, m_off.Z + target->GetBobOffset());
|
||||
SetXYZ(pos); // attached lights do not need to go into the regular blockmap
|
||||
Prev = target->Pos();
|
||||
subsector = R_PointInSubsector(Prev);
|
||||
Sector = subsector->sector;
|
||||
// Offset is calculated in relation to the owning actor.
|
||||
DAngle angle = target->Angles.Yaw;
|
||||
double s = angle.Sin();
|
||||
double c = angle.Cos();
|
||||
|
||||
// Some z-coordinate fudging to prevent the light from getting too close to the floor or ceiling planes. With proper attenuation this would render them invisible.
|
||||
// A distance of 5 is needed so that the light's effect doesn't become too small.
|
||||
if (Z() < target->floorz + 5.) SetZ(target->floorz + 5.);
|
||||
else if (Z() > target->ceilingz - 5.) SetZ(target->ceilingz - 5.);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Z() < floorz + 5.) SetZ(floorz + 5.);
|
||||
else if (Z() > ceilingz - 5.) SetZ(ceilingz - 5.);
|
||||
}
|
||||
Pos = target->Vec3Offset(m_off.X * c + m_off.Y * s, m_off.X * s - m_off.Y * c, m_off.Z + target->GetBobOffset());
|
||||
Sector = target->subsector->sector; // Get the render sector. target->Sector is the sector according to play logic.
|
||||
|
||||
// Some z-coordinate fudging to prevent the light from getting too close to the floor or ceiling planes. With proper attenuation this would render them invisible.
|
||||
// A distance of 5 is needed so that the light's effect doesn't become too small.
|
||||
if (Z() < target->floorz + 5.) Pos.Z = target->floorz + 5.;
|
||||
else if (Z() > target->ceilingz - 5.) Pos.Z = target->ceilingz - 5.;
|
||||
|
||||
// The radius being used here is always the maximum possible with the
|
||||
// current settings. This avoids constant relinking of flickering lights
|
||||
|
||||
float intensity;
|
||||
|
||||
if (lighttype == FlickerLight || lighttype == RandomFlickerLight || lighttype == PulseLight)
|
||||
{
|
||||
intensity = float(MAX(args[LIGHT_INTENSITY], args[LIGHT_SECONDARY_INTENSITY]));
|
||||
intensity = float(MAX(GetIntensity(), GetSecondaryIntensity()));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -413,60 +441,6 @@ void ADynamicLight::UpdateLocation()
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void ADynamicLight::SetOrigin(double x, double y, double z, bool moving)
|
||||
{
|
||||
Super::SetOrigin(x, y, z, moving);
|
||||
LinkLight();
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void ADynamicLight::SetOffset(const DVector3 &pos)
|
||||
{
|
||||
m_off = pos;
|
||||
UpdateLocation();
|
||||
}
|
||||
|
||||
static void SetOffset(ADynamicLight *self, double x, double y, double z)
|
||||
{
|
||||
self->SetOffset(DVector3(x, y, z));
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION_NATIVE(ADynamicLight, SetOffset, SetOffset)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(ADynamicLight)
|
||||
PARAM_FLOAT(x)
|
||||
PARAM_FLOAT(y)
|
||||
PARAM_FLOAT(z)
|
||||
self->SetOffset(DVector3(x, y, z));
|
||||
return 0;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// The target pointer in dynamic lights should never be substituted unless
|
||||
// notOld is NULL (which indicates that the object was destroyed by force.)
|
||||
//
|
||||
//==========================================================================
|
||||
size_t ADynamicLight::PointerSubstitution (DObject *old, DObject *notOld)
|
||||
{
|
||||
AActor *saved_target = target;
|
||||
size_t ret = Super::PointerSubstitution(old, notOld);
|
||||
if (notOld != NULL) target = saved_target;
|
||||
return ret;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// These have been copied from the secnode code and modified for the light links
|
||||
|
@ -478,7 +452,7 @@ size_t ADynamicLight::PointerSubstitution (DObject *old, DObject *notOld)
|
|||
//
|
||||
//=============================================================================
|
||||
|
||||
FLightNode * AddLightNode(FLightNode ** thread, void * linkto, ADynamicLight * light, FLightNode *& nextnode)
|
||||
FLightNode * AddLightNode(FLightNode ** thread, void * linkto, FDynamicLight * light, FLightNode *& nextnode)
|
||||
{
|
||||
FLightNode * node;
|
||||
|
||||
|
@ -553,7 +527,7 @@ static FLightNode * DeleteLightNode(FLightNode * node)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
double ADynamicLight::DistToSeg(const DVector3 &pos, seg_t *seg)
|
||||
double FDynamicLight::DistToSeg(const DVector3 &pos, seg_t *seg)
|
||||
{
|
||||
double u, px, py;
|
||||
|
||||
|
@ -588,7 +562,7 @@ struct LightLinkEntry
|
|||
};
|
||||
static TArray<LightLinkEntry> collected_ss;
|
||||
|
||||
void ADynamicLight::CollectWithinRadius(const DVector3 &opos, subsector_t *subSec, float radius)
|
||||
void FDynamicLight::CollectWithinRadius(const DVector3 &opos, subsector_t *subSec, float radius)
|
||||
{
|
||||
if (!subSec) return;
|
||||
collected_ss.Clear();
|
||||
|
@ -641,7 +615,7 @@ void ADynamicLight::CollectWithinRadius(const DVector3 &opos, subsector_t *subSe
|
|||
if (othersub->validcount != ::validcount)
|
||||
{
|
||||
othersub->validcount = ::validcount;
|
||||
collected_ss.Push({ othersub, PosRelative(other) });
|
||||
collected_ss.Push({ othersub, PosRelative(other->frontsector->PortalGroup) });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -670,7 +644,7 @@ void ADynamicLight::CollectWithinRadius(const DVector3 &opos, subsector_t *subSe
|
|||
if (othersub->validcount != ::validcount)
|
||||
{
|
||||
othersub->validcount = ::validcount;
|
||||
collected_ss.Push({ othersub, PosRelative(othersub->sector) });
|
||||
collected_ss.Push({ othersub, PosRelative(othersub->sector->PortalGroup) });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -684,7 +658,7 @@ void ADynamicLight::CollectWithinRadius(const DVector3 &opos, subsector_t *subSe
|
|||
if (othersub->validcount != ::validcount)
|
||||
{
|
||||
othersub->validcount = ::validcount;
|
||||
collected_ss.Push({ othersub, PosRelative(othersub->sector) });
|
||||
collected_ss.Push({ othersub, PosRelative(othersub->sector->PortalGroup) });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -698,7 +672,7 @@ void ADynamicLight::CollectWithinRadius(const DVector3 &opos, subsector_t *subSe
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
void ADynamicLight::LinkLight()
|
||||
void FDynamicLight::LinkLight()
|
||||
{
|
||||
// mark the old light nodes
|
||||
FLightNode * node;
|
||||
|
@ -725,9 +699,9 @@ void ADynamicLight::LinkLight()
|
|||
if (radius>0)
|
||||
{
|
||||
// passing in radius*radius allows us to do a distance check without any calls to sqrt
|
||||
subsector_t * subSec = R_PointInSubsector(Pos());
|
||||
subsector_t * subSec = R_PointInSubsector(Pos);
|
||||
::validcount++;
|
||||
CollectWithinRadius(Pos(), subSec, float(radius*radius));
|
||||
CollectWithinRadius(Pos, subSec, float(radius*radius));
|
||||
|
||||
}
|
||||
|
||||
|
@ -774,33 +748,14 @@ void ADynamicLight::LinkLight()
|
|||
// Deletes the link lists
|
||||
//
|
||||
//==========================================================================
|
||||
void ADynamicLight::UnlinkLight ()
|
||||
void FDynamicLight::UnlinkLight ()
|
||||
{
|
||||
if (owned && target != NULL)
|
||||
{
|
||||
// Delete reference in owning actor
|
||||
for(int c=target->AttachedLights.Size()-1; c>=0; c--)
|
||||
{
|
||||
if (target->AttachedLights[c] == this)
|
||||
{
|
||||
target->AttachedLights.Delete(c);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
while (touching_sides) touching_sides = DeleteLightNode(touching_sides);
|
||||
while (touching_subsectors) touching_subsectors = DeleteLightNode(touching_subsectors);
|
||||
while (touching_sector) touching_sector = DeleteLightNode(touching_sector);
|
||||
shadowmapped = false;
|
||||
}
|
||||
|
||||
void ADynamicLight::OnDestroy()
|
||||
{
|
||||
UnlinkLight();
|
||||
Super::OnDestroy();
|
||||
}
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
|
@ -809,23 +764,19 @@ void ADynamicLight::OnDestroy()
|
|||
|
||||
void AActor::AttachLight(unsigned int count, const FLightDefaults *lightdef)
|
||||
{
|
||||
ADynamicLight *light;
|
||||
FDynamicLight *light;
|
||||
|
||||
if (count < AttachedLights.Size())
|
||||
{
|
||||
light = barrier_cast<ADynamicLight*>(AttachedLights[count]);
|
||||
light = AttachedLights[count];
|
||||
assert(light != NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
light = Spawn<ADynamicLight>(Pos(), NO_REPLACE);
|
||||
light->target = this;
|
||||
light->owned = true;
|
||||
light->ObjectFlags |= OF_Transient;
|
||||
//light->lightflags |= LF_ATTENUATE;
|
||||
light = GetLight();
|
||||
light->SetActor(this, true);
|
||||
AttachedLights.Push(light);
|
||||
}
|
||||
light->flags2&=~MF2_DORMANT;
|
||||
lightdef->ApplyProperties(light);
|
||||
}
|
||||
|
||||
|
@ -844,11 +795,8 @@ void AActor::SetDynamicLights()
|
|||
if (state == NULL) return;
|
||||
if (LightAssociations.Size() > 0)
|
||||
{
|
||||
ADynamicLight *lights, *tmpLight;
|
||||
unsigned int i;
|
||||
|
||||
lights = tmpLight = NULL;
|
||||
|
||||
for (i = 0; i < LightAssociations.Size(); i++)
|
||||
{
|
||||
if (LightAssociations[i]->Sprite() == sprite &&
|
||||
|
@ -871,24 +819,24 @@ void AActor::SetDynamicLights()
|
|||
|
||||
for(;count<AttachedLights.Size();count++)
|
||||
{
|
||||
AttachedLights[count]->flags2 |= MF2_DORMANT;
|
||||
memset(AttachedLights[count]->args, 0, 3*sizeof(args[0]));
|
||||
AttachedLights[count]->Deactivate();
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// Needed for garbage collection
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
size_t AActor::PropagateMark()
|
||||
void AActor::DeleteAttachedLights()
|
||||
{
|
||||
for (unsigned i = 0; i<AttachedLights.Size(); i++)
|
||||
for (auto l : AttachedLights)
|
||||
{
|
||||
GC::Mark(AttachedLights[i]);
|
||||
l->UnlinkLight();
|
||||
l->ReleaseLight();
|
||||
}
|
||||
return Super::PropagateMark();
|
||||
AttachedLights.Clear();
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
@ -901,21 +849,10 @@ void AActor::DeleteAllAttachedLights()
|
|||
{
|
||||
TThinkerIterator<AActor> it;
|
||||
AActor * a;
|
||||
ADynamicLight * l;
|
||||
|
||||
while ((a=it.Next()))
|
||||
{
|
||||
a->AttachedLights.Clear();
|
||||
}
|
||||
|
||||
TThinkerIterator<ADynamicLight> it2;
|
||||
|
||||
l=it2.Next();
|
||||
while (l)
|
||||
{
|
||||
ADynamicLight * ll = it2.Next();
|
||||
if (l->owned) l->Destroy();
|
||||
l=ll;
|
||||
a->DeleteAttachedLights();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -932,7 +869,14 @@ void AActor::RecreateAllAttachedLights()
|
|||
|
||||
while ((a=it.Next()))
|
||||
{
|
||||
a->SetDynamicLights();
|
||||
if (a->IsKindOf(NAME_DynamicLight))
|
||||
{
|
||||
::AttachLight(a);
|
||||
}
|
||||
else
|
||||
{
|
||||
a->SetDynamicLights();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -947,18 +891,17 @@ CCMD(listlights)
|
|||
int walls, sectors, subsecs;
|
||||
int allwalls=0, allsectors=0, allsubsecs = 0;
|
||||
int i=0, shadowcount = 0;
|
||||
ADynamicLight * dl;
|
||||
TThinkerIterator<ADynamicLight> it;
|
||||
FDynamicLight * dl;
|
||||
|
||||
while ((dl=it.Next()))
|
||||
for (dl = level.lights; dl; dl = dl->next)
|
||||
{
|
||||
walls=0;
|
||||
sectors=0;
|
||||
subsecs = 0;
|
||||
Printf("%s at (%f, %f, %f), color = 0x%02x%02x%02x, radius = %f %s %s",
|
||||
dl->target? dl->target->GetClass()->TypeName.GetChars() : dl->GetClass()->TypeName.GetChars(),
|
||||
dl->X(), dl->Y(), dl->Z(), dl->args[LIGHT_RED],
|
||||
dl->args[LIGHT_GREEN], dl->args[LIGHT_BLUE], dl->radius, (dl->lightflags & LF_ATTENUATE)? "attenuated" : "", dl->shadowmapped? "shadowmapped" : "");
|
||||
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" : "");
|
||||
i++;
|
||||
shadowcount += dl->shadowmapped;
|
||||
|
||||
|
|
|
@ -2,11 +2,11 @@
|
|||
#include "c_cvars.h"
|
||||
#include "actor.h"
|
||||
#include "cycler.h"
|
||||
#include "g_levellocals.h"
|
||||
|
||||
EXTERN_CVAR(Bool, gl_lights)
|
||||
EXTERN_CVAR(Bool, gl_attachedlights)
|
||||
|
||||
class ADynamicLight;
|
||||
class FSerializer;
|
||||
|
||||
enum ELightType
|
||||
|
@ -29,7 +29,6 @@ enum
|
|||
LIGHT_BLUE = 2,
|
||||
LIGHT_INTENSITY = 3,
|
||||
LIGHT_SECONDARY_INTENSITY = 4,
|
||||
LIGHT_SCALE = 3,
|
||||
};
|
||||
|
||||
enum LightFlag
|
||||
|
@ -53,7 +52,7 @@ class FLightDefaults
|
|||
public:
|
||||
FLightDefaults(FName name, ELightType type);
|
||||
|
||||
void ApplyProperties(ADynamicLight * light) const;
|
||||
void ApplyProperties(FDynamicLight * light) const;
|
||||
FName GetName() const { return m_Name; }
|
||||
void SetParameter(double p) { m_Param = p; }
|
||||
void SetArg(int arg, int val) { m_Args[arg] = val; }
|
||||
|
@ -93,8 +92,10 @@ protected:
|
|||
bool m_dontlightactors = false;
|
||||
bool m_swapped = false;
|
||||
bool m_spot = false;
|
||||
double m_spotInnerAngle = 10.0;
|
||||
double m_spotOuterAngle = 25.0;
|
||||
bool m_explicitPitch = false;
|
||||
DAngle m_spotInnerAngle = 10.0;
|
||||
DAngle m_spotOuterAngle = 25.0;
|
||||
DAngle m_pitch = 0.0;
|
||||
};
|
||||
|
||||
//==========================================================================
|
||||
|
@ -154,7 +155,7 @@ struct FLightNode
|
|||
FLightNode * nextTarget;
|
||||
FLightNode ** prevLight;
|
||||
FLightNode * nextLight;
|
||||
ADynamicLight * lightsource;
|
||||
FDynamicLight * lightsource;
|
||||
union
|
||||
{
|
||||
side_t * targLine;
|
||||
|
@ -163,73 +164,86 @@ struct FLightNode
|
|||
};
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// Base class
|
||||
//
|
||||
// [CO] I merged everything together in this one class so that I don't have
|
||||
// to create and re-create an excessive amount of objects
|
||||
//
|
||||
|
||||
class ADynamicLight : public AActor
|
||||
struct FDynamicLight
|
||||
{
|
||||
friend class FLightDefaults;
|
||||
DECLARE_CLASS(ADynamicLight, AActor)
|
||||
public:
|
||||
virtual void Tick();
|
||||
void Serialize(FSerializer &arc);
|
||||
void PostSerialize();
|
||||
uint8_t GetRed() const { return args[LIGHT_RED]; }
|
||||
uint8_t GetGreen() const { return args[LIGHT_GREEN]; }
|
||||
uint8_t GetBlue() const { return args[LIGHT_BLUE]; }
|
||||
|
||||
inline DVector3 PosRelative(int portalgroup) const
|
||||
{
|
||||
return Pos + Displacements.getOffset(Sector->PortalGroup, portalgroup);
|
||||
}
|
||||
|
||||
bool ShouldLightActor(AActor *check)
|
||||
{
|
||||
return visibletoplayer && IsActive() && (!(lightflags & LF_DONTLIGHTSELF) || target != check) && !(lightflags&LF_DONTLIGHTACTORS);
|
||||
}
|
||||
|
||||
void SetOffset(const DVector3 &pos)
|
||||
{
|
||||
m_off = pos;
|
||||
}
|
||||
|
||||
|
||||
bool IsActive() const { return m_active; }
|
||||
float GetRadius() const { return (IsActive() ? m_currentRadius * 2.f : 0.f); }
|
||||
int GetRed() const { return pArgs[LIGHT_RED]; }
|
||||
int GetGreen() const { return pArgs[LIGHT_GREEN]; }
|
||||
int GetBlue() const { return pArgs[LIGHT_BLUE]; }
|
||||
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); }
|
||||
void Deactivate() { m_active = false; }
|
||||
void Activate();
|
||||
|
||||
void SetActor(AActor *ac, bool isowned) { target = ac; owned = isowned; }
|
||||
double X() const { return Pos.X; }
|
||||
double Y() const { return Pos.Y; }
|
||||
double Z() const { return Pos.Z; }
|
||||
|
||||
void Tick();
|
||||
void UpdateLocation();
|
||||
void LinkLight();
|
||||
void UnlinkLight();
|
||||
size_t PointerSubstitution(DObject *old, DObject *notOld);
|
||||
|
||||
void BeginPlay();
|
||||
void SetOrigin(double x, double y, double z, bool moving = false);
|
||||
void PostBeginPlay();
|
||||
void OnDestroy() override;
|
||||
void Activate(AActor *activator);
|
||||
void Deactivate(AActor *activator);
|
||||
void SetOffset(const DVector3 &pos);
|
||||
void UpdateLocation();
|
||||
bool IsOwned() const { return owned; }
|
||||
bool IsActive() const { return !(flags2&MF2_DORMANT); }
|
||||
bool IsSubtractive() { return !!(lightflags & LF_SUBTRACTIVE); }
|
||||
bool IsAdditive() { return !!(lightflags & LF_ADDITIVE); }
|
||||
bool IsSpot() { return !!(lightflags & LF_SPOT); }
|
||||
FState *targetState;
|
||||
FLightNode * touching_sides;
|
||||
FLightNode * touching_subsectors;
|
||||
FLightNode * touching_sector;
|
||||
void ReleaseLight();
|
||||
|
||||
private:
|
||||
double DistToSeg(const DVector3 &pos, seg_t *seg);
|
||||
void CollectWithinRadius(const DVector3 &pos, subsector_t *subSec, float radius);
|
||||
|
||||
protected:
|
||||
DVector3 m_off;
|
||||
float m_currentRadius;
|
||||
unsigned int m_lastUpdate;
|
||||
FCycler m_cycler;
|
||||
subsector_t * subsector;
|
||||
|
||||
public:
|
||||
FCycler m_cycler;
|
||||
DVector3 Pos;
|
||||
DVector3 m_off;
|
||||
|
||||
// This date can either come from the owning actor or from a light definition
|
||||
// To avoid having to copy these around every tic, these are pointers to the source data.
|
||||
const DAngle *pSpotInnerAngle;
|
||||
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;
|
||||
|
||||
double specialf1;
|
||||
FDynamicLight *next, *prev;
|
||||
sector_t *Sector;
|
||||
TObjPtr<AActor *> target;
|
||||
FLightNode * touching_sides;
|
||||
FLightNode * touching_subsectors;
|
||||
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;
|
||||
int m_lastUpdate;
|
||||
int mShadowmapIndex;
|
||||
bool m_active;
|
||||
bool visibletoplayer;
|
||||
bool shadowmapped;
|
||||
uint8_t lighttype;
|
||||
bool owned;
|
||||
bool halo;
|
||||
uint8_t color2[3];
|
||||
bool visibletoplayer;
|
||||
bool swapped;
|
||||
bool shadowmapped;
|
||||
int bufferindex;
|
||||
LightFlags lightflags;
|
||||
DAngle SpotInnerAngle;
|
||||
DAngle SpotOuterAngle;
|
||||
|
||||
int mShadowmapIndex;
|
||||
bool explicitpitch;
|
||||
|
||||
};
|
||||
|
|
|
@ -84,34 +84,35 @@ FLightDefaults::FLightDefaults(FName name, ELightType type)
|
|||
m_type = type;
|
||||
}
|
||||
|
||||
void FLightDefaults::ApplyProperties(ADynamicLight * light) const
|
||||
void FLightDefaults::ApplyProperties(FDynamicLight * light) const
|
||||
{
|
||||
auto oldtype = light->lighttype;
|
||||
|
||||
light->m_active = true;
|
||||
light->lighttype = m_type;
|
||||
light->specialf1 = m_Param;
|
||||
light->SetOffset(m_Pos);
|
||||
light->halo = m_halo;
|
||||
for (int a = 0; a < 3; a++) light->args[a] = clamp<int>((int)(m_Args[a]), 0, 255);
|
||||
light->args[LIGHT_INTENSITY] = m_Args[LIGHT_INTENSITY];
|
||||
light->args[LIGHT_SECONDARY_INTENSITY] = m_Args[LIGHT_SECONDARY_INTENSITY];
|
||||
light->lightflags &= ~(LF_ADDITIVE | LF_SUBTRACTIVE | LF_DONTLIGHTSELF);
|
||||
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->lightflags |= LF_SPOT;
|
||||
light->SpotInnerAngle = m_spotInnerAngle;
|
||||
light->SpotOuterAngle = m_spotOuterAngle;
|
||||
light->pSpotInnerAngle = &m_spotInnerAngle;
|
||||
light->pSpotOuterAngle = &m_spotOuterAngle;
|
||||
if (m_explicitPitch) light->pPitch = &m_pitch;
|
||||
else light->pPitch = &light->target->Angles.Pitch;
|
||||
}
|
||||
light->m_tickCount = 0;
|
||||
if (m_type == PulseLight)
|
||||
{
|
||||
float pulseTime = float(m_Param / TICRATE);
|
||||
|
||||
light->m_lastUpdate = level.maptime;
|
||||
if (m_swapped) light->m_cycler.SetParams(float(light->args[LIGHT_SECONDARY_INTENSITY]), float(light->args[LIGHT_INTENSITY]), pulseTime, oldtype == PulseLight);
|
||||
else light->m_cycler.SetParams(float(light->args[LIGHT_INTENSITY]), float(light->args[LIGHT_SECONDARY_INTENSITY]), pulseTime, oldtype == PulseLight);
|
||||
if (m_swapped) light->m_cycler.SetParams(float(m_Args[LIGHT_SECONDARY_INTENSITY]), float(m_Args[LIGHT_INTENSITY]), pulseTime, oldtype == PulseLight);
|
||||
else light->m_cycler.SetParams(float(m_Args[LIGHT_INTENSITY]), float(m_Args[LIGHT_SECONDARY_INTENSITY]), pulseTime, oldtype == PulseLight);
|
||||
light->m_cycler.ShouldCycle(true);
|
||||
light->m_cycler.SetCycleType(CYCLE_Sin);
|
||||
light->m_currentRadius = (float)light->m_cycler.GetVal();
|
||||
|
@ -125,7 +126,8 @@ void FLightDefaults::ApplyProperties(ADynamicLight * light) const
|
|||
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.
|
||||
}
|
||||
|
||||
|
||||
//==========================================================================
|
||||
|
|
|
@ -599,16 +599,6 @@ void gl_PreprocessLevel()
|
|||
|
||||
void gl_CleanLevelData()
|
||||
{
|
||||
// Dynamic lights must be destroyed before the sector information here is deleted.
|
||||
TThinkerIterator<ADynamicLight> it(STAT_DLIGHT);
|
||||
AActor * mo=it.Next();
|
||||
while (mo)
|
||||
{
|
||||
AActor * next = it.Next();
|
||||
mo->Destroy();
|
||||
mo=next;
|
||||
}
|
||||
|
||||
if (level.sides.Size() > 0 && level.sides[0].segs)
|
||||
{
|
||||
delete [] level.sides[0].segs;
|
||||
|
|
|
@ -58,8 +58,8 @@ struct FDynLightData
|
|||
|
||||
|
||||
|
||||
bool gl_GetLight(int group, Plane & p, ADynamicLight * light, bool checkside, FDynLightData &data);
|
||||
void gl_AddLightToList(int group, ADynamicLight * light, FDynLightData &ldata);
|
||||
bool gl_GetLight(int group, Plane & p, FDynamicLight * light, bool checkside, FDynLightData &data);
|
||||
void gl_AddLightToList(int group, FDynamicLight * light, FDynLightData &ldata);
|
||||
void gl_UploadLights(FDynLightData &data);
|
||||
|
||||
|
||||
|
|
|
@ -57,12 +57,13 @@ CVAR (Bool, gl_light_particles, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG);
|
|||
|
||||
CVAR(Int, gl_attenuate, -1, 0); // This is mainly a debug option.
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// Sets up the parameters to render one dynamic light onto one plane
|
||||
//
|
||||
//==========================================================================
|
||||
bool gl_GetLight(int group, Plane & p, ADynamicLight * light, bool checkside, FDynLightData &ldata)
|
||||
bool gl_GetLight(int group, Plane & p, FDynamicLight * light, bool checkside, FDynLightData &ldata)
|
||||
{
|
||||
DVector3 pos = light->PosRelative(group);
|
||||
float radius = (light->GetRadius());
|
||||
|
@ -85,7 +86,7 @@ bool gl_GetLight(int group, Plane & p, ADynamicLight * light, bool checkside, FD
|
|||
// Add one dynamic light to the light data list
|
||||
//
|
||||
//==========================================================================
|
||||
void gl_AddLightToList(int group, ADynamicLight * light, FDynLightData &ldata)
|
||||
void gl_AddLightToList(int group, FDynamicLight * light, FDynLightData &ldata)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
|
@ -136,14 +137,15 @@ void gl_AddLightToList(int group, ADynamicLight * light, FDynLightData &ldata)
|
|||
if (light->IsSpot())
|
||||
{
|
||||
lightType = 1.0f;
|
||||
spotInnerAngle = light->SpotInnerAngle.Cos();
|
||||
spotOuterAngle = light->SpotOuterAngle.Cos();
|
||||
spotInnerAngle = (float)light->pSpotInnerAngle->Cos();
|
||||
spotOuterAngle = (float)light->pSpotOuterAngle->Cos();
|
||||
|
||||
DAngle negPitch = -light->Angles.Pitch;
|
||||
DAngle negPitch = -*light->pPitch;
|
||||
DAngle Angle = light->target->Angles.Yaw;
|
||||
double xzLen = negPitch.Cos();
|
||||
spotDirX = -light->Angles.Yaw.Cos() * xzLen;
|
||||
spotDirY = -negPitch.Sin();
|
||||
spotDirZ = -light->Angles.Yaw.Sin() * xzLen;
|
||||
spotDirX = float(-Angle.Cos() * xzLen);
|
||||
spotDirY = float(-negPitch.Sin());
|
||||
spotDirZ = float(-Angle.Sin() * xzLen);
|
||||
}
|
||||
|
||||
float *data = &ldata.arrays[i][ldata.arrays[i].Reserve(16)];
|
||||
|
|
|
@ -96,11 +96,11 @@ CUSTOM_CVAR (Bool, gl_light_shadowmap, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
|
|||
{
|
||||
if (!self)
|
||||
{
|
||||
// Unset any residual shadow map indices in the light actors.
|
||||
TThinkerIterator<ADynamicLight> it(STAT_DLIGHT);
|
||||
while (auto light = it.Next())
|
||||
{
|
||||
auto light = level.lights;
|
||||
while (light)
|
||||
{
|
||||
light->mShadowmapIndex = 1024;
|
||||
light = light->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -148,10 +148,10 @@ void FShadowMap::Update()
|
|||
UpdateCycles.Unclock();
|
||||
}
|
||||
|
||||
bool FShadowMap::ShadowTest(ADynamicLight *light, const DVector3 &pos)
|
||||
bool FShadowMap::ShadowTest(FDynamicLight *light, const DVector3 &pos)
|
||||
{
|
||||
if (light->shadowmapped && light->radius > 0.0 && IsEnabled() && mAABBTree)
|
||||
return mAABBTree->RayTest(light->Pos(), pos) >= 1.0f;
|
||||
if (light->shadowmapped && light->GetRadius() > 0.0 && IsEnabled() && mAABBTree)
|
||||
return mAABBTree->RayTest(light->Pos, pos) >= 1.0f;
|
||||
else
|
||||
return true;
|
||||
}
|
||||
|
@ -167,8 +167,7 @@ void FShadowMap::UploadLights()
|
|||
int lightindex = 0;
|
||||
|
||||
// Todo: this should go through the blockmap in a spiral pattern around the player so that closer lights are preferred.
|
||||
TThinkerIterator<ADynamicLight> it(STAT_DLIGHT);
|
||||
while (auto light = it.Next())
|
||||
for (auto light = level.lights; light; light = light->next)
|
||||
{
|
||||
LightsProcessed++;
|
||||
if (light->shadowmapped && lightindex < 1024 * 4)
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
#include "tarray.h"
|
||||
#include <memory>
|
||||
|
||||
class ADynamicLight;
|
||||
struct FDynamicLight;
|
||||
struct level_info_t;
|
||||
|
||||
class FShadowMap
|
||||
|
@ -21,7 +21,7 @@ public:
|
|||
void Update();
|
||||
|
||||
// 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);
|
||||
bool ShadowTest(FDynamicLight *light, const DVector3 &pos);
|
||||
|
||||
// Returns true if gl_light_shadowmap is enabled and supported by the hardware
|
||||
bool IsEnabled() const;
|
||||
|
|
|
@ -124,9 +124,9 @@ void GLFlat::SetupSubsectorLights(int pass, subsector_t * sub, int *dli)
|
|||
FLightNode * node = sub->lighthead;
|
||||
while (node)
|
||||
{
|
||||
ADynamicLight * light = node->lightsource;
|
||||
FDynamicLight * light = node->lightsource;
|
||||
|
||||
if (light->flags2&MF2_DORMANT)
|
||||
if (!light->IsActive())
|
||||
{
|
||||
node=node->nextLight;
|
||||
continue;
|
||||
|
@ -135,7 +135,7 @@ void GLFlat::SetupSubsectorLights(int pass, subsector_t * sub, int *dli)
|
|||
|
||||
// we must do the side check here because gl_SetupLight needs the correct plane orientation
|
||||
// which we don't have for Legacy-style 3D-floors
|
||||
double planeh = plane.plane.ZatPoint(light);
|
||||
double planeh = plane.plane.ZatPoint(light->Pos);
|
||||
if (gl_lights_checkside && ((planeh<light->Z() && ceiling) || (planeh>light->Z() && !ceiling)))
|
||||
{
|
||||
node = node->nextLight;
|
||||
|
|
|
@ -956,8 +956,8 @@ void FGLRenderer::RenderView (player_t* player)
|
|||
drawer.SetFixedColormap (player);
|
||||
|
||||
// Check if there's some lights. If not some code can be skipped.
|
||||
TThinkerIterator<ADynamicLight> it(STAT_DLIGHT);
|
||||
mLightCount = ((it.Next()) != NULL);
|
||||
FDynamicLight * dl = level.lights;
|
||||
mLightCount = ((dl->next) != nullptr);
|
||||
|
||||
mShadowMap.Update();
|
||||
sector_t * viewsector = drawer.RenderViewpoint(player->camera, NULL, r_viewpoint.FieldOfView.Degrees, ratio, fovratio, true, true);
|
||||
|
@ -988,8 +988,8 @@ void GLSceneDrawer::WriteSavePic (player_t *player, FileWriter *file, int width,
|
|||
if (!gl.legacyMode) GLRenderer->mLights->Clear();
|
||||
|
||||
// Check if there's some lights. If not some code can be skipped.
|
||||
TThinkerIterator<ADynamicLight> it(STAT_DLIGHT);
|
||||
GLRenderer->mLightCount = ((it.Next()) != NULL);
|
||||
FDynamicLight * dl = level.lights;
|
||||
GLRenderer->mLightCount = ((dl->next) != nullptr);
|
||||
|
||||
sector_t *viewsector = RenderViewpoint(players[consoleplayer].camera, &bounds,
|
||||
r_viewpoint.FieldOfView.Degrees, 1.6f, 1.6f, true, false);
|
||||
|
|
|
@ -63,7 +63,7 @@ T smoothstep(const T edge0, const T edge1, const T x)
|
|||
|
||||
void gl_SetDynSpriteLight(AActor *self, float x, float y, float z, subsector_t * subsec)
|
||||
{
|
||||
ADynamicLight *light;
|
||||
FDynamicLight *light;
|
||||
float frac, lr, lg, lb;
|
||||
float radius;
|
||||
float out[3] = { 0.0f, 0.0f, 0.0f };
|
||||
|
@ -73,7 +73,7 @@ void gl_SetDynSpriteLight(AActor *self, float x, float y, float z, subsector_t *
|
|||
while (node)
|
||||
{
|
||||
light=node->lightsource;
|
||||
if (light->visibletoplayer && !(light->flags2&MF2_DORMANT) && (!(light->lightflags&LF_DONTLIGHTSELF) || light->target != self || !self) && !(light->lightflags&LF_DONTLIGHTACTORS))
|
||||
if (light->ShouldLightActor(self))
|
||||
{
|
||||
float dist;
|
||||
FVector3 L;
|
||||
|
@ -107,13 +107,14 @@ void gl_SetDynSpriteLight(AActor *self, float x, float y, float z, subsector_t *
|
|||
if (light->IsSpot())
|
||||
{
|
||||
L *= -1.0f / dist;
|
||||
DAngle negPitch = -light->Angles.Pitch;
|
||||
DAngle negPitch = -*light->pPitch;
|
||||
DAngle Angle = light->target->Angles.Yaw;
|
||||
double xyLen = negPitch.Cos();
|
||||
double spotDirX = -light->Angles.Yaw.Cos() * xyLen;
|
||||
double spotDirY = -light->Angles.Yaw.Sin() * xyLen;
|
||||
double spotDirX = -Angle.Cos() * xyLen;
|
||||
double spotDirY = -Angle.Sin() * xyLen;
|
||||
double spotDirZ = -negPitch.Sin();
|
||||
double cosDir = L.X * spotDirX + L.Y * spotDirY + L.Z * spotDirZ;
|
||||
frac *= (float)smoothstep(light->SpotOuterAngle.Cos(), light->SpotInnerAngle.Cos(), cosDir);
|
||||
frac *= (float)smoothstep(light->pSpotOuterAngle->Cos(), light->pSpotInnerAngle->Cos(), cosDir);
|
||||
}
|
||||
|
||||
if (frac > 0 && GLRenderer->mShadowMap.ShadowTest(light, { x, y, z }))
|
||||
|
@ -175,7 +176,7 @@ int gl_SetDynModelLight(AActor *self, int dynlightindex)
|
|||
|
||||
if (self)
|
||||
{
|
||||
static std::vector<ADynamicLight*> addedLights; // static so that we build up a reserve (memory allocations stop)
|
||||
static std::vector<FDynamicLight*> addedLights; // static so that we build up a reserve (memory allocations stop)
|
||||
|
||||
addedLights.clear();
|
||||
|
||||
|
@ -189,8 +190,8 @@ int gl_SetDynModelLight(AActor *self, int dynlightindex)
|
|||
FLightNode * node = subsector->lighthead;
|
||||
while (node) // check all lights touching a subsector
|
||||
{
|
||||
ADynamicLight *light = node->lightsource;
|
||||
if (light->visibletoplayer && !(light->flags2&MF2_DORMANT) && (!(light->lightflags&LF_DONTLIGHTSELF) || light->target != self) && !(light->lightflags&LF_DONTLIGHTACTORS))
|
||||
FDynamicLight *light = node->lightsource;
|
||||
if (light->ShouldLightActor(self))
|
||||
{
|
||||
int group = subsector->sector->PortalGroup;
|
||||
DVector3 pos = light->PosRelative(group);
|
||||
|
|
|
@ -15,7 +15,7 @@ struct F3DFloor;
|
|||
struct model_t;
|
||||
struct FSpriteModelFrame;
|
||||
struct particle_t;
|
||||
class ADynamicLight;
|
||||
struct FDynamicLight;
|
||||
class FMaterial;
|
||||
struct GLDrawList;
|
||||
struct GLSkyInfo;
|
||||
|
@ -205,7 +205,7 @@ private:
|
|||
void SplitWall(sector_t * frontsector, bool translucent);
|
||||
|
||||
void SetupLights();
|
||||
bool PrepareLight(ADynamicLight * light, int pass);
|
||||
bool PrepareLight(FDynamicLight * light, int pass);
|
||||
void MakeVertices(bool nosplit);
|
||||
void RenderWall(int textured);
|
||||
void RenderTextured(int rflags);
|
||||
|
|
|
@ -102,11 +102,11 @@ void GLWall::SetupLights()
|
|||
// Iterate through all dynamic lights which touch this wall and render them
|
||||
while (node)
|
||||
{
|
||||
if (!(node->lightsource->flags2&MF2_DORMANT))
|
||||
if (node->lightsource->IsActive())
|
||||
{
|
||||
iter_dlight++;
|
||||
|
||||
DVector3 posrel = node->lightsource->PosRelative(seg->frontsector);
|
||||
DVector3 posrel = node->lightsource->PosRelative(seg->frontsector->PortalGroup);
|
||||
float x = posrel.X;
|
||||
float y = posrel.Y;
|
||||
float z = posrel.Z;
|
||||
|
|
|
@ -4830,6 +4830,7 @@ void AActor::OnDestroy ()
|
|||
// note: if OnDestroy is ever made optional, E_WorldThingDestroyed should still be called for ANY thing.
|
||||
E_WorldThingDestroyed(this);
|
||||
|
||||
DeleteAttachedLights();
|
||||
ClearRenderSectorList();
|
||||
ClearRenderLineList();
|
||||
|
||||
|
@ -5536,27 +5537,26 @@ AActor *P_SpawnMapThing (FMapThing *mthing, int position)
|
|||
(mthing->fillcolor & 0xff00) >> 8, (mthing->fillcolor & 0xff)) << 24);
|
||||
|
||||
// allow color strings for lights and reshuffle the args for spot lights
|
||||
if (i->IsDescendantOf(RUNTIME_CLASS(ADynamicLight)))
|
||||
if (i->IsDescendantOf(NAME_DynamicLight))
|
||||
{
|
||||
auto light = static_cast<ADynamicLight*>(mobj);
|
||||
if (mthing->arg0str != NAME_None)
|
||||
{
|
||||
PalEntry color = V_GetColor(nullptr, mthing->arg0str);
|
||||
light->args[0] = color.r;
|
||||
light->args[1] = color.g;
|
||||
light->args[2] = color.b;
|
||||
mobj->args[0] = color.r;
|
||||
mobj->args[1] = color.g;
|
||||
mobj->args[2] = color.b;
|
||||
}
|
||||
else if (light->lightflags & LF_SPOT)
|
||||
else if (mobj->IntVar(NAME_lightflags) & LF_SPOT)
|
||||
{
|
||||
light->args[0] = RPART(mthing->args[0]);
|
||||
light->args[1] = GPART(mthing->args[0]);
|
||||
light->args[2] = BPART(mthing->args[0]);
|
||||
mobj->args[0] = RPART(mthing->args[0]);
|
||||
mobj->args[1] = GPART(mthing->args[0]);
|
||||
mobj->args[2] = BPART(mthing->args[0]);
|
||||
}
|
||||
|
||||
if (light->lightflags & LF_SPOT)
|
||||
if (mobj->IntVar(NAME_lightflags) & LF_SPOT)
|
||||
{
|
||||
light->SpotInnerAngle = double(mthing->args[1]);
|
||||
light->SpotOuterAngle = double(mthing->args[2]);
|
||||
mobj->AngleVar(NAME_SpotInnerAngle) = double(mthing->args[1]);
|
||||
mobj->AngleVar(NAME_SpotOuterAngle) = double(mthing->args[2]);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -32,7 +32,7 @@ class RenderMemory;
|
|||
class PolyTranslucentObject;
|
||||
class PolyDrawSectorPortal;
|
||||
class PolyDrawLinePortal;
|
||||
class ADynamicLight;
|
||||
struct FDynamicLight;
|
||||
|
||||
class PolyRenderThread
|
||||
{
|
||||
|
@ -54,7 +54,7 @@ public:
|
|||
std::vector<std::unique_ptr<PolyDrawSectorPortal>> SectorPortals;
|
||||
std::vector<std::unique_ptr<PolyDrawLinePortal>> LinePortals;
|
||||
|
||||
TArray<ADynamicLight*> AddedLightsArray;
|
||||
TArray<FDynamicLight*> AddedLightsArray;
|
||||
|
||||
// Make sure texture can accessed safely
|
||||
void PrepareTexture(FTexture *texture, FRenderStyle style);
|
||||
|
|
|
@ -127,8 +127,8 @@ void PolyModelRenderer::AddLights(AActor *actor)
|
|||
FLightNode * node = subsector->lighthead;
|
||||
while (node) // check all lights touching a subsector
|
||||
{
|
||||
ADynamicLight *light = node->lightsource;
|
||||
if (light->visibletoplayer && !(light->flags2&MF2_DORMANT) && (!(light->lightflags&LF_DONTLIGHTSELF) || light->target != actor) && !(light->lightflags&LF_DONTLIGHTACTORS))
|
||||
FDynamicLight *light = node->lightsource;
|
||||
if (light->ShouldLightActor(actor))
|
||||
{
|
||||
int group = subsector->sector->PortalGroup;
|
||||
DVector3 pos = light->PosRelative(group);
|
||||
|
@ -153,7 +153,7 @@ void PolyModelRenderer::AddLights(AActor *actor)
|
|||
Lights = Thread->FrameMemory->AllocMemory<PolyLight>(NumLights);
|
||||
for (int i = 0; i < NumLights; i++)
|
||||
{
|
||||
ADynamicLight *lightsource = addedLights[i];
|
||||
FDynamicLight *lightsource = addedLights[i];
|
||||
|
||||
bool is_point_light = (lightsource->lightflags & LF_ATTENUATE) != 0;
|
||||
|
||||
|
|
|
@ -289,7 +289,7 @@ void RenderPolyPlane::SetDynLights(PolyRenderThread *thread, PolyDrawArgs &args,
|
|||
FLightNode *cur_node = light_list;
|
||||
while (cur_node)
|
||||
{
|
||||
if (!(cur_node->lightsource->flags2&MF2_DORMANT))
|
||||
if (cur_node->lightsource->IsActive())
|
||||
max_lights++;
|
||||
cur_node = cur_node->nextLight;
|
||||
}
|
||||
|
@ -307,7 +307,7 @@ void RenderPolyPlane::SetDynLights(PolyRenderThread *thread, PolyDrawArgs &args,
|
|||
cur_node = light_list;
|
||||
while (cur_node)
|
||||
{
|
||||
if (!(cur_node->lightsource->flags2&MF2_DORMANT))
|
||||
if (cur_node->lightsource->IsActive())
|
||||
{
|
||||
bool is_point_light = (cur_node->lightsource->lightflags & LF_ATTENUATE) != 0;
|
||||
|
||||
|
|
|
@ -384,8 +384,8 @@ void RenderPolySprite::SetDynlight(AActor *thing, PolyDrawArgs &args)
|
|||
auto node = thing->Sector->lighthead;
|
||||
while (node != nullptr)
|
||||
{
|
||||
ADynamicLight *light = node->lightsource;
|
||||
if (light->visibletoplayer && !(light->flags2&MF2_DORMANT) && (!(light->lightflags&LF_DONTLIGHTSELF) || light->target != thing) && !(light->lightflags&LF_DONTLIGHTACTORS))
|
||||
FDynamicLight *light = node->lightsource;
|
||||
if (light->ShouldLightActor(thing))
|
||||
{
|
||||
float lx = (float)(light->X() - thing->X());
|
||||
float ly = (float)(light->Y() - thing->Y());
|
||||
|
|
|
@ -425,7 +425,7 @@ void RenderPolyWall::SetDynLights(PolyRenderThread *thread, PolyDrawArgs &args)
|
|||
FLightNode *cur_node = light_list;
|
||||
while (cur_node)
|
||||
{
|
||||
if (!(cur_node->lightsource->flags2&MF2_DORMANT))
|
||||
if (cur_node->lightsource->IsActive())
|
||||
max_lights++;
|
||||
cur_node = cur_node->nextLight;
|
||||
}
|
||||
|
@ -443,7 +443,7 @@ void RenderPolyWall::SetDynLights(PolyRenderThread *thread, PolyDrawArgs &args)
|
|||
cur_node = light_list;
|
||||
while (cur_node)
|
||||
{
|
||||
if (!(cur_node->lightsource->flags2&MF2_DORMANT))
|
||||
if (cur_node->lightsource->IsActive())
|
||||
{
|
||||
bool is_point_light = (cur_node->lightsource->lightflags & LF_ATTENUATE) != 0;
|
||||
|
||||
|
|
|
@ -820,7 +820,7 @@ class GLDefsParser
|
|||
break;
|
||||
case LIGHTTAG_SCALE:
|
||||
floatVal = ParseFloat(sc);
|
||||
defaults->SetArg(LIGHT_SCALE, clamp((int)(floatVal * 255), 1, 1024));
|
||||
defaults->SetArg(LIGHT_INTENSITY, clamp((int)(floatVal * 255), 1, 1024));
|
||||
break;
|
||||
case LIGHTTAG_SUBTRACTIVE:
|
||||
defaults->SetSubtractive(ParseInt(sc) != 0);
|
||||
|
|
|
@ -419,24 +419,11 @@ static FFlagDef MoreFlagDefs[] =
|
|||
DEFINE_DUMMY_FLAG(SERVERSIDEONLY, false),
|
||||
};
|
||||
|
||||
static FFlagDef DynLightFlagDefs[] =
|
||||
{
|
||||
// PlayerPawn flags
|
||||
DEFINE_FLAG(LF, SUBTRACTIVE, ADynamicLight, lightflags),
|
||||
DEFINE_FLAG(LF, ADDITIVE, ADynamicLight, lightflags),
|
||||
DEFINE_FLAG(LF, DONTLIGHTSELF, ADynamicLight, lightflags),
|
||||
DEFINE_FLAG(LF, ATTENUATE, ADynamicLight, lightflags),
|
||||
DEFINE_FLAG(LF, NOSHADOWMAP, ADynamicLight, lightflags),
|
||||
DEFINE_FLAG(LF, DONTLIGHTACTORS, ADynamicLight, lightflags),
|
||||
DEFINE_FLAG(LF, SPOT, ADynamicLight, lightflags),
|
||||
};
|
||||
|
||||
static const struct FFlagList { const PClass * const *Type; FFlagDef *Defs; int NumDefs; int Use; } FlagLists[] =
|
||||
{
|
||||
{ &RUNTIME_CLASS_CASTLESS(AActor), ActorFlagDefs, countof(ActorFlagDefs), 3 }, // -1 to account for the terminator
|
||||
{ &RUNTIME_CLASS_CASTLESS(AActor), MoreFlagDefs, countof(MoreFlagDefs), 1 },
|
||||
{ &RUNTIME_CLASS_CASTLESS(AActor), InternalActorFlagDefs, countof(InternalActorFlagDefs), 2 },
|
||||
{ &RUNTIME_CLASS_CASTLESS(ADynamicLight),DynLightFlagDefs, countof(DynLightFlagDefs), 3 },
|
||||
};
|
||||
#define NUM_FLAG_LISTS (countof(FlagLists))
|
||||
|
||||
|
|
|
@ -204,7 +204,7 @@ namespace swrenderer
|
|||
FLightNode *cur_node = light_list;
|
||||
while (cur_node)
|
||||
{
|
||||
if (!(cur_node->lightsource->flags2&MF2_DORMANT))
|
||||
if (cur_node->lightsource->IsActive())
|
||||
max_lights++;
|
||||
cur_node = cur_node->nextLight;
|
||||
}
|
||||
|
@ -216,7 +216,7 @@ namespace swrenderer
|
|||
cur_node = light_list;
|
||||
while (cur_node)
|
||||
{
|
||||
if (!(cur_node->lightsource->flags2&MF2_DORMANT))
|
||||
if (cur_node->lightsource->IsActive())
|
||||
{
|
||||
double lightX = cur_node->lightsource->X() - Thread->Viewport->viewpoint.Pos.X;
|
||||
double lightY = cur_node->lightsource->Y() - Thread->Viewport->viewpoint.Pos.Y;
|
||||
|
|
|
@ -230,7 +230,7 @@ namespace swrenderer
|
|||
VisiblePlaneLight *cur_node = light_list;
|
||||
while (cur_node)
|
||||
{
|
||||
if (!(cur_node->lightsource->flags2&MF2_DORMANT))
|
||||
if (cur_node->lightsource->IsActive())
|
||||
max_lights++;
|
||||
cur_node = cur_node->next;
|
||||
}
|
||||
|
|
|
@ -76,7 +76,7 @@ namespace swrenderer
|
|||
|
||||
while (node)
|
||||
{
|
||||
if (!(node->lightsource->flags2&MF2_DORMANT) && (height.PointOnSide(node->lightsource->Pos()) > 0))
|
||||
if (node->lightsource->IsActive() && (height.PointOnSide(node->lightsource->Pos) > 0))
|
||||
{
|
||||
bool found = false;
|
||||
VisiblePlaneLight *light_node = lights;
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
#include "r_state.h"
|
||||
#include "swrenderer/r_memory.h"
|
||||
|
||||
class ADynamicLight;
|
||||
struct FDynamicLight;
|
||||
struct FLightNode;
|
||||
struct FDynamicColormap;
|
||||
struct FSectorPortal;
|
||||
|
@ -38,7 +38,7 @@ namespace swrenderer
|
|||
|
||||
struct VisiblePlaneLight
|
||||
{
|
||||
ADynamicLight *lightsource;
|
||||
FDynamicLight *lightsource;
|
||||
VisiblePlaneLight *next;
|
||||
};
|
||||
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
class DrawerCommandQueue;
|
||||
typedef std::shared_ptr<DrawerCommandQueue> DrawerCommandQueuePtr;
|
||||
class RenderMemory;
|
||||
class ADynamicLight;
|
||||
struct FDynamicLight;
|
||||
|
||||
EXTERN_CVAR(Bool, r_models);
|
||||
extern bool r_modelscene;
|
||||
|
@ -77,7 +77,7 @@ namespace swrenderer
|
|||
std::unique_ptr<LightVisibility> Light;
|
||||
DrawerCommandQueuePtr DrawQueue;
|
||||
|
||||
TArray<ADynamicLight*> AddedLightsArray;
|
||||
TArray<FDynamicLight*> AddedLightsArray;
|
||||
|
||||
std::thread thread;
|
||||
|
||||
|
|
|
@ -168,8 +168,8 @@ namespace swrenderer
|
|||
FLightNode * node = subsector->lighthead;
|
||||
while (node) // check all lights touching a subsector
|
||||
{
|
||||
ADynamicLight *light = node->lightsource;
|
||||
if (light->visibletoplayer && !(light->flags2&MF2_DORMANT) && (!(light->lightflags&LF_DONTLIGHTSELF) || light->target != actor) && !(light->lightflags&LF_DONTLIGHTACTORS))
|
||||
FDynamicLight *light = node->lightsource;
|
||||
if (light->ShouldLightActor(actor))
|
||||
{
|
||||
int group = subsector->sector->PortalGroup;
|
||||
DVector3 pos = light->PosRelative(group);
|
||||
|
@ -194,7 +194,7 @@ namespace swrenderer
|
|||
Lights = Thread->FrameMemory->AllocMemory<PolyLight>(NumLights);
|
||||
for (int i = 0; i < NumLights; i++)
|
||||
{
|
||||
ADynamicLight *lightsource = addedLights[i];
|
||||
FDynamicLight *lightsource = addedLights[i];
|
||||
|
||||
bool is_point_light = (lightsource->lightflags & LF_ATTENUATE) != 0;
|
||||
|
||||
|
|
|
@ -254,8 +254,8 @@ namespace swrenderer
|
|||
auto node = vis->sector->lighthead;
|
||||
while (node != nullptr)
|
||||
{
|
||||
ADynamicLight *light = node->lightsource;
|
||||
if (light->visibletoplayer && !(light->flags2&MF2_DORMANT) && (!(light->lightflags&LF_DONTLIGHTSELF) || light->target != thing) && !(light->lightflags&LF_DONTLIGHTACTORS))
|
||||
FDynamicLight *light = node->lightsource;
|
||||
if (light->ShouldLightActor(thing))
|
||||
{
|
||||
float lx = (float)(light->X() - thing->X());
|
||||
float ly = (float)(light->Y() - thing->Y());
|
||||
|
|
|
@ -1,10 +1,20 @@
|
|||
class DynamicLight : Actor native
|
||||
class DynamicLight : Actor
|
||||
{
|
||||
native double SpotInnerAngle;
|
||||
native double SpotOuterAngle;
|
||||
double SpotInnerAngle;
|
||||
double SpotOuterAngle;
|
||||
private int lighttype;
|
||||
private int lightflags;
|
||||
|
||||
property SpotInnerAngle: SpotInnerAngle;
|
||||
property SpotOuterAngle: SpotOuterAngle;
|
||||
|
||||
flagdef subtractive: lightflags, 0;
|
||||
flagdef additive: lightflags, 1;
|
||||
flagdef dontlightself: lightflags, 2;
|
||||
flagdef attenuate: lightflags, 3;
|
||||
flagdef noshadowmap: lightflags, 4;
|
||||
flagdef dontlightactors: lightflags, 5;
|
||||
flagdef spot: lightflags, 6;
|
||||
|
||||
enum EArgs
|
||||
{
|
||||
|
@ -30,6 +40,9 @@ class DynamicLight : Actor native
|
|||
};
|
||||
|
||||
native void SetOffset(Vector3 offset);
|
||||
private native void AttachLight();
|
||||
private native void ActivateLight();
|
||||
private native void DeactivateLight();
|
||||
|
||||
Default
|
||||
{
|
||||
|
@ -44,6 +57,46 @@ class DynamicLight : Actor native
|
|||
+FIXMAPTHINGPOS
|
||||
+INVISIBLE
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
override void Tick()
|
||||
{
|
||||
// Lights do not call the super method.
|
||||
}
|
||||
|
||||
override void BeginPlay()
|
||||
{
|
||||
ChangeStatNum(STAT_DLIGHT);
|
||||
AttachLight();
|
||||
}
|
||||
|
||||
override void PostBeginPlay()
|
||||
{
|
||||
Super.PostBeginPlay();
|
||||
|
||||
if (!(SpawnFlags & MTF_DORMANT))
|
||||
{
|
||||
Activate(self);
|
||||
}
|
||||
}
|
||||
|
||||
override void Activate(Actor activator)
|
||||
{
|
||||
bDormant = false;
|
||||
ActivateLight();
|
||||
}
|
||||
|
||||
override void Deactivate(Actor activator)
|
||||
{
|
||||
bDormant = true;
|
||||
DeactivateLight();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue