Disable skyhack for level mesh and fix frustum test against skies

This commit is contained in:
Magnus Norddahl 2025-05-31 23:57:38 +02:00
commit 8d10617762
5 changed files with 118 additions and 23 deletions

View file

@ -10,6 +10,7 @@
#include "hw_renderstate.h"
#include "hw_vertexbuilder.h"
#include "hw_dynlightdata.h"
#include "hwrenderer/scene/hw_fakeflat.h"
#include "hwrenderer/scene/hw_lighting.h"
#include "hwrenderer/scene/hw_drawstructs.h"
#include "hwrenderer/scene/hw_drawinfo.h"
@ -329,23 +330,33 @@ void DoomLevelMesh::AddSectorsToDrawLists(const TArray<int>& sectors, LevelMeshD
}
}
void DoomLevelMesh::AddSidesToDrawLists(const TArray<int>& sides, LevelMeshDrawLists& lists, HWDrawInfo* di)
void DoomLevelMesh::AddSidesToDrawLists(const TArray<int>& sides, LevelMeshDrawLists& lists, HWDrawInfo* di, FRenderState& state)
{
for (int sideIndex : sides)
{
for (const DrawRangeInfo& di : Sides[sideIndex].DrawRanges)
if (!Sides[sideIndex].NeedsImmediateRendering)
{
lists.Add(di.DrawType, di.PipelineID, { di.IndexStart, di.IndexStart + di.IndexCount });
}
for (const DrawRangeInfo& di : Sides[sideIndex].DrawRanges)
{
lists.Add(di.DrawType, di.PipelineID, { di.IndexStart, di.IndexStart + di.IndexCount });
}
for (const HWMissing& missing : Sides[sideIndex].MissingUpper)
{
di->AddUpperMissingTexture(missing.side, missing.sub, missing.plane);
}
for (const HWMissing& missing : Sides[sideIndex].MissingUpper)
{
di->AddUpperMissingTexture(missing.side, missing.sub, missing.plane);
}
for (const HWMissing& missing : Sides[sideIndex].MissingLower)
for (const HWMissing& missing : Sides[sideIndex].MissingLower)
{
di->AddLowerMissingTexture(missing.side, missing.sub, missing.plane);
}
}
else
{
di->AddLowerMissingTexture(missing.side, missing.sub, missing.plane);
// To do: is it good enough to just grab the first seg here?
side_t* side = &di->Level->sides[sideIndex];
seg_t* seg = side->segs[0];
di->ProcessSeg(seg, state);
}
}
}
@ -673,6 +684,8 @@ void DoomLevelMesh::FreeSide(FLevelLocals& doomMap, unsigned int sideIndex)
Sides[sideIndex].MissingUpper.Clear();
Sides[sideIndex].MissingLower.Clear();
Sides[sideIndex].Decals.Clear();
Sides[sideIndex].NeedsImmediateRendering = false;
}
void DoomLevelMesh::FreeFlat(FLevelLocals& doomMap, unsigned int sectorIndex)
@ -1088,6 +1101,29 @@ void DoomLevelMesh::CreateSide(FLevelLocals& doomMap, unsigned int sideIndex)
state.SetDepthFunc(DF_LEqual);
// DrawDecals(state, Decals[0]);
// These things aren't working properly with the level mesh.
bool incompatible = false;
for (const HWWall& wall : result.opaque)
if ((wall.flags & HWWall::HWF_SKYHACK) != 0)
incompatible = true;
for (const HWWall& wall : result.masked)
if ((wall.flags & HWWall::HWF_SKYHACK) != 0)
incompatible = true;
for (const HWWall& wall : result.maskedOffset)
if ((wall.flags & HWWall::HWF_SKYHACK) != 0)
incompatible = true;
if (result.translucent.size() != 0 || result.translucentBorder.size() != 0 || incompatible)
{
// For things that HWWall doesn't do correctly when drawn into the level mesh for one reason or another.
sideBlock.NeedsImmediateRendering = true;
}
else
{
for (const HWWall& portal : result.portals)
sideBlock.WallPortals.Push(portal);
}
/*
// final pass: translucent stuff
state.AlphaFunc(Alpha_GEqual, gl_mask_sprite_threshold);
@ -1102,9 +1138,6 @@ void DoomLevelMesh::CreateSide(FLevelLocals& doomMap, unsigned int sideIndex)
state.SetRenderStyle(STYLE_Normal);
*/
for (const HWWall& portal : result.portals)
sideBlock.WallPortals.Push(portal);
for (const HWMissing& missing : result.upper)
sideBlock.MissingUpper.Push(missing);

View file

@ -84,6 +84,7 @@ struct SideSurfaceBlock
TArray<HWMissing> MissingLower;
TArray<HWDecalCreateInfo> Decals;
bool InSideDecalsList = false;
bool NeedsImmediateRendering = false;
TArray<DrawRangeInfo> DrawRanges;
SurfaceUpdateType UpdateType = SurfaceUpdateType::None;
LightListAllocInfo Lights;
@ -152,7 +153,7 @@ public:
void ProcessDecals(HWDrawInfo* drawinfo, FRenderState& state);
void AddSectorsToDrawLists(const TArray<int>& sectors, LevelMeshDrawLists& lists);
void AddSidesToDrawLists(const TArray<int>& sides, LevelMeshDrawLists& lists, HWDrawInfo* di);
void AddSidesToDrawLists(const TArray<int>& sides, LevelMeshDrawLists& lists, HWDrawInfo* di, FRenderState& state);
TArray<HWWall>& GetSidePortals(int sideIndex);

View file

@ -447,12 +447,13 @@ void HWDrawInfo::RenderPVS(bool drawpsprites, FRenderState& state)
}
else
{
// Anything outside the BSP using this?
viewx = FLOAT2FIXED(Viewpoint.Pos.X);
viewy = FLOAT2FIXED(Viewpoint.Pos.Y);
multithread = false;
uselevelmesh = true;
validcount++; // used for processing sidedefs only once by the renderer.
Bsp.Clock();
ClipWall.Clock();
@ -504,6 +505,14 @@ void HWDrawInfo::RenderPVS(bool drawpsprites, FRenderState& state)
}
}
if (gl_levelmesh)
level.levelMesh->CurFrameStats.Portals++;
SeenFlatsDrawLists.Clear();
SeenSidesDrawLists.Clear();
level.levelMesh->AddSectorsToDrawLists(SeenSectors.Get(), SeenFlatsDrawLists);
level.levelMesh->AddSidesToDrawLists(SeenSides.Get(), SeenSidesDrawLists, this, state);
if (gl_render_things)
{
for (int subIndex : SeenSubsectors.Get())
@ -537,6 +546,43 @@ void HWDrawInfo::RenderPVS(bool drawpsprites, FRenderState& state)
}
}
void HWDrawInfo::ProcessSeg(seg_t* seg, FRenderState& state)
{
subsector_t* sub = seg->Subsector;
sector_t* front, * back;
front = hw_FakeFlat(drawctx, sub->sector, in_area, false);
auto backsector = seg->backsector;
if (!backsector && seg->linedef->isVisualPortal() && seg->sidedef == seg->linedef->sidedef[0]) // For one-sided portals use the portal's destination sector as backsector.
{
auto portal = seg->linedef->getPortal();
backsector = portal->mDestination->frontsector;
back = hw_FakeFlat(drawctx, backsector, in_area, true);
if (front->floorplane.isSlope() || front->ceilingplane.isSlope() || back->floorplane.isSlope() || back->ceilingplane.isSlope())
{
// Having a one-sided portal like this with slopes is too messy so let's ignore that case.
back = nullptr;
}
}
else if (backsector)
{
if (front->sectornum == backsector->sectornum || (seg->sidedef->Flags & WALLF_POLYOBJ))
{
back = front;
}
else
{
back = hw_FakeFlat(drawctx, backsector, in_area, true);
}
}
else back = nullptr;
HWMeshHelper result;
HWWallDispatcher disp(this);
HWWall wall;
wall.sub = sub;
wall.Process(&disp, state, seg, front, back);
}
//-----------------------------------------------------------------------------
//
// CreateScene
@ -569,14 +615,6 @@ void HWDrawInfo::CreateScene(bool drawpsprites, FRenderState& state)
RenderPVS(drawpsprites, state);
if (gl_levelmesh)
level.levelMesh->CurFrameStats.Portals++;
SeenFlatsDrawLists.Clear();
SeenSidesDrawLists.Clear();
level.levelMesh->AddSectorsToDrawLists(SeenSectors.Get(), SeenFlatsDrawLists);
level.levelMesh->AddSidesToDrawLists(SeenSides.Get(), SeenSidesDrawLists, this);
// And now the crappy hacks that have to be done to avoid rendering anomalies.
// These cannot be multithreaded when the time comes because all these depend
// on the global 'validcount' variable.

View file

@ -316,6 +316,8 @@ public:
}
}
void ProcessSeg(seg_t* seg, FRenderState& state);
HWPortal * FindPortal(const void * src);
void RenderBSPNode(void *node, FRenderState& state);
void RenderOrthoNoFog(FRenderState& state);

View file

@ -158,6 +158,27 @@ bool hw_CheckClip(side_t * sidedef, sector_t * frontsector, sector_t * backsecto
if (frustum)
{
if (frontsector->GetTexture(sector_t::ceiling) == skyflatnum)
{
fs_ceilingheight1 = 32768.0;
fs_ceilingheight2 = 32768.0;
}
if (frontsector->GetTexture(sector_t::floor) == skyflatnum)
{
fs_floorheight1 = -32768.0;
fs_floorheight1 = -32768.0;
}
if (backsector->GetTexture(sector_t::ceiling) == skyflatnum)
{
bs_ceilingheight1 = 32768.0;
bs_ceilingheight2 = 32768.0;
}
if (backsector->GetTexture(sector_t::floor) == skyflatnum)
{
bs_floorheight1 = -32768.0;
bs_floorheight1 = -32768.0;
}
// Is the line visible by the camera's clip frustum?
DVector3 p0(linedef->v1->fX(), std::min(bs_ceilingheight1, fs_ceilingheight1), linedef->v1->fY());
DVector3 p1(linedef->v2->fX(), std::min(bs_ceilingheight2, fs_ceilingheight2), linedef->v2->fY());