Merge remote-tracking branch 'gzdoom/master' into big_beautiful_merge

This commit is contained in:
Magnus Norddahl 2025-08-06 21:06:53 +02:00
commit 3fdd22ef91
1433 changed files with 484787 additions and 9566 deletions

View file

@ -296,7 +296,7 @@ DoomLevelMesh::DoomLevelMesh(FLevelLocals& doomMap)
// Collect all the models we want to bake into the level mesh
if (lm_models)
{
TThinkerIterator<AActor> it(&doomMap, PClass::FindClass("Actor"), STAT_STATIC, true);
TThinkerIterator<AActor> it(&doomMap, PClass::FindClass("Actor"), STAT_STATIC, FThinkerIteratorMode::forceSearch);
AActor* thing;
while ((thing = it.Next()) != nullptr)
{
@ -650,7 +650,9 @@ void DoomLevelMesh::AddSidesToDrawLists(const TArray<int>& sides, LevelMeshDrawL
int dynlightindex = -1;
if (di->Level->HasDynamicLights && !di->isFullbrightScene() && decals[0].texture != nullptr && !lm_dynlights)
{
#ifdef NEEDS_BIG_BEAUTIFUL_MERGE_PORTING
dynlightindex = decals[0].SetupLights(di, state, lightdata, level.sides[sideIndex].lighthead);
#endif
}
for (const HWDecalCreateInfo& info : decals)
@ -1046,7 +1048,7 @@ void DoomLevelMesh::UpdateLightShadows(sector_t* sector)
{
for (FSection& section : level.sections.SectionsForSector(sector))
{
int lightcount = 0;
#ifdef NEEDS_BIG_BEAUTIFUL_MERGE_PORTING
FLightNode* cur = section.lighthead;
while (cur)
{
@ -1057,6 +1059,7 @@ void DoomLevelMesh::UpdateLightShadows(sector_t* sector)
}
cur = cur->nextLight;
}
#endif
}
}
@ -1182,12 +1185,16 @@ void DoomLevelMesh::UpdateSideLightList(FLevelLocals& doomMap, unsigned int side
return;
FreeLightList(sideBlock.Lights.Start, sideBlock.Lights.Count);
#ifdef NEEDS_BIG_BEAUTIFUL_MERGE_PORTING
sideBlock.Lights = CreateLightList(sub->section->lighthead, sub->sector->PortalGroup);
#endif
}
else
{
FreeLightList(sideBlock.Lights.Start, sideBlock.Lights.Count);
#ifdef NEEDS_BIG_BEAUTIFUL_MERGE_PORTING
sideBlock.Lights = CreateLightList(side->lighthead, side->sector->PortalGroup);
#endif
}
int surf = Sides[sideIndex].FirstSurface;
@ -1215,7 +1222,9 @@ void DoomLevelMesh::UpdateFlatLightList(FLevelLocals& doomMap, unsigned int sect
sector_t* sector = &doomMap.sectors[sectorIndex];
for (FSection& section : doomMap.sections.SectionsForSector(sectorIndex))
{
#ifdef NEEDS_BIG_BEAUTIFUL_MERGE_PORTING
Flats[sectorIndex].Lights.Push(CreateLightList(section.lighthead, section.sector->PortalGroup));
#endif
}
int surf = Flats[sectorIndex].FirstSurface;
@ -1373,7 +1382,9 @@ void DoomLevelMesh::CreateSide(FLevelLocals& doomMap, unsigned int sideIndex)
{
if (!lightlistCreated)
{
#ifdef NEEDS_BIG_BEAUTIFUL_MERGE_PORTING
sideBlock.Lights = CreateLightList(sub->section->lighthead, sub->sector->PortalGroup);
#endif
lightlistCreated = true;
}
@ -1388,7 +1399,9 @@ void DoomLevelMesh::CreateSide(FLevelLocals& doomMap, unsigned int sideIndex)
}
else
{
#ifdef NEEDS_BIG_BEAUTIFUL_MERGE_PORTING
sideBlock.Lights = CreateLightList(side->lighthead, side->sector->PortalGroup);
#endif
subsector_t* sub = seg->Subsector;
sector_t* front = side->sector;
@ -1480,7 +1493,11 @@ void DoomLevelMesh::CreateFlat(FLevelLocals& doomMap, unsigned int sectorIndex)
int lightlistSection = 0;
for (FSection& section : doomMap.sections.SectionsForSector(sectorIndex))
{
#ifdef NEEDS_BIG_BEAUTIFUL_MERGE_PORTING
Flats[sectorIndex].Lights.Push(CreateLightList(section.lighthead, section.sector->PortalGroup));
#else
Flats[sectorIndex].Lights.Push({});
#endif
const auto& lightlist = Flats[sectorIndex].Lights.Last();
HWFlatMeshHelper result;

View file

@ -321,7 +321,7 @@ void HWDrawInfo::AddLine (seg_t *seg, bool portalclip, FRenderState& state)
{
if (!(currentsubsector->flags & SSECMF_DRAWN))
{
if (clipper.SafeCheckRange(startAngle, endAngle) && (!r_radarclipper || (Level->flags3 & LEVEL3_NOFOGOFWAR)))
if (clipper.SafeCheckRange(startAngle, endAngle) && !Viewpoint.IsAllowedOoB())
{
currentsubsector->flags |= SSECMF_DRAWN;
}
@ -338,7 +338,7 @@ void HWDrawInfo::AddLine (seg_t *seg, bool portalclip, FRenderState& state)
return;
}
if (Viewpoint.IsAllowedOoB() && (!r_radarclipper || (Level->flags3 & LEVEL3_NOFOGOFWAR) || clipperr.SafeCheckRange(startAngleR, endAngleR)))
if (!Viewpoint.IsAllowedOoB() || (!r_radarclipper || (Level->flags3 & LEVEL3_NOFOGOFWAR) || clipperr.SafeCheckRange(startAngleR, endAngleR)))
currentsubsector->flags |= SSECMF_DRAWN;
uint8_t ispoly = uint8_t(seg->sidedef->Flags & WALLF_POLYOBJ);

View file

@ -141,6 +141,8 @@ void HWDrawInfo::StartScene(FRenderViewpoint &parentvp, HWViewpointUniforms *uni
VPUniforms.SunDir = FVector3(level.SunDirection.X, level.SunDirection.Z, level.SunDirection.Y);
VPUniforms.SunColor = level.SunColor;
VPUniforms.SunIntensity = level.SunIntensity;
VPUniforms.mThickFogDistance = Level->thickfogdistance;
VPUniforms.mThickFogMultiplier = Level->thickfogmultiplier;
}
mClipper->SetViewpoint(Viewpoint);
vClipper->SetViewpoint(Viewpoint);
@ -1139,17 +1141,6 @@ void HWDrawInfo::DrawCorona(FRenderState& state, AActor* corona, float coronaFad
state.Draw(DT_TriangleStrip, vertexindex, 4);
}
static ETraceStatus CheckForViewpointActor(FTraceResults& res, void* userdata)
{
FRenderViewpoint* data = (FRenderViewpoint*)userdata;
if (res.HitType == TRACE_HitActor && res.Actor && res.Actor == data->ViewActor)
{
return TRACE_Skip;
}
return TRACE_Stop;
}
//==========================================================================
//
// TraceCallbackForDitherTransparency
@ -1189,7 +1180,7 @@ static ETraceStatus TraceCallbackForDitherTransparency(FTraceResults& res, void*
res.Line->sidedef[res.Side]->dithertranscount = 1;
}
}
}
}
break;
case TRACE_HitFloor:
if (res.Sector->subsectorcount > 0 && (*CurMapSections)[res.Sector->subsectors[0]->mapsection] && res.HitVector.dot(res.Sector->floorplane.Normal()) < 0.0)
@ -1298,6 +1289,16 @@ void HWDrawInfo::SetDitherTransFlags(AActor* actor)
}
}
static ETraceStatus CheckForViewpointActor(FTraceResults& res, void* userdata)
{
FRenderViewpoint* data = (FRenderViewpoint*)userdata;
if (res.HitType == TRACE_HitActor && res.Actor && res.Actor == data->ViewActor)
{
return TRACE_Skip;
}
return TRACE_Stop;
}
void HWDrawInfo::DrawCoronas(FRenderState& state)
{

View file

@ -287,8 +287,10 @@ struct HWDrawInfo
void AddSpecialPortalLines(subsector_t * sub, sector_t * sector, linebase_t *line);
public:
void DoSubsector(subsector_t * sub);
void DrawPSprite(HUDSprite* huds, FRenderState& state);
WeaponLighting GetWeaponLighting(sector_t* viewsector, const DVector3& pos, int cm, area_t in_area, const DVector3& playerpos);
int SetupLightsForOtherPlane(subsector_t * sub, FDynLightData &lightdata, const secplane_t *plane);
int CreateOtherPlaneVertices(subsector_t *sub, const secplane_t *plane);
void DrawPSprite(HUDSprite *huds, FRenderState &state);
WeaponLighting GetWeaponLighting(sector_t *viewsector, const DVector3 &pos, int cm, area_t in_area, const DVector3 &playerpos, bool weaponPureLightLevel);
void PreparePlayerSprites2D(sector_t* viewsector, area_t in_area, FRenderState& state);
void PreparePlayerSprites3D(sector_t* viewsector, area_t in_area, FRenderState& state);
@ -413,7 +415,7 @@ public:
void AddOtherFloorPlane(int sector, gl_subsectorrendernode * node, FRenderState& state);
void AddOtherCeilingPlane(int sector, gl_subsectorrendernode * node, FRenderState& state);
void GetDynSpriteLight(AActor *self, sun_trace_cache_t * traceCache, double x, double y, double z, FLightNode *node, int portalgroup, float *out, bool fullbright);
void GetDynSpriteLight(AActor *self, sun_trace_cache_t * traceCache, double x, double y, double z, FSection *sec, int portalgroup, float *out, bool fullbright);
void GetDynSpriteLight(AActor *thing, particle_t *particle, sun_trace_cache_t * traceCache, float *out);
void GetDynSpriteLightList(AActor *self, double x, double y, double z, sun_trace_cache_t * traceCache, FDynLightData &modellightdata, bool isModel);
@ -503,7 +505,7 @@ inline bool isDarkLightMode(ELightMode lightmode)
return lightmode == ELightMode::Doom || lightmode == ELightMode::DoomDark;
}
int CalcLightLevel(ELightMode lightmode, int lightlevel, int rellight, bool weapon, int blendfactor);
int CalcLightLevel(ELightMode lightmode, int lightlevel, int rellight, bool weapon, int blendfactor, bool weaponPureLightLevel = false);
PalEntry CalcLightColor(ELightMode lightmode, int light, PalEntry pe, int blendfactor);
float GetFogDensity(FLevelLocals* Level, ELightMode lightmode, int lightlevel, PalEntry fogcolor, int sectorfogdensity, int blendfactor);
bool CheckFog(FLevelLocals* Level, sector_t* frontsector, sector_t* backsector, ELightMode lightmode);

View file

@ -345,7 +345,7 @@ public:
bool stack;
bool ceiling;
uint8_t renderflags;
uint8_t hacktype;
uint8_t hacktype;
int iboindex;
//int vboheight;
@ -354,7 +354,7 @@ public:
F3DFloor* controlsector;
void CreateSkyboxVertices(FFlatVertex *buffer);
void SetupLights(HWFlatDispatcher *di, FRenderState& state, FLightNode *head, FDynLightData &lightdata, int portalgroup);
void SetupLights(HWFlatDispatcher *di, FRenderState& state, FDynLightData &lightdata, int portalgroup);
void PutFlat(HWFlatDispatcher *di, bool fog = false);
void Process(HWFlatDispatcher *di, FRenderState& state, sector_t * model, int whichplane, bool notexture);
@ -364,8 +364,8 @@ public:
void DrawSubsectors(HWFlatDispatcher *di, FRenderState &state);
void DrawFlat(HWFlatDispatcher *di, FRenderState &state, bool translucent);
void DrawOtherPlanes(HWDrawInfo *di, FRenderState &state);
void DrawFloodPlanes(HWDrawInfo *di, FRenderState &state);
void DrawOtherPlanes(HWDrawInfo *di, FRenderState &state);
void DrawFloodPlanes(HWDrawInfo *di, FRenderState &state);
};
//==========================================================================

View file

@ -159,7 +159,7 @@ void HWFlat::CreateSkyboxVertices(FFlatVertex *vert)
//
//==========================================================================
void HWFlat::SetupLights(HWFlatDispatcher *di, FRenderState& state, FLightNode * node, FDynLightData &lightdata, int portalgroup)
void HWFlat::SetupLights(HWFlatDispatcher *di, FRenderState& state, FDynLightData &lightdata, int portalgroup)
{
if (!di->di)
{
@ -175,29 +175,37 @@ void HWFlat::SetupLights(HWFlatDispatcher *di, FRenderState& state, FLightNode *
dynlightindex = -1;
return; // no lights on additively blended surfaces.
}
while (node)
auto flatLightList = di->Level->lightlists.flat_dlist.CheckKey(section);
if (flatLightList)
{
FDynamicLight * light = node->lightsource;
if (!light->IsActive() || light->DontLightMap())
TMap<FDynamicLight *, std::unique_ptr<FLightNode>>::Iterator it(*flatLightList);
TMap<FDynamicLight *, std::unique_ptr<FLightNode>>::Pair *pair;
while (it.NextPair(pair))
{
node = node->nextLight;
continue;
}
iter_dlightf++;
auto node = pair->Value.get();
if (!node) continue;
FDynamicLight * light = node->lightsource;
// we must do the side check here because gl_GetLight needs the correct plane orientation
// which we don't have for Legacy-style 3D-floors
double planeh = plane.plane.ZatPoint(light->Pos);
if ((planeh<light->Z() && ceiling) || (planeh>light->Z() && !ceiling))
{
node = node->nextLight;
continue;
}
if (!light->IsActive() || light->DontLightMap())
{
continue;
}
iter_dlightf++;
p.Set(plane.plane.Normal(), plane.plane.fD());
draw_dlightf += GetLight(lightdata, portalgroup, p, light, false);
node = node->nextLight;
// we must do the side check here because gl_GetLight needs the correct plane orientation
// which we don't have for Legacy-style 3D-floors
double planeh = plane.plane.ZatPoint(light->Pos);
if ((planeh<light->Z() && ceiling) || (planeh>light->Z() && !ceiling))
{
continue;
}
p.Set(plane.plane.Normal(), plane.plane.fD());
draw_dlightf += GetLight(lightdata, portalgroup, p, light, false);
}
}
dynlightindex = state.UploadLights(lightdata);
@ -213,7 +221,7 @@ void HWFlat::DrawSubsectors(HWFlatDispatcher *di, FRenderState &state)
{
if (di->Level->HasDynamicLights && !di->isFullbrightScene() && !lm_dynlights)
{
SetupLights(di, state, section->lighthead, lightdata, sector->PortalGroup);
SetupLights(di, state, lightdata, sector->PortalGroup);
}
state.SetLightIndex(dynlightindex);
state.DrawIndexed(DT_Triangles, iboindex + section->vertexindex, section->vertexcount);
@ -329,8 +337,9 @@ void HWFlat::DrawFlat(HWFlatDispatcher *di, FRenderState &state, bool translucen
int rel = getExtraLight();
double zshift = (plane.plane.Normal().Z > 0.0 ? 0.1f : -0.1f); // The HWPlaneMirrorPortal::DrawPortalStencil() z-fights with flats
state.SetNormal(plane.plane.Normal().X, plane.plane.Normal().Z, plane.plane.Normal().Y);
double zshift = (plane.plane.Normal().Z > 0.0 ? 0.01f : -0.01f); // The HWPlaneMirrorPortal::DrawPortalStencil() z-fights with flats
state.SetLightProbeIndex(sector->lightProbe.index);
SetColor(state, di->Level, di->lightmode, lightlevel, rel, di->isFullbrightScene(), Colormap, alpha);
@ -384,12 +393,12 @@ void HWFlat::DrawFlat(HWFlatDispatcher *di, FRenderState &state, bool translucen
if (!texture->GetTranslucency()) state.AlphaFunc(Alpha_GEqual, gl_mask_threshold);
else state.AlphaFunc(Alpha_GEqual, 0.f);
state.SetMaterial(texture, UF_Texture, 0, CLAMP_NONE, NO_TRANSLATION, -1);
bool texmatrix = SetPlaneTextureRotation(state, &plane, texture);
if (di->di) // dpjudas, gl_levelmesh could use zshift for reflective flats. - [DVR]
if (di->di)
{
di->di->VPUniforms.mViewMatrix.translate(0.0, zshift, 0.0);
di->di->vpIndex = state.SetViewpoint(di->di->VPUniforms);
// screen->mViewpoints->SetViewpoint(state, &di->di->VPUniforms);
}
DrawSubsectors(di, state);
if (di->di)

View file

@ -76,7 +76,7 @@ CUSTOM_CVAR(Int, gl_distfog, 70, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
//
//==========================================================================
int CalcLightLevel(ELightMode lightmode, int lightlevel, int rellight, bool weapon, int blendfactor)
int CalcLightLevel(ELightMode lightmode, int lightlevel, int rellight, bool weapon, int blendfactor, bool weaponPureLightLevel)
{
int light;
@ -84,7 +84,7 @@ int CalcLightLevel(ELightMode lightmode, int lightlevel, int rellight, bool weap
bool darklightmode = (isDarkLightMode(lightmode)) || (isSoftwareLighting(lightmode) && blendfactor > 0);
if (darklightmode && lightlevel < 192 && !weapon)
if ((darklightmode && lightlevel < 192 && !weapon) || (weapon && weaponPureLightLevel))
{
if (lightlevel > 100)
{

View file

@ -13,9 +13,9 @@ class FSkyBox;
struct HWSkyInfo
{
float x_offset[2];
float x_offset[3];
float y_offset; // doubleskies don't have a y-offset
FGameTexture * texture[2];
FGameTexture * texture[3];
FTextureID skytexno1;
bool mirrored;
bool doublesky;
@ -351,7 +351,6 @@ public:
};
struct HWSkyPortal : public HWPortal
{
HWSkyInfo * origin;

View file

@ -119,23 +119,30 @@ int HWDrawInfo::SetupLightsForOtherPlane(subsector_t * sub, FDynLightData &light
{
Plane p;
FLightNode * node = sub->section->lighthead;
lightdata.Clear();
while (node)
auto flatLightList = Level->lightlists.flat_dlist.CheckKey(sub->section);
if (flatLightList)
{
FDynamicLight * light = node->lightsource;
if (!light->IsActive())
TMap<FDynamicLight *, std::unique_ptr<FLightNode>>::Iterator it(*flatLightList);
TMap<FDynamicLight *, std::unique_ptr<FLightNode>>::Pair *pair;
while (it.NextPair(pair))
{
node = node->nextLight;
continue;
}
iter_dlightf++;
auto node = pair->Value.get();
if (!node) continue;
p.Set(plane->Normal(), plane->fD());
draw_dlightf += GetLight(lightdata, sub->sector->PortalGroup, p, light, true);
node = node->nextLight;
FDynamicLight * light = node->lightsource;
if (!light->IsActive())
{
continue;
}
iter_dlightf++;
p.Set(plane->Normal(), plane->fD());
draw_dlightf += GetLight(lightdata, sub->sector->PortalGroup, p, light, true);
}
}
return state.UploadLights(lightdata);

View file

@ -118,6 +118,9 @@ void HWSkyInfo::init(HWDrawInfo *di, sector_t* sec, int skypos, int sky1, PalEnt
}
else fadecolor = 0;
texture[2] = TexMan.GetGameTexture(di->Level->skymisttexture, true);
x_offset[2] = di->Level->hw_skymistpos;
}
@ -319,7 +322,7 @@ void HWWall::SkyTop(HWWallDispatcher *di, FRenderState& state, seg_t * seg,secto
// float backreflect = bs->GetReflect(sector_t::ceiling);
// if (backreflect > 0 && bs->ceilingplane.fD() == fs->ceilingplane.fD() && !bs->isClosed())
// {
// // Don't add intra-portal line to the portal.
// Don't add intra-portal line to the portal.
// if (!(di->di && di->di->Viewpoint.IsAllowedOoB()))
// {
// return;

View file

@ -74,19 +74,26 @@ void HWSkyPortal::DrawContents(HWDrawInfo *di, FRenderState &state)
vertexBuffer->RenderDome(state, origin->texture[0], origin->x_offset[0], origin->y_offset, origin->mirrored, FSkyVertexBuffer::SKYMODE_MAINLAYER, !!(di->Level->flags & LEVEL_FORCETILEDSKY));
state.SetTextureMode(TM_NORMAL);
}
state.AlphaFunc(Alpha_Greater, 0.f);
if (origin->doublesky && origin->texture[1])
{
vertexBuffer->RenderDome(state, origin->texture[1], origin->x_offset[1], origin->y_offset, false, FSkyVertexBuffer::SKYMODE_SECONDLAYER, !!(di->Level->flags & LEVEL_FORCETILEDSKY));
}
}
if (di->Level->skyfog>0 && !di->isFullbrightScene() && (origin->fadecolor & 0xffffff) != 0)
if (di->Level->skyfog>0 && (origin->fadecolor & 0xffffff) != 0)
{
PalEntry FadeColor = origin->fadecolor;
FadeColor.a = clamp<int>(di->Level->skyfog, 0, 255);
if (di->Level->flags3 & LEVEL3_SKYMIST && origin->texture[2])
{
vertexBuffer->RenderDome(state, origin->texture[2], origin->x_offset[2], 0.f, false, FSkyVertexBuffer::SKYMODE_FOGLAYER, !!(di->Level->flags & LEVEL_FORCETILEDSKY), 0, 0, FadeColor);
}
else if (!di->isFullbrightScene())
{
PalEntry FadeColor = origin->fadecolor;
FadeColor.a = clamp<int>(di->Level->skyfog, 0, 255);
state.EnableTexture(false);
state.SetObjectColor(FadeColor);
state.Draw(DT_Triangles, 0, 12);

View file

@ -131,10 +131,8 @@ float inverseSquareAttenuation(float dist, float radius, float strength, float l
return mix(((b * b) / (dist * dist + 1.0f) * strength), clamp((radius - dist) / radius, 0.0f, 1.0f), linearity);
}
void HWDrawInfo::GetDynSpriteLight(AActor *self, sun_trace_cache_t * traceCache, double x, double y, double z, FLightNode *node, int portalgroup, float *out, bool fullbright)
void HWDrawInfo::GetDynSpriteLight(AActor *self, sun_trace_cache_t * traceCache, double x, double y, double z, FSection *sec, int portalgroup, float *out, bool fullbright)
{
if (fullbright || get_gl_spritelight() > 0)
return;
FDynamicLight *light;
float frac, lr, lg, lb;
@ -142,6 +140,11 @@ void HWDrawInfo::GetDynSpriteLight(AActor *self, sun_trace_cache_t * traceCache,
out[0] = out[1] = out[2] = 0.f;
if (fullbright || get_gl_spritelight() > 0)
return;
#ifdef NEEDS_BIG_BEAUTIFUL_MERGE_PORTING
ActorTraceStaticLight staticLight(self);
if (ActorTraceStaticLight::TraceSunVisibility(x, y, z, traceCache, (self ? staticLight.ActorMoved : traceCache ? traceCache->Pos != DVector3(x, y, z) : false)))
@ -157,22 +160,24 @@ void HWDrawInfo::GetDynSpriteLight(AActor *self, sun_trace_cache_t * traceCache,
}
// Go through both light lists
while (node)
auto flatLightList = Level->lightlists.flat_dlist.CheckKey(sec);
if (flatLightList)
{
light=node->lightsource;
if (light->ShouldLightActor(self))
TMap<FDynamicLight *, std::unique_ptr<FLightNode>>::Iterator it(*flatLightList);
TMap<FDynamicLight *, std::unique_ptr<FLightNode>>::Pair *pair;
while (it.NextPair(pair))
{
float dist;
FVector3 L;
auto node = pair->Value.get();
if (!node) continue;
// This is a performance critical section of code where we cannot afford to let the compiler decide whether to inline the function or not.
// This will do the calculations explicitly rather than calling one of AActor's utility functions.
if (Level->Displacements.size > 0)
light=node->lightsource;
if (light->ShouldLightActor(self))
{
int fromgroup = light->Sector->PortalGroup;
int togroup = portalgroup;
if (fromgroup == togroup || fromgroup == 0 || togroup == 0) goto direct;
float dist;
FVector3 L;
<<<<<<< HEAD
DVector2 offset = Level->Displacements.getOffset(fromgroup, togroup);
L = FVector3(x - (float)(light->X() + offset.X), y - (float)(light->Y() + offset.Y), z - (float)light->Z());
}
@ -221,6 +226,53 @@ void HWDrawInfo::GetDynSpriteLight(AActor *self, sun_trace_cache_t * traceCache,
lg = light->GetGreen() / 255.0f;
lb = light->GetBlue() / 255.0f;
=======
// This is a performance critical section of code where we cannot afford to let the compiler decide whether to inline the function or not.
// This will do the calculations explicitly rather than calling one of AActor's utility functions.
if (Level->Displacements.size > 0)
{
int fromgroup = light->Sector->PortalGroup;
int togroup = portalgroup;
if (fromgroup == togroup || fromgroup == 0 || togroup == 0) goto direct;
DVector2 offset = Level->Displacements.getOffset(fromgroup, togroup);
L = FVector3(x - (float)(light->X() + offset.X), y - (float)(light->Y() + offset.Y), z - (float)light->Z());
}
else
{
direct:
L = FVector3(x - (float)light->X(), y - (float)light->Y(), z - (float)light->Z());
}
dist = (float)L.LengthSquared();
radius = light->GetRadius();
if (dist < radius * radius)
{
dist = sqrtf(dist); // only calculate the square root if we really need it.
frac = 1.0f - (dist / radius);
if (light->IsSpot())
{
L *= -1.0f / dist;
DAngle negPitch = -*light->pPitch;
DAngle Angle = light->target->Angles.Yaw;
double xyLen = negPitch.Cos();
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->pSpotOuterAngle->Cos(), light->pSpotInnerAngle->Cos(), cosDir);
}
if (frac > 0 && (!light->shadowmapped || (light->GetRadius() > 0 && screen->mShadowMap.ShadowTest(light->Pos, { x, y, z }))))
{
lr = light->GetRed() / 255.0f;
lg = light->GetGreen() / 255.0f;
lb = light->GetBlue() / 255.0f;
>>>>>>> gzdoom/master
if (light->target && (light->target->renderflags2 & RF2_LIGHTMULTALPHA))
{
float alpha = (float)light->target->Alpha;
@ -250,19 +302,19 @@ void HWDrawInfo::GetDynSpriteLight(AActor *self, sun_trace_cache_t * traceCache,
}
}
}
node = node->nextLight;
}
#endif
}
void HWDrawInfo::GetDynSpriteLight(AActor *thing, particle_t *particle, sun_trace_cache_t * traceCache, float *out)
{
if (thing)
{
GetDynSpriteLight(thing, &thing->StaticLightsTraceCache, thing->X(), thing->Y(), thing->Center(), thing->section->lighthead, thing->Sector->PortalGroup, out, (thing->flags5 & MF5_BRIGHT));
GetDynSpriteLight(thing, &thing->StaticLightsTraceCache, thing->X(), thing->Y(), thing->Center(), thing->section, thing->Sector->PortalGroup, out, (thing->flags5 & MF5_BRIGHT));
}
else if (particle)
{
GetDynSpriteLight(nullptr, traceCache, particle->Pos.X, particle->Pos.Y, particle->Pos.Z, particle->subsector->section->lighthead, particle->subsector->sector->PortalGroup, out, (particle->flags & SPF_FULLBRIGHT));
GetDynSpriteLight(nullptr, traceCache, particle->Pos.X, particle->Pos.Y, particle->Pos.Z, particle->subsector->section, particle->subsector->sector->PortalGroup, out, (particle->flags & SPF_FULLBRIGHT));
}
}
@ -271,6 +323,8 @@ void HWDrawInfo::GetDynSpriteLightList(AActor *self, double x, double y, double
{
modellightdata.Clear();
#ifdef NEEDS_BIG_BEAUTIFUL_MERGE_PORTING
if (self && (self->flags5 & MF5_BRIGHT))
return;
@ -304,6 +358,7 @@ void HWDrawInfo::GetDynSpriteLightList(AActor *self, double x, double y, double
FLightNode * node = section->lighthead;
while (node) // check all lights touching a subsector
{
<<<<<<< HEAD
FDynamicLight *light = node->lightsource;
if (light->ShouldLightActor(self))
{
@ -327,6 +382,36 @@ void HWDrawInfo::GetDynSpriteLightList(AActor *self, double x, double y, double
if (gl_spritelight > 0 || staticLight.TraceLightVisbility(node, L, dist, light->updated))
{
AddLightToList(modellightdata, group, light, true, gl_spritelight > 0);
=======
auto section = subsector->section;
if (section->validcount == dl_validcount) return; // already done from a previous subsector.
auto flatLightList = self->Level->lightlists.flat_dlist.CheckKey(subsector->section);
if (flatLightList)
{
TMap<FDynamicLight *, std::unique_ptr<FLightNode>>::Iterator it(*flatLightList);
TMap<FDynamicLight *, std::unique_ptr<FLightNode>>::Pair *pair;
while (it.NextPair(pair))
{ // check all lights touching a subsector
auto node = pair->Value.get();
if (!node) continue;
FDynamicLight *light = node->lightsource;
if (light->ShouldLightActor(self))
{
int group = subsector->sector->PortalGroup;
DVector3 pos = light->PosRelative(group);
float radius = (float)(light->GetRadius() + actorradius);
double dx = pos.X - x;
double dy = pos.Y - y;
double dz = pos.Z - z;
double distSquared = dx * dx + dy * dy + dz * dz;
if (distSquared < radius * radius) // Light and actor touches
{
if (std::find(addedLights.begin(), addedLights.end(), light) == addedLights.end()) // Check if we already added this light from a different subsector
{
AddLightToList(modellightdata, group, light, true);
addedLights.Push(light);
}
>>>>>>> gzdoom/master
}
addedLights.Insert(index, light);
@ -336,6 +421,7 @@ void HWDrawInfo::GetDynSpriteLightList(AActor *self, double x, double y, double
node = node->nextLight;
}
});
#endif
}
void HWDrawInfo::GetDynSpriteLightList(AActor *thing, particle_t *particle, sun_trace_cache_t * traceCache, FDynLightData &modellightdata, bool isModel)

View file

@ -509,11 +509,14 @@ bool HWSprite::CalculateVertices(HWDrawInfo* di, FVector3* v, DVector3* vp)
return true;
}
// [DVR] +ANGLEDROLL
const bool AngledRoll = (actor != nullptr && actor->renderflags2 & RF2_ANGLEDROLL);
// [BB] Billboard stuff
const bool drawWithXYBillboard = ((particle && gl_billboard_particles && !(particle->flags & SPF_NO_XY_BILLBOARD)) || (!(actor && actor->renderflags & RF_FORCEYBILLBOARD)
//&& di->mViewActor != nullptr
&& (gl_billboard_mode == 1 || (actor && actor->renderflags & RF_FORCEXYBILLBOARD))));
&& (gl_billboard_mode == 1 || (actor && actor->renderflags & RF_FORCEXYBILLBOARD)))) && !AngledRoll;
const bool drawBillboardFacingCamera = hw_force_cambbpref ? gl_billboard_faces_camera :
gl_billboard_faces_camera
@ -620,13 +623,31 @@ bool HWSprite::CalculateVertices(HWDrawInfo* di, FVector3* v, DVector3* vp)
// Compute center of sprite
float angleRad = (FAngle::fromDeg(270.) - HWAngles.Yaw).Radians();
float rollDegrees = Angles.Roll.Degrees();
float pitchDegrees = 0.0;
if (AngledRoll)
{
rollDegrees = fmodf(rollDegrees, 360.0f);
DAngle ang = di->Viewpoint.Angles.Yaw + actor->Angles.Yaw + actor->AngledRollOffset - DAngle::fromDeg(90.0);
angleRad = ang.Radians();
FVector3 relPos = center - FVector3(di->Viewpoint.Pos);
if (useOffsets) relPos += FVector3(xx, yy, zz);
Matrix3x4 rolltilt;
rolltilt.MakeIdentity();
ang = actor->Angles.Yaw + actor->AngledRollOffset;
rolltilt.Rotate(ang.Cos(), ang.Sin(), 0.0, -rollDegrees);
pitchDegrees = 270.0 - DVector3(rolltilt * relPos).Angle().Degrees();
}
mat.Translate(center.X, center.Z, center.Y);
mat.Scale(1.0, 1.0/pixelstretch, 1.0); // unstretch sprite by level aspect ratio
if (useOffsets) mat.Translate(xx, zz, yy);
mat.Scale(1.0, 1.0/pixelstretch, 1.0); // unstretch sprite by level aspect ratio
if (AngledRoll) mat.Rotate(0.0, 1.0, 0.0, -HWAngles.Yaw.Degrees()); // Cancel regular Y-billboarding
mat.Rotate(cos(angleRad), 0, sin(angleRad), rollDegrees);
if (useOffsets) mat.Translate(-xx, -zz, -yy);
if (AngledRoll) mat.Rotate(0.0, 1.0, 0.0, pitchDegrees); // New Y-billboarding about rolled z-axis
mat.Scale(1.0, pixelstretch, 1.0); // stretch sprite by level aspect ratio
if (useOffsets) mat.Translate(-xx, -zz, -yy);
mat.Translate(-center.X, -center.Z, -center.Y);
}
@ -898,7 +919,8 @@ void HWSprite::Process(HWDrawInfo *di, FRenderState& state, AActor* thing, secto
const auto &vp = di->Viewpoint;
AActor *camera = vp.camera;
if (thing->renderflags & RF_INVISIBLE || !thing->RenderStyle.IsVisible(thing->Alpha))
const double alpha = thing->InterpolatedAlpha(vp.TicFrac);
if (thing->renderflags & RF_INVISIBLE || !thing->RenderStyle.IsVisible(alpha))
{
if (!(thing->flags & MF_STEALTH) || !di->isStealthVision() || thing == camera)
return;
@ -911,7 +933,7 @@ void HWSprite::Process(HWDrawInfo *di, FRenderState& state, AActor* thing, secto
return;
int spritenum = thing->sprite;
DVector2 sprscale(thing->Scale.X, thing->Scale.Y);
DVector2 sprscale = thing->InterpolatedScale(vp.TicFrac);
if (thing->player != nullptr)
{
P_CheckPlayerSprite(thing, spritenum, sprscale);
@ -1039,8 +1061,22 @@ void HWSprite::Process(HWDrawInfo *di, FRenderState& state, AActor* thing, secto
if (!modelframe)
{
bool mirror = false;
bool backfaced = false;
DAngle ang = (thingpos - vp.Pos).Angle();
if (di->Viewpoint.IsOrtho()) ang = vp.Angles.Yaw;
else if (actor && thing->renderflags2 & RF2_ANGLEDROLL)
{
Matrix3x4 rolltilt;
rolltilt.MakeIdentity();
DAngle tempang = thing->Angles.Yaw + thing->AngledRollOffset;
rolltilt.Rotate(tempang.Cos(), tempang.Sin(), 0.0, -thing->Angles.Roll.Degrees());
tempang = DVector3(rolltilt * FVector3(thingpos - vp.Pos)).Angle();
backfaced = fabs((ang - tempang).Degrees()) > 90.0;
if (backfaced) // (ang - tempang).Cos() < 0.0)
{
ang = DAngle::fromDeg(180.0) - ang;
}
}
FTextureID patch;
// [ZZ] add direct picnum override
if (isPicnumOverride)
@ -1233,6 +1269,15 @@ void HWSprite::Process(HWDrawInfo *di, FRenderState& state, AActor* thing, secto
depth = (float)((x - vp.Pos.X) * vp.TanCos + (y - vp.Pos.Y) * vp.TanSin);
if(thing->renderflags2 & RF2_ISOMETRICSPRITES) depth = depth * vp.PitchCos - vp.PitchSin * z2; // Helps with stacking actors with small xy offsets
if(actor && (thing->renderflags2 & RF2_ANGLEDROLL) && !(thing->renderflags & RF_ROLLCENTER))
{
double rollsin = thing->Angles.Roll.Sin();
DAngle tempang2 = thing->Angles.Yaw + thing->AngledRollOffset + DAngle::fromDeg(rollsin < 0.0
? 90.0 : -90.0);
double r2 = 0.5 * fabs((z2 - z1) * rollsin);
depth = (float)((x + r2 * tempang2.Cos() - vp.Pos.X) * vp.TanCos
+ (y + r2 * tempang2.Sin() - vp.Pos.Y) * vp.TanSin);
}
if (isSpriteShadow) depth += 1.f/65536.f; // always sort shadows behind the sprite.
if (gl_spriteclip == -1 && (thing->renderflags & RF_SPRITETYPEMASK) == RF_FACESPRITE) // perform anamorphosis
@ -1282,7 +1327,7 @@ void HWSprite::Process(HWDrawInfo *di, FRenderState& state, AActor* thing, secto
z1 = z1 * spbias + vpz * vpbias;
x2 = x2 * spbias + vpx * vpbias;
y2 = y2 * spbias + vpy * vpbias;
z2 = z2 * spbias + vpz * vpbias;
z2 = z2 * spbias + vpz * vpbias;
}
// light calculation
@ -1348,7 +1393,7 @@ void HWSprite::Process(HWDrawInfo *di, FRenderState& state, AActor* thing, secto
translation = thing->Translation;
OverrideShader = -1;
trans = thing->Alpha;
trans = alpha;
hw_styleflags = STYLEHW_Normal;
if (RenderStyle.BlendOp >= STYLEOP_Fuzz && RenderStyle.BlendOp <= STYLEOP_FuzzOrRevSub)

View file

@ -427,76 +427,138 @@ void HWWall::SetupLights(HWDrawInfo*di, FRenderState& state, FDynLightData &ligh
auto normal = glseg.Normal();
p.Set(normal, -normal.X * glseg.x1 - normal.Z * glseg.y1);
FLightNode *node;
if (seg->sidedef == NULL)
{
node = NULL;
}
else if (!(seg->sidedef->Flags & WALLF_POLYOBJ))
{
node = seg->sidedef->lighthead;
}
else if (sub)
if ((seg->sidedef->Flags & WALLF_POLYOBJ) && sub)
{
// Polobject segs cannot be checked per sidedef so use the subsector instead.
node = sub->section->lighthead;
}
else node = NULL;
auto flatLightList = di->Level->lightlists.flat_dlist.CheckKey(sub->section);
// Iterate through all dynamic lights which touch this wall and render them
while (node)
{
if (node->lightsource->IsActive() && !node->lightsource->DontLightMap())
if (flatLightList)
{
iter_dlight++;
DVector3 posrel = node->lightsource->PosRelative(seg->frontsector->PortalGroup);
float x = posrel.X;
float y = posrel.Y;
float z = posrel.Z;
float dist = fabsf(p.DistToPoint(x, z, y));
float radius = node->lightsource->GetRadius();
float scale = 1.0f / ((2.f * radius) - dist);
FVector3 fn, pos;
if (radius > 0.f && dist < radius)
TMap<FDynamicLight *, std::unique_ptr<FLightNode>>::Iterator it(*flatLightList);
TMap<FDynamicLight *, std::unique_ptr<FLightNode>>::Pair *pair;
while (it.NextPair(pair))
{
FVector3 nearPt, up, right;
auto node = pair->Value.get();
if (!node) continue;
pos = { x, z, y };
fn = p.Normal();
fn.GetRightUp(right, up);
FVector3 tmpVec = fn * dist;
nearPt = pos + tmpVec;
FVector3 t1;
int outcnt[4]={0,0,0,0};
texcoord tcs[4];
// do a quick check whether the light touches this polygon
for(int i=0;i<4;i++)
if (node->lightsource->IsActive() && !node->lightsource->DontLightMap())
{
t1 = FVector3(&vtx[i*3]);
FVector3 nearToVert = t1 - nearPt;
tcs[i].u = ((nearToVert | right) * scale) + 0.5f;
tcs[i].v = ((nearToVert | up) * scale) + 0.5f;
iter_dlight++;
if (tcs[i].u<0) outcnt[0]++;
if (tcs[i].u>1) outcnt[1]++;
if (tcs[i].v<0) outcnt[2]++;
if (tcs[i].v>1) outcnt[3]++;
DVector3 posrel = node->lightsource->PosRelative(seg->frontsector->PortalGroup);
float x = posrel.X;
float y = posrel.Y;
float z = posrel.Z;
float dist = fabsf(p.DistToPoint(x, z, y));
float radius = node->lightsource->GetRadius();
float scale = 1.0f / ((2.f * radius) - dist);
FVector3 fn, pos;
}
if (outcnt[0]!=4 && outcnt[1]!=4 && outcnt[2]!=4 && outcnt[3]!=4)
{
draw_dlight += GetLight(lightdata, seg->frontsector->PortalGroup, p, node->lightsource, true);
if (radius > 0.f && dist < radius)
{
FVector3 nearPt, up, right;
pos = { x, z, y };
fn = p.Normal();
fn.GetRightUp(right, up);
FVector3 tmpVec = fn * dist;
nearPt = pos + tmpVec;
FVector3 t1;
int outcnt[4]={0,0,0,0};
texcoord tcs[4];
// do a quick check whether the light touches this polygon
for(int i=0;i<4;i++)
{
t1 = FVector3(&vtx[i*3]);
FVector3 nearToVert = t1 - nearPt;
tcs[i].u = ((nearToVert | right) * scale) + 0.5f;
tcs[i].v = ((nearToVert | up) * scale) + 0.5f;
if (tcs[i].u<0) outcnt[0]++;
if (tcs[i].u>1) outcnt[1]++;
if (tcs[i].v<0) outcnt[2]++;
if (tcs[i].v>1) outcnt[3]++;
}
if (outcnt[0]!=4 && outcnt[1]!=4 && outcnt[2]!=4 && outcnt[3]!=4)
{
draw_dlight += GetLight(lightdata, seg->frontsector->PortalGroup, p, node->lightsource, true);
}
}
}
}
}
node = node->nextLight;
}
else
{
auto wallLightList = di->Level->lightlists.wall_dlist.CheckKey(seg->sidedef);
if (wallLightList)
{
TMap<FDynamicLight *, std::unique_ptr<FLightNode>>::Iterator it(*wallLightList);
TMap<FDynamicLight *, std::unique_ptr<FLightNode>>::Pair *pair;
while (it.NextPair(pair))
{
auto node = pair->Value.get();
if (!node) continue;
if (node->lightsource->IsActive() && !node->lightsource->DontLightMap())
{
iter_dlight++;
DVector3 posrel = node->lightsource->PosRelative(seg->frontsector->PortalGroup);
float x = posrel.X;
float y = posrel.Y;
float z = posrel.Z;
float dist = fabsf(p.DistToPoint(x, z, y));
float radius = node->lightsource->GetRadius();
float scale = 1.0f / ((2.f * radius) - dist);
FVector3 fn, pos;
if (radius > 0.f && dist < radius)
{
FVector3 nearPt, up, right;
pos = { x, z, y };
fn = p.Normal();
fn.GetRightUp(right, up);
FVector3 tmpVec = fn * dist;
nearPt = pos + tmpVec;
FVector3 t1;
int outcnt[4]={0,0,0,0};
texcoord tcs[4];
// do a quick check whether the light touches this polygon
for(int i=0;i<4;i++)
{
t1 = FVector3(&vtx[i*3]);
FVector3 nearToVert = t1 - nearPt;
tcs[i].u = ((nearToVert | right) * scale) + 0.5f;
tcs[i].v = ((nearToVert | up) * scale) + 0.5f;
if (tcs[i].u<0) outcnt[0]++;
if (tcs[i].u>1) outcnt[1]++;
if (tcs[i].v<0) outcnt[2]++;
if (tcs[i].v>1) outcnt[3]++;
}
if (outcnt[0]!=4 && outcnt[1]!=4 && outcnt[2]!=4 && outcnt[3]!=4)
{
draw_dlight += GetLight(lightdata, seg->frontsector->PortalGroup, p, node->lightsource, true);
}
}
}
}
}
}
dynlightindex = state.UploadLights(lightdata);
}

View file

@ -54,6 +54,8 @@ EXTERN_CVAR(Bool, r_drawplayersprites)
EXTERN_CVAR(Bool, r_deathcamera)
CVARD(Bool, gl_weapon_purelightlevel, false, CVAR_GLOBALCONFIG | CVAR_ARCHIVE, "Makes the lighting on weapon sprites (or models) purely match the sector's light level you're standing in");
//==========================================================================
//
// R_DrawPSprite
@ -94,6 +96,7 @@ void HWDrawInfo::DrawPSprite(HUDSprite *huds, FRenderState &state)
FHWModelRenderer renderer(this, state, huds->lightindex);
RenderHUDModel(&renderer, huds->weapon, huds->translation, huds->rotation + FVector3(huds->mx / 4., (huds->my - WEAPONTOP) / -4., 0), huds->pivot, huds->mframe, Viewpoint.TicFrac);
state.SetFlatVertexBuffer();
state.SetShadeVertex(false);
}
@ -326,7 +329,7 @@ static FVector2 BobWeapon3D(WeaponPosition3D &weap, DPSprite *psp, FVector3 &tra
//
//==========================================================================
WeaponLighting HWDrawInfo::GetWeaponLighting(sector_t *viewsector, const DVector3 &pos, int cm, area_t in_area, const DVector3 &playerpos)
WeaponLighting HWDrawInfo::GetWeaponLighting(sector_t *viewsector, const DVector3 &pos, int cm, area_t in_area, const DVector3 &playerpos, bool weaponPureLightLevel = false)
{
WeaponLighting l;
@ -374,7 +377,7 @@ WeaponLighting HWDrawInfo::GetWeaponLighting(sector_t *viewsector, const DVector
if (Level->flags3 & LEVEL3_NOCOLOREDSPRITELIGHTING) l.cm.ClearColor();
}
l.lightlevel = CalcLightLevel(lightmode, l.lightlevel, getExtraLight(), true, 0);
l.lightlevel = CalcLightLevel(lightmode, l.lightlevel, getExtraLight(), true, 0, weaponPureLightLevel);
if (isSoftwareLighting(lightmode) || l.lightlevel < 92)
{
@ -706,7 +709,7 @@ void HWDrawInfo::PreparePlayerSprites2D(sector_t * viewsector, area_t in_area, F
AActor *camera = vp.camera;
WeaponPosition2D weap = GetWeaponPosition2D(camera->player, vp.TicFrac);
WeaponLighting light = GetWeaponLighting(viewsector, vp.Pos, isFullbrightScene(), in_area, camera->Pos());
WeaponLighting light = GetWeaponLighting(viewsector, vp.Pos, isFullbrightScene(), in_area, camera->Pos(), gl_weapon_purelightlevel);
VMFunction * ModifyBobLayer = nullptr;
DVector2 bobxy = DVector2(weap.bobx , weap.boby);
@ -796,7 +799,7 @@ void HWDrawInfo::PreparePlayerSprites3D(sector_t * viewsector, area_t in_area, F
AActor *camera = vp.camera;
WeaponPosition3D weap = GetWeaponPosition3D(camera->player, vp.TicFrac);
WeaponLighting light = GetWeaponLighting(viewsector, vp.Pos, isFullbrightScene(), in_area, camera->Pos());
WeaponLighting light = GetWeaponLighting(viewsector, vp.Pos, isFullbrightScene(), in_area, camera->Pos(), gl_weapon_purelightlevel);
VMFunction * ModifyBobLayer3D = nullptr;
VMFunction * ModifyBobPivotLayer3D = nullptr;

View file

@ -79,6 +79,10 @@ void InitSkyMap(FLevelLocals *Level)
{
Level->skytexture1 = TexMan.GetFrontSkyLayer(Level->skytexture1);
}
if (Level->skymisttexture.isNull())
{
Level->skymisttexture = TexMan.CheckForTexture("skymist1", ETextureType::Any);
}
skytex1 = TexMan.GetGameTexture(Level->skytexture1, false);
skytex2 = TexMan.GetGameTexture(Level->skytexture2, false);
@ -143,6 +147,7 @@ void R_UpdateSky (uint64_t mstime)
// The hardware renderer uses a different value range and clamps it to a single rotation
Level->hw_sky1pos = (float)(fmod((double(mstime) * Level->skyspeed1), 1024.) * (90. / 256.));
Level->hw_sky2pos = (float)(fmod((double(mstime) * Level->skyspeed2), 1024.) * (90. / 256.));
Level->hw_skymistpos = (float)(fmod((double(mstime) * Level->skymistspeed), 1024.) * (90. / 256.));
}
}

View file

@ -922,6 +922,8 @@ static void R_DoActorTickerAngleChanges(player_t* const player, DRotator& angles
EXTERN_CVAR(Float, chase_dist)
EXTERN_CVAR(Float, chase_height)
int WorldPaused();
void R_SetupFrame(FRenderViewpoint& viewPoint, const FViewWindow& viewWindow, AActor* const actor, int side)
{
viewPoint.TicFrac = I_GetTimeFrac();
@ -958,8 +960,17 @@ void R_SetupFrame(FRenderViewpoint& viewPoint, const FViewWindow& viewWindow, AA
iView->AngleOffsets.Zero();
if (iView->prevTic != -1 && curTic > iView->prevTic)
{
iView->prevTic = curTic;
iView->Old = iView->New;
// If it's been more than a tic since it was rendered, don't interpolate
// from whatever last position it had (it's probably no longer valid).
if (curTic - iView->prevTic > 1)
{
iView->prevTic = -1;
}
else
{
iView->prevTic = curTic;
iView->Old = iView->New;
}
}
const auto& mainView = r_viewpoint;
@ -1034,7 +1045,7 @@ void R_SetupFrame(FRenderViewpoint& viewPoint, const FViewWindow& viewWindow, AA
viewPoint.sector = viewPoint.ViewLevel->PointInRenderSubsector(camPos)->sector;
}
if (!paused)
if (!WorldPaused())
{
FQuakeJiggers jiggers;
if (DEarthquake::StaticGetQuakeIntensities(viewPoint.TicFrac, viewPoint.camera, jiggers) > 0)

View file

@ -209,11 +209,57 @@ namespace swrenderer
FLightNode* RenderWallPart::GetLightList()
{
while (light_list)
{
// Clear out the wall part light list
FLightNode *next = nullptr;
if (light_list->nextLight) next = light_list->nextLight;
delete light_list;
if (next) light_list = next;
}
CameraLight* cameraLight = CameraLight::Instance();
if ((cameraLight->FixedLightLevel() >= 0) || cameraLight->FixedColormap())
return nullptr; // [SP] Don't draw dynlights if invul/lightamp active
else if (curline && curline->sidedef)
return curline->sidedef->lighthead;
{
auto Level = curline->Subsector->sector->Level;
auto wallLightList = Level->lightlists.wall_dlist.CheckKey(curline->sidedef);
if (wallLightList)
{
TMap<FDynamicLight *, std::unique_ptr<FLightNode>>::Iterator it(*wallLightList);
TMap<FDynamicLight *, std::unique_ptr<FLightNode>>::Pair *pair;
while (it.NextPair(pair))
{
auto node = pair->Value.get();
if (!node) continue;
if (node->lightsource->IsActive())
{
bool found = false;
FLightNode *light_node = light_list;
while (light_node)
{
if (light_node->lightsource == node->lightsource)
{
found = true;
break;
}
light_node = light_node->nextLight;
}
if (!found)
{
FLightNode *newlight = new FLightNode;
newlight->nextLight = light_list;
newlight->lightsource = node->lightsource;
light_list = newlight;
}
}
}
}
return light_list;
}
else
return nullptr;
}

View file

@ -66,7 +66,7 @@ namespace swrenderer
fillshort(top, viewwidth, 0x7fff);
}
void VisiblePlane::AddLights(RenderThread *thread, FLightNode *node)
void VisiblePlane::AddLights(RenderThread *thread, FSection *sec)
{
if (!r_dynlights)
return;
@ -75,30 +75,39 @@ namespace swrenderer
if (cameraLight->FixedColormap() != NULL || cameraLight->FixedLightLevel() >= 0)
return; // [SP] no dynlights if invul or lightamp
while (node)
auto Level = sec->sector->Level;
auto flatLightList = Level->lightlists.flat_dlist.CheckKey(sec);
if (flatLightList)
{
if (node->lightsource->IsActive() && (height.PointOnSide(node->lightsource->Pos) > 0))
TMap<FDynamicLight *, std::unique_ptr<FLightNode>>::Iterator it(*flatLightList);
TMap<FDynamicLight *, std::unique_ptr<FLightNode>>::Pair *pair;
while (it.NextPair(pair))
{
bool found = false;
VisiblePlaneLight *light_node = lights;
while (light_node)
auto node = pair->Value.get();
if (!node) continue;
if (node->lightsource->IsActive() && (height.PointOnSide(node->lightsource->Pos) > 0))
{
if (light_node->lightsource == node->lightsource)
bool found = false;
VisiblePlaneLight *light_node = lights;
while (light_node)
{
found = true;
break;
if (light_node->lightsource == node->lightsource)
{
found = true;
break;
}
light_node = light_node->next;
}
if (!found)
{
VisiblePlaneLight *newlight = thread->FrameMemory->NewObject<VisiblePlaneLight>();
newlight->next = lights;
newlight->lightsource = node->lightsource;
lights = newlight;
}
light_node = light_node->next;
}
if (!found)
{
VisiblePlaneLight *newlight = thread->FrameMemory->NewObject<VisiblePlaneLight>();
newlight->next = lights;
newlight->lightsource = node->lightsource;
lights = newlight;
}
}
node = node->nextLight;
}
}

View file

@ -46,7 +46,7 @@ namespace swrenderer
{
VisiblePlane(RenderThread *thread);
void AddLights(RenderThread *thread, FLightNode *node);
void AddLights(RenderThread *thread, FSection *sec);
void Render(RenderThread *thread, fixed_t alpha, bool additive, bool masked);
VisiblePlane *next = nullptr; // Next visplane in hash chain -- killough

View file

@ -561,7 +561,7 @@ namespace swrenderer
Fake3DOpaque::Normal,
0);
ceilingplane->AddLights(Thread, sub->section->lighthead);
ceilingplane->AddLights(Thread, sub->section);
}
int adjusted_floorlightlevel = floorlightlevel;
@ -601,7 +601,7 @@ namespace swrenderer
Fake3DOpaque::Normal,
0);
floorplane->AddLights(Thread, sub->section->lighthead);
floorplane->AddLights(Thread, sub->section);
}
Add3DFloorPlanes(sub, frontsector, basecolormap, foggy, adjusted_ceilinglightlevel, adjusted_floorlightlevel);
@ -738,7 +738,7 @@ namespace swrenderer
Fake3DOpaque::FakeFloor,
fakeAlpha);
floorplane3d->AddLights(Thread, sub->section->lighthead);
floorplane3d->AddLights(Thread, sub->section);
FakeDrawLoop(sub, &tempsec, floorplane3d, nullptr, Fake3DOpaque::FakeFloor);
}
@ -806,7 +806,7 @@ namespace swrenderer
Fake3DOpaque::FakeCeiling,
fakeAlpha);
ceilingplane3d->AddLights(Thread, sub->section->lighthead);
ceilingplane3d->AddLights(Thread, sub->section);
FakeDrawLoop(sub, &tempsec, nullptr, ceilingplane3d, Fake3DOpaque::FakeCeiling);
}

View file

@ -208,42 +208,50 @@ namespace swrenderer
float lit_red = 0;
float lit_green = 0;
float lit_blue = 0;
auto node = vis->section->lighthead;
while (node != nullptr)
auto Level = vis->sector->Level;
auto flatLightList = Level->lightlists.flat_dlist.CheckKey(vis->section);
if (flatLightList)
{
FDynamicLight *light = node->lightsource;
if (light->ShouldLightActor(thing))
TMap<FDynamicLight *, std::unique_ptr<FLightNode>>::Iterator it(*flatLightList);
TMap<FDynamicLight *, std::unique_ptr<FLightNode>>::Pair *pair;
while (it.NextPair(pair))
{
float lx = (float)(light->X() - thing->X());
float ly = (float)(light->Y() - thing->Y());
float lz = (float)(light->Z() - thing->Center());
float LdotL = lx * lx + ly * ly + lz * lz;
float radius = node->lightsource->GetRadius();
if (radius * radius >= LdotL)
auto node = pair->Value.get();
if (!node) continue;
FDynamicLight *light = node->lightsource;
if (light->ShouldLightActor(thing))
{
float distance = sqrt(LdotL);
float attenuation = 1.0f - distance / radius;
if (attenuation > 0.0f)
{
float red = light->GetRed() * (1.0f / 255.0f);
float green = light->GetGreen() * (1.0f / 255.0f);
float blue = light->GetBlue() * (1.0f / 255.0f);
/*if (light->IsSubtractive())
{
float bright = FVector3(lr, lg, lb).Length();
FVector3 lightColor(lr, lg, lb);
red = (bright - lr) * -1;
green = (bright - lg) * -1;
blue = (bright - lb) * -1;
}*/
lit_red += red * attenuation;
lit_green += green * attenuation;
lit_blue += blue * attenuation;
float lx = (float)(light->X() - thing->X());
float ly = (float)(light->Y() - thing->Y());
float lz = (float)(light->Z() - thing->Center());
float LdotL = lx * lx + ly * ly + lz * lz;
float radius = node->lightsource->GetRadius();
if (radius * radius >= LdotL)
{
float distance = sqrt(LdotL);
float attenuation = 1.0f - distance / radius;
if (attenuation > 0.0f)
{
float red = light->GetRed() * (1.0f / 255.0f);
float green = light->GetGreen() * (1.0f / 255.0f);
float blue = light->GetBlue() * (1.0f / 255.0f);
/*if (light->IsSubtractive())
{
float bright = FVector3(lr, lg, lb).Length();
FVector3 lightColor(lr, lg, lb);
red = (bright - lr) * -1;
green = (bright - lg) * -1;
blue = (bright - lb) * -1;
}*/
lit_red += red * attenuation;
lit_green += green * attenuation;
lit_blue += blue * attenuation;
}
}
}
}
node = node->nextLight;
}
lit_red = clamp(lit_red * 255.0f, 0.0f, 255.0f);
lit_green = clamp(lit_green * 255.0f, 0.0f, 255.0f);