rewrite of HWWalls to allow grabbing the output from the render item generator.

This commit is contained in:
Christoph Oelckers 2023-10-19 18:35:51 +02:00
parent d65d1a3b82
commit 9cd57faec1
8 changed files with 431 additions and 299 deletions

View file

@ -42,6 +42,7 @@
#include "hw_clock.h"
#include "flatvertices.h"
#include "hw_vertexbuilder.h"
#include "hw_walldispatcher.h"
#ifdef ARCH_IA32
#include <immintrin.h>
@ -105,6 +106,7 @@ static RenderJobQueue jobQueue; // One static queue is sufficient here. This cod
void HWDrawInfo::WorkerThread()
{
sector_t *front, *back;
HWWallDispatcher disp(this);
WTTotal.Clock();
isWorkerThread = true; // for adding asserts in GL API code. The worker thread may never call any GL API.
@ -169,7 +171,7 @@ void HWDrawInfo::WorkerThread()
}
else back = nullptr;
wall.Process(this, job->seg, front, back);
wall.Process(&disp, job->seg, front, back);
rendered_lines++;
SetupWall.Unclock();
break;
@ -348,9 +350,10 @@ void HWDrawInfo::AddLine (seg_t *seg, bool portalclip)
else
{
HWWall wall;
HWWallDispatcher disp(this);
SetupWall.Clock();
wall.sub = seg->Subsector;
wall.Process(this, seg, currentsector, backsector);
wall.Process(&disp, seg, currentsector, backsector);
rendered_lines++;
SetupWall.Unclock();
}

View file

@ -214,7 +214,6 @@ private:
int CalcLightLevel(int lightlevel, int rellight, bool weapon, int blendfactor);
PalEntry CalcLightColor(int light, PalEntry pe, int blendfactor);
float GetFogDensity(int lightlevel, PalEntry fogcolor, int sectorfogdensity, int blendfactor);
bool CheckFog(sector_t *frontsector, sector_t *backsector);
WeaponLighting GetWeaponLighting(sector_t *viewsector, const DVector3 &pos, int cm, area_t in_area, const DVector3 &playerpos);
void PreparePlayerSprites2D(sector_t * viewsector, area_t in_area);

View file

@ -13,6 +13,8 @@
#pragma warning(disable:4244)
#endif
bool CheckFog(FLevelLocals* Level, sector_t* frontsector, sector_t* backsector, ELightMode lightmode);
struct HWHorizonInfo;
struct HWSkyInfo;
struct F3DFloor;
@ -113,6 +115,11 @@ struct texcoord
};
struct HWDrawInfo;
class HWWall;
// this only exists to keep HWWallDispatcher trivial
struct HWWallDispatcher;
class HWWall
{
@ -121,13 +128,13 @@ public:
enum
{
HWF_CLAMPX=1,
HWF_CLAMPY=2,
HWF_SKYHACK=4,
HWF_GLOW=8, // illuminated by glowing flats
HWF_NOSPLITUPPER=16,
HWF_NOSPLITLOWER=32,
HWF_NOSPLIT=64,
HWF_CLAMPX = 1,
HWF_CLAMPY = 2,
HWF_SKYHACK = 4,
HWF_GLOW = 8, // illuminated by glowing flats
HWF_NOSPLITUPPER = 16,
HWF_NOSPLITLOWER = 32,
HWF_NOSPLIT = 64,
HWF_TRANSLUCENT = 128,
HWF_NOSLICE = 256
};
@ -151,13 +158,13 @@ public:
friend struct HWDrawList;
friend class HWPortal;
vertex_t * vertexes[2]; // required for polygon splitting
FGameTexture *texture;
TArray<lightlist_t> *lightlist;
LightmapSurface *lightmap;
vertex_t* vertexes[2]; // required for polygon splitting
FGameTexture* texture;
TArray<lightlist_t>* lightlist;
LightmapSurface* lightmap;
HWSeg glseg;
float ztop[2],zbottom[2];
float ztop[2], zbottom[2];
texcoord tcs[4];
texcoord lightuv[4];
float lindex;
@ -165,7 +172,7 @@ public:
FColormap Colormap;
ERenderStyle RenderStyle;
float ViewDistance;
short lightlevel;
@ -181,12 +188,17 @@ public:
union
{
// it's either one of them but never more!
FSectorPortal *secportal; // sector portal (formerly skybox)
HWSkyInfo * sky; // for normal sky
HWHorizonInfo * horizon; // for horizon information
FSectorPortalGroup * portal; // stacked sector portals
secplane_t * planemirror; // for plane mirrors
FLinePortalSpan *lineportal; // line-to-line portals
FSectorPortal* secportal; // sector portal (formerly skybox)
HWSkyInfo* sky; // for normal sky
HWHorizonInfo* horizon; // for horizon information
FSectorPortalGroup* portal; // stacked sector portals
secplane_t* planemirror; // for plane mirrors
FLinePortalSpan* lineportal; // line-to-line portals
struct
{
int portaltype; // for the mesh builder. Real portals can only be assigned when being rendered.
int portalplane;
};
};
@ -199,92 +211,92 @@ public:
unsigned int vertcount;
public:
seg_t * seg; // this gives the easiest access to all other structs involved
subsector_t * sub; // For polyobjects
sector_t *frontsector, *backsector;
//private:
seg_t* seg; // this gives the easiest access to all other structs involved
subsector_t* sub; // For polyobjects
sector_t* frontsector, * backsector;
//private:
void PutWall(HWDrawInfo *di, bool translucent);
void PutPortal(HWDrawInfo *di, int ptype, int plane);
void CheckTexturePosition(FTexCoordInfo *tci);
void PutWall(HWWallDispatcher* di, bool translucent);
void PutPortal(HWWallDispatcher* di, int ptype, int plane);
void CheckTexturePosition(FTexCoordInfo* tci);
void Put3DWall(HWDrawInfo *di, lightlist_t * lightlist, bool translucent);
bool SplitWallComplex(HWDrawInfo *di, sector_t * frontsector, bool translucent, float& maplightbottomleft, float& maplightbottomright);
void SplitWall(HWDrawInfo *di, sector_t * frontsector, bool translucent);
void Put3DWall(HWWallDispatcher* di, lightlist_t* lightlist, bool translucent);
bool SplitWallComplex(HWWallDispatcher* di, sector_t* frontsector, bool translucent, float& maplightbottomleft, float& maplightbottomright);
void SplitWall(HWWallDispatcher* di, sector_t* frontsector, bool translucent);
void SetupLights(HWDrawInfo *di, FDynLightData &lightdata);
void SetupLights(HWDrawInfo* di, FDynLightData& lightdata);
void MakeVertices(HWDrawInfo *di, bool nosplit);
void MakeVertices(HWDrawInfo* di, bool nosplit);
void SkyPlane(HWDrawInfo *di, sector_t *sector, int plane, bool allowmirror);
void SkyLine(HWDrawInfo *di, sector_t *sec, line_t *line);
void SkyNormal(HWDrawInfo *di, sector_t * fs,vertex_t * v1,vertex_t * v2);
void SkyTop(HWDrawInfo *di, seg_t * seg,sector_t * fs,sector_t * bs,vertex_t * v1,vertex_t * v2);
void SkyBottom(HWDrawInfo *di, seg_t * seg,sector_t * fs,sector_t * bs,vertex_t * v1,vertex_t * v2);
void SkyPlane(HWWallDispatcher* di, sector_t* sector, int plane, bool allowmirror);
void SkyLine(HWWallDispatcher* di, sector_t* sec, line_t* line);
void SkyNormal(HWWallDispatcher* di, sector_t* fs, vertex_t* v1, vertex_t* v2);
void SkyTop(HWWallDispatcher* di, seg_t* seg, sector_t* fs, sector_t* bs, vertex_t* v1, vertex_t* v2);
void SkyBottom(HWWallDispatcher* di, seg_t* seg, sector_t* fs, sector_t* bs, vertex_t* v1, vertex_t* v2);
bool DoHorizon(HWDrawInfo *di, seg_t * seg,sector_t * fs, vertex_t * v1,vertex_t * v2);
bool DoHorizon(HWWallDispatcher* di, seg_t* seg, sector_t* fs, vertex_t* v1, vertex_t* v2);
bool SetWallCoordinates(seg_t * seg, FTexCoordInfo *tci, float ceilingrefheight,
bool SetWallCoordinates(seg_t* seg, FTexCoordInfo* tci, float ceilingrefheight,
float topleft, float topright, float bottomleft, float bottomright, float t_ofs);
void DoTexture(HWDrawInfo *di, int type,seg_t * seg,int peg,
float ceilingrefheight, float floorrefheight,
float CeilingHeightstart,float CeilingHeightend,
float FloorHeightstart,float FloorHeightend,
float v_offset);
void DoTexture(HWWallDispatcher* di, int type, seg_t* seg, int peg,
float ceilingrefheight, float floorrefheight,
float CeilingHeightstart, float CeilingHeightend,
float FloorHeightstart, float FloorHeightend,
float v_offset);
void DoMidTexture(HWDrawInfo *di, seg_t * seg, bool drawfogboundary,
sector_t * front, sector_t * back,
sector_t * realfront, sector_t * realback,
float fch1, float fch2, float ffh1, float ffh2,
float bch1, float bch2, float bfh1, float bfh2, float zalign);
void DoMidTexture(HWWallDispatcher* di, seg_t* seg, bool drawfogboundary,
sector_t* front, sector_t* back,
sector_t* realfront, sector_t* realback,
float fch1, float fch2, float ffh1, float ffh2,
float bch1, float bch2, float bfh1, float bfh2, float zalign);
void GetPlanePos(F3DFloor::planeref * planeref, float & left, float & right);
void GetPlanePos(F3DFloor::planeref* planeref, float& left, float& right);
void BuildFFBlock(HWDrawInfo *di, seg_t * seg, F3DFloor * rover, int roverIndex,
float ff_topleft, float ff_topright,
float ff_bottomleft, float ff_bottomright);
void InverseFloors(HWDrawInfo *di, seg_t * seg, sector_t * frontsector,
float topleft, float topright,
float bottomleft, float bottomright);
void ClipFFloors(HWDrawInfo *di, seg_t * seg, F3DFloor * ffloor, int ffloorIndex, sector_t * frontsector,
float topleft, float topright,
float bottomleft, float bottomright);
void DoFFloorBlocks(HWDrawInfo *di, seg_t * seg, sector_t * frontsector, sector_t * backsector,
float fch1, float fch2, float ffh1, float ffh2,
float bch1, float bch2, float bfh1, float bfh2);
void BuildFFBlock(HWWallDispatcher* di, seg_t* seg, F3DFloor* rover, int roverIndex,
float ff_topleft, float ff_topright,
float ff_bottomleft, float ff_bottomright);
void InverseFloors(HWWallDispatcher* di, seg_t* seg, sector_t* frontsector,
float topleft, float topright,
float bottomleft, float bottomright);
void ClipFFloors(HWWallDispatcher* di, seg_t* seg, F3DFloor* ffloor, int ffloorIndex, sector_t* frontsector,
float topleft, float topright,
float bottomleft, float bottomright);
void DoFFloorBlocks(HWWallDispatcher* di, seg_t* seg, sector_t* frontsector, sector_t* backsector,
float fch1, float fch2, float ffh1, float ffh2,
float bch1, float bch2, float bfh1, float bfh2);
void ProcessDecal(HWDrawInfo *di, DBaseDecal *decal, const FVector3 &normal);
void ProcessDecals(HWDrawInfo *di);
void ProcessDecal(HWDrawInfo* di, DBaseDecal* decal, const FVector3& normal);
void ProcessDecals(HWDrawInfo* di);
int CreateVertices(FFlatVertex *&ptr, bool nosplit);
void SplitLeftEdge (FFlatVertex *&ptr);
void SplitRightEdge(FFlatVertex *&ptr);
void SplitUpperEdge(FFlatVertex *&ptr);
void SplitLowerEdge(FFlatVertex *&ptr);
int CreateVertices(FFlatVertex*& ptr, bool nosplit);
void SplitLeftEdge(FFlatVertex*& ptr);
void SplitRightEdge(FFlatVertex*& ptr);
void SplitUpperEdge(FFlatVertex*& ptr);
void SplitLowerEdge(FFlatVertex*& ptr);
void CountLeftEdge (unsigned &ptr);
void CountRightEdge(unsigned &ptr);
void CountLeftEdge(unsigned& ptr);
void CountRightEdge(unsigned& ptr);
int CountVertices();
void RenderWall(HWDrawInfo *di, FRenderState &state, int textured);
void RenderFogBoundary(HWDrawInfo *di, FRenderState &state);
void RenderMirrorSurface(HWDrawInfo *di, FRenderState &state);
void RenderTexturedWall(HWDrawInfo *di, FRenderState &state, int rflags);
void RenderTranslucentWall(HWDrawInfo *di, FRenderState &state);
void DrawDecalsForMirror(HWDrawInfo *di, FRenderState &state, TArray<HWDecal *> &decals);
void RenderWall(HWDrawInfo* di, FRenderState& state, int textured);
void RenderFogBoundary(HWDrawInfo* di, FRenderState& state);
void RenderMirrorSurface(HWDrawInfo* di, FRenderState& state);
void RenderTexturedWall(HWDrawInfo* di, FRenderState& state, int rflags);
void RenderTranslucentWall(HWDrawInfo* di, FRenderState& state);
void DrawDecalsForMirror(HWDrawInfo* di, FRenderState& state, TArray<HWDecal*>& decals);
public:
void Process(HWDrawInfo *di, seg_t *seg, sector_t *frontsector, sector_t *backsector);
void ProcessLowerMiniseg(HWDrawInfo *di, seg_t *seg, sector_t *frontsector, sector_t *backsector);
void Process(HWWallDispatcher* di, seg_t* seg, sector_t* frontsector, sector_t* backsector);
void ProcessLowerMiniseg(HWWallDispatcher* di, seg_t* seg, sector_t* frontsector, sector_t* backsector);
float PointOnSide(float x,float y)
float PointOnSide(float x, float y)
{
return -((y-glseg.y1)*(glseg.x2-glseg.x1)-(x-glseg.x1)*(glseg.y2-glseg.y1));
return -((y - glseg.y1) * (glseg.x2 - glseg.x1) - (x - glseg.x1) * (glseg.y2 - glseg.y1));
}
void DrawWall(HWDrawInfo *di, FRenderState &state, bool translucent);
void DrawWall(HWDrawInfo* di, FRenderState& state, bool translucent);
};

View file

@ -227,7 +227,7 @@ float HWDrawInfo::GetFogDensity(int lightlevel, PalEntry fogcolor, int sectorfog
//
//==========================================================================
bool HWDrawInfo::CheckFog(sector_t *frontsector, sector_t *backsector)
bool CheckFog(FLevelLocals* Level, sector_t *frontsector, sector_t *backsector, ELightMode lightmode)
{
if (frontsector == backsector) return false; // there can't be a boundary if both sides are in the same sector.

View file

@ -41,6 +41,7 @@
#include "hw_lightbuffer.h"
#include "hwrenderer/scene/hw_portal.h"
#include "hw_fakeflat.h"
#include "hw_walldispatcher.h"
//==========================================================================
//
@ -1117,7 +1118,8 @@ void HWDrawInfo::ProcessLowerMinisegs(TArray<seg_t *> &lowersegs)
{
seg_t * seg=lowersegs[j];
HWWall wall;
wall.ProcessLowerMiniseg(this, seg, seg->Subsector->render_sector, seg->PartnerSeg->Subsector->render_sector);
HWWallDispatcher disp(this);
wall.ProcessLowerMiniseg(&disp, seg, seg->Subsector->render_sector, seg->PartnerSeg->Subsector->render_sector);
rendered_lines++;
}
}

View file

@ -33,6 +33,7 @@
#include "hwrenderer/scene/hw_portal.h"
#include "hw_lighting.h"
#include "hw_material.h"
#include "hw_walldispatcher.h"
CVAR(Bool,gl_noskyboxes, false, 0)
@ -111,7 +112,7 @@ void HWSkyInfo::init(HWDrawInfo *di, int sky1, PalEntry FadeColor)
//
//==========================================================================
void HWWall::SkyPlane(HWDrawInfo *di, sector_t *sector, int plane, bool allowreflect)
void HWWall::SkyPlane(HWWallDispatcher *di, sector_t *sector, int plane, bool allowreflect)
{
int ptype = -1;
@ -121,10 +122,13 @@ void HWWall::SkyPlane(HWDrawInfo *di, sector_t *sector, int plane, bool allowref
// Either a regular sky or a skybox with skyboxes disabled
if ((sportal == nullptr && sector->GetTexture(plane) == skyflatnum) || (gl_noskyboxes && sportal != nullptr && sportal->mType == PORTS_SKYVIEWPOINT))
{
HWSkyInfo skyinfo;
skyinfo.init(di, sector->sky, Colormap.FadeColor);
ptype = PORTALTYPE_SKY;
sky = &skyinfo;
if (di->di)
{
HWSkyInfo skyinfo;
skyinfo.init(di->di, sector->sky, Colormap.FadeColor);
ptype = PORTALTYPE_SKY;
sky = &skyinfo;
}
PutPortal(di, ptype, plane);
}
else if (sportal != nullptr)
@ -140,7 +144,7 @@ void HWWall::SkyPlane(HWDrawInfo *di, sector_t *sector, int plane, bool allowref
{
if (sector->PortalBlocksView(plane)) return;
if (screen->instack[1 - plane]) return;
if (di->di && screen->instack[1 - plane]) return;
ptype = PORTALTYPE_SECTORSTACK;
portal = glport;
}
@ -157,11 +161,14 @@ void HWWall::SkyPlane(HWDrawInfo *di, sector_t *sector, int plane, bool allowref
}
else if (allowreflect && sector->GetReflect(plane) > 0 && !(di->Level->ib_compatflags & BCOMPATF_NOMIRRORS))
{
auto vpz = di->Viewpoint.Pos.Z;
if ((plane == sector_t::ceiling && vpz > sector->ceilingplane.fD()) ||
(plane == sector_t::floor && vpz < -sector->floorplane.fD())) return;
if (di->di)
{
auto vpz = di->di->Viewpoint.Pos.Z;
if ((plane == sector_t::ceiling && vpz > sector->ceilingplane.fD()) ||
(plane == sector_t::floor && vpz < -sector->floorplane.fD())) return;
planemirror = plane == sector_t::ceiling ? &sector->ceilingplane : &sector->floorplane;
}
ptype = PORTALTYPE_PLANEMIRROR;
planemirror = plane == sector_t::ceiling ? &sector->ceilingplane : &sector->floorplane;
}
if (ptype != -1)
{
@ -176,7 +183,7 @@ void HWWall::SkyPlane(HWDrawInfo *di, sector_t *sector, int plane, bool allowref
//
//==========================================================================
void HWWall::SkyLine(HWDrawInfo *di, sector_t *fs, line_t *line)
void HWWall::SkyLine(HWWallDispatcher *di, sector_t *fs, line_t *line)
{
FSectorPortal *secport = line->GetTransferredPortal();
HWSkyInfo skyinfo;
@ -192,7 +199,7 @@ void HWWall::SkyLine(HWDrawInfo *di, sector_t *fs, line_t *line)
}
else
{
skyinfo.init(di, fs->sky, Colormap.FadeColor);
if (di->di) skyinfo.init(di->di, fs->sky, Colormap.FadeColor);
ptype = PORTALTYPE_SKY;
sky = &skyinfo;
}
@ -210,7 +217,7 @@ void HWWall::SkyLine(HWDrawInfo *di, sector_t *fs, line_t *line)
//
//==========================================================================
void HWWall::SkyNormal(HWDrawInfo *di, sector_t * fs,vertex_t * v1,vertex_t * v2)
void HWWall::SkyNormal(HWWallDispatcher *di, sector_t * fs,vertex_t * v1,vertex_t * v2)
{
ztop[0]=ztop[1]=32768.0f;
zbottom[0]=zceil[0];
@ -229,7 +236,7 @@ void HWWall::SkyNormal(HWDrawInfo *di, sector_t * fs,vertex_t * v1,vertex_t * v2
//
//==========================================================================
void HWWall::SkyTop(HWDrawInfo *di, seg_t * seg,sector_t * fs,sector_t * bs,vertex_t * v1,vertex_t * v2)
void HWWall::SkyTop(HWWallDispatcher *di, seg_t * seg,sector_t * fs,sector_t * bs,vertex_t * v1,vertex_t * v2)
{
if (fs->GetTexture(sector_t::ceiling)==skyflatnum)
{
@ -323,7 +330,7 @@ void HWWall::SkyTop(HWDrawInfo *di, seg_t * seg,sector_t * fs,sector_t * bs,vert
//
//==========================================================================
void HWWall::SkyBottom(HWDrawInfo *di, seg_t * seg,sector_t * fs,sector_t * bs,vertex_t * v1,vertex_t * v2)
void HWWall::SkyBottom(HWWallDispatcher *di, seg_t * seg,sector_t * fs,sector_t * bs,vertex_t * v1,vertex_t * v2)
{
if (fs->GetTexture(sector_t::floor)==skyflatnum)
{
@ -343,8 +350,8 @@ void HWWall::SkyBottom(HWDrawInfo *di, seg_t * seg,sector_t * fs,sector_t * bs,v
}
else
{
// Special hack for Vrack2b
if (bs->floorplane.ZatPoint(di->Viewpoint.Pos) > di->Viewpoint.Pos.Z) return;
// Special hack for Vrack2b. For mesh based rendering this check needs to be done in the actual render pass!
if (di->di && bs->floorplane.ZatPoint(di->di->Viewpoint.Pos) > di->di->Viewpoint.Pos.Z) return;
}
}
zbottom[0]=zbottom[1]=-32768.0f;

View file

@ -0,0 +1,80 @@
#pragma once
struct HWMissing
{
side_t* side;
subsector_t* sub;
double plane;
};
struct HWMeshHelper
{
TArray<HWWall> list;
TArray<HWWall> translucent;
TArray<HWWall> portals;
TArray<HWMissing> lower;
TArray<HWMissing> upper;
};
struct HWWallDispatcher
{
FLevelLocals* Level;
HWDrawInfo* di;
HWMeshHelper* mh;
ELightMode lightmode;
HWWallDispatcher(HWDrawInfo* info)
{
Level = info->Level;
di = info;
mh = nullptr;
lightmode = info->lightmode;
}
HWWallDispatcher(FLevelLocals* lev, HWMeshHelper* help, ELightMode lm)
{
Level = lev;
di = nullptr;
mh = help;
lightmode = lm;
}
void AddUpperMissingTexture(side_t* side, subsector_t* sub, float height)
{
if (di) di->AddUpperMissingTexture(side, sub, height);
else
{
mh->upper.Reserve(1);
mh->upper.Last() = { side, sub, height };
}
}
void AddLowerMissingTexture(side_t* side, subsector_t* sub, float height)
{
if (di) di->AddUpperMissingTexture(side, sub, height);
else
{
mh->lower.Reserve(1);
mh->lower.Last() = { side, sub, height };
}
}
bool isFullbrightScene()
{
// The mesh builder cannot know this and must treat everything as not fullbright.
return di && di->isFullbrightScene();
}
void AddWall(HWWall* wal)
{
if (di) di->AddWall(wal);
else if (!(wal->flags & HWWall::HWF_TRANSLUCENT)) mh->list.Push(*wal);
else mh->translucent.Push(*wal);
}
void AddPortal(HWWall* wal)
{
mh->portals.Push(*wal);
}
};

View file

@ -43,6 +43,7 @@
#include "hw_lightbuffer.h"
#include "hw_renderstate.h"
#include "hw_skydome.h"
#include "hw_walldispatcher.h"
void SetGlowPlanes(FRenderState &state, const secplane_t& top, const secplane_t& bottom)
@ -80,7 +81,7 @@ void SetSplitPlanes(FRenderState& state, const secplane_t& top, const secplane_t
//
//==========================================================================
void HWWall::RenderWall(HWDrawInfo *di, FRenderState &state, int textured)
void HWWall::RenderWall(HWDrawInfo*di, FRenderState &state, int textured)
{
assert(vertcount > 0);
state.SetLightIndex(dynlightindex);
@ -94,7 +95,7 @@ void HWWall::RenderWall(HWDrawInfo *di, FRenderState &state, int textured)
//
//==========================================================================
void HWWall::RenderFogBoundary(HWDrawInfo *di, FRenderState &state)
void HWWall::RenderFogBoundary(HWDrawInfo*di, FRenderState &state)
{
if (gl_fogmode && !di->isFullbrightScene())
{
@ -117,7 +118,7 @@ void HWWall::RenderFogBoundary(HWDrawInfo *di, FRenderState &state)
//
//
//==========================================================================
void HWWall::RenderMirrorSurface(HWDrawInfo *di, FRenderState &state)
void HWWall::RenderMirrorSurface(HWDrawInfo*di, FRenderState &state)
{
if (!TexMan.mirrorTexture.isValid()) return;
@ -179,7 +180,7 @@ static const uint8_t renderwalltotier[] =
CVAR(Bool, hw_npottest, false, 0)
#endif
void HWWall::RenderTexturedWall(HWDrawInfo *di, FRenderState &state, int rflags)
void HWWall::RenderTexturedWall(HWDrawInfo*di, FRenderState &state, int rflags)
{
int tmode = state.GetTextureMode();
int rel = rellight + getExtraLight();
@ -312,7 +313,7 @@ void HWWall::RenderTexturedWall(HWDrawInfo *di, FRenderState &state, int rflags)
//
//==========================================================================
void HWWall::RenderTranslucentWall(HWDrawInfo *di, FRenderState &state)
void HWWall::RenderTranslucentWall(HWDrawInfo*di, FRenderState &state)
{
state.SetRenderStyle(RenderStyle);
if (texture)
@ -338,7 +339,7 @@ void HWWall::RenderTranslucentWall(HWDrawInfo *di, FRenderState &state)
//
//
//==========================================================================
void HWWall::DrawWall(HWDrawInfo *di, FRenderState &state, bool translucent)
void HWWall::DrawWall(HWDrawInfo*di, FRenderState &state, bool translucent)
{
if (screen->BuffersArePersistent())
{
@ -379,7 +380,7 @@ void HWWall::DrawWall(HWDrawInfo *di, FRenderState &state, bool translucent)
//
//==========================================================================
void HWWall::SetupLights(HWDrawInfo *di, FDynLightData &lightdata)
void HWWall::SetupLights(HWDrawInfo*di, FDynLightData &lightdata)
{
lightdata.Clear();
@ -493,58 +494,67 @@ const char HWWall::passflag[] = {
//
//
//==========================================================================
void HWWall::PutWall(HWDrawInfo *di, bool translucent)
void HWWall::PutWall(HWWallDispatcher *di, bool translucent)
{
if (texture && texture->GetTranslucency() && passflag[type] == 2)
{
translucent = true;
}
auto ddi = di->di;
if (translucent)
{
flags |= HWF_TRANSLUCENT;
ViewDistance = (di->Viewpoint.Pos - (seg->linedef->v1->fPos() + seg->linedef->Delta() / 2)).XY().LengthSquared();
}
if (di->isFullbrightScene())
if (di->di)
{
// light planes don't get drawn with fullbright rendering
if (texture == NULL) return;
Colormap.Clear();
}
if (di->isFullbrightScene() || (Colormap.LightColor.isWhite() && lightlevel == 255))
{
flags &= ~HWF_GLOW;
}
if (!screen->BuffersArePersistent())
{
if (di->Level->HasDynamicLights && !di->isFullbrightScene() && texture != nullptr)
if (translucent)
{
SetupLights(di, lightdata);
ViewDistance = (ddi->Viewpoint.Pos - (seg->linedef->v1->fPos() + seg->linedef->Delta() / 2)).XY().LengthSquared();
}
MakeVertices(di, translucent);
}
bool solid;
if (passflag[type] == 1) solid = true;
else if (type == RENDERWALL_FFBLOCK) solid = texture && !texture->isMasked();
else solid = false;
bool hasDecals = solid && seg->sidedef && seg->sidedef->AttachedDecals;
if (hasDecals)
{
// If we want to use the light infos for the decal we cannot delay the creation until the render pass.
if (screen->BuffersArePersistent())
if (ddi->isFullbrightScene())
{
if (di->Level->HasDynamicLights && !di->isFullbrightScene() && texture != nullptr)
// light planes don't get drawn with fullbright rendering
if (texture == NULL) return;
Colormap.Clear();
}
if (ddi->isFullbrightScene() || (Colormap.LightColor.isWhite() && lightlevel == 255))
{
flags &= ~HWF_GLOW;
}
if (!screen->BuffersArePersistent())
{
if (ddi->Level->HasDynamicLights && !ddi->isFullbrightScene() && texture != nullptr)
{
SetupLights(di, lightdata);
SetupLights(ddi, lightdata);
}
MakeVertices(ddi, translucent);
}
bool solid;
if (passflag[type] == 1) solid = true;
else if (type == RENDERWALL_FFBLOCK) solid = texture && !texture->isMasked();
else solid = false;
bool hasDecals = solid && seg->sidedef && seg->sidedef->AttachedDecals;
if (hasDecals)
{
// If we want to use the light infos for the decal we cannot delay the creation until the render pass.
if (screen->BuffersArePersistent())
{
if (ddi->Level->HasDynamicLights && !ddi->isFullbrightScene() && texture != nullptr)
{
SetupLights(ddi, lightdata);
}
}
ProcessDecals(ddi);
}
ProcessDecals(di);
}
@ -563,113 +573,123 @@ void HWWall::PutWall(HWDrawInfo *di, bool translucent)
//
//==========================================================================
void HWWall::PutPortal(HWDrawInfo *di, int ptype, int plane)
void HWWall::PutPortal(HWWallDispatcher *di, int ptype, int plane)
{
HWPortal * portal = nullptr;
MakeVertices(di, false);
switch (ptype)
auto ddi = di->di;
if (ddi)
{
// portals don't go into the draw list.
// Instead they are added to the portal manager
case PORTALTYPE_HORIZON:
horizon = portalState.UniqueHorizons.Get(horizon);
portal = di->FindPortal(horizon);
if (!portal)
MakeVertices(ddi, false);
switch (ptype)
{
portal = new HWHorizonPortal(&portalState, horizon, di->Viewpoint);
di->Portals.Push(portal);
}
portal->AddLine(this);
break;
case PORTALTYPE_SKYBOX:
portal = di->FindPortal(secportal);
if (!portal)
{
// either a regular skybox or an Eternity-style horizon
if (secportal->mType != PORTS_SKYVIEWPOINT) portal = new HWEEHorizonPortal(&portalState, secportal);
else
{
portal = new HWSkyboxPortal(&portalState, secportal);
di->Portals.Push(portal);
}
}
portal->AddLine(this);
break;
case PORTALTYPE_SECTORSTACK:
portal = di->FindPortal(this->portal);
if (!portal)
{
portal = new HWSectorStackPortal(&portalState, this->portal);
di->Portals.Push(portal);
}
portal->AddLine(this);
break;
case PORTALTYPE_PLANEMIRROR:
if (portalState.PlaneMirrorMode * planemirror->fC() <= 0)
{
planemirror = portalState.UniquePlaneMirrors.Get(planemirror);
portal = di->FindPortal(planemirror);
// portals don't go into the draw list.
// Instead they are added to the portal manager
case PORTALTYPE_HORIZON:
horizon = portalState.UniqueHorizons.Get(horizon);
portal = ddi->FindPortal(horizon);
if (!portal)
{
portal = new HWPlaneMirrorPortal(&portalState, planemirror);
di->Portals.Push(portal);
portal = new HWHorizonPortal(&portalState, horizon, ddi->Viewpoint);
ddi->Portals.Push(portal);
}
portal->AddLine(this);
}
break;
break;
case PORTALTYPE_MIRROR:
portal = di->FindPortal(seg->linedef);
if (!portal)
{
portal = new HWMirrorPortal(&portalState, seg->linedef);
di->Portals.Push(portal);
}
portal->AddLine(this);
if (gl_mirror_envmap)
{
// draw a reflective layer over the mirror
di->AddMirrorSurface(this);
}
break;
case PORTALTYPE_LINETOLINE:
if (!lineportal)
return;
portal = di->FindPortal(lineportal);
if (!portal)
{
line_t *otherside = lineportal->lines[0]->mDestination;
if (otherside != nullptr && otherside->portalindex < di->Level->linePortals.Size())
case PORTALTYPE_SKYBOX:
portal = ddi->FindPortal(secportal);
if (!portal)
{
di->ProcessActorsInPortal(otherside->getPortal()->mGroup, di->in_area);
// either a regular skybox or an Eternity-style horizon
if (secportal->mType != PORTS_SKYVIEWPOINT) portal = new HWEEHorizonPortal(&portalState, secportal);
else
{
portal = new HWSkyboxPortal(&portalState, secportal);
ddi->Portals.Push(portal);
}
}
portal = new HWLineToLinePortal(&portalState, lineportal);
di->Portals.Push(portal);
}
portal->AddLine(this);
break;
portal->AddLine(this);
break;
case PORTALTYPE_SKY:
sky = portalState.UniqueSkies.Get(sky);
portal = di->FindPortal(sky);
if (!portal)
case PORTALTYPE_SECTORSTACK:
portal = ddi->FindPortal(this->portal);
if (!portal)
{
portal = new HWSectorStackPortal(&portalState, this->portal);
ddi->Portals.Push(portal);
}
portal->AddLine(this);
break;
case PORTALTYPE_PLANEMIRROR:
if (portalState.PlaneMirrorMode * planemirror->fC() <= 0)
{
planemirror = portalState.UniquePlaneMirrors.Get(planemirror);
portal = ddi->FindPortal(planemirror);
if (!portal)
{
portal = new HWPlaneMirrorPortal(&portalState, planemirror);
ddi->Portals.Push(portal);
}
portal->AddLine(this);
}
break;
case PORTALTYPE_MIRROR:
portal = ddi->FindPortal(seg->linedef);
if (!portal)
{
portal = new HWMirrorPortal(&portalState, seg->linedef);
ddi->Portals.Push(portal);
}
portal->AddLine(this);
if (gl_mirror_envmap)
{
// draw a reflective layer over the mirror
ddi->AddMirrorSurface(this);
}
break;
case PORTALTYPE_LINETOLINE:
if (!lineportal)
return;
portal = ddi->FindPortal(lineportal);
if (!portal)
{
line_t* otherside = lineportal->lines[0]->mDestination;
if (otherside != nullptr && otherside->portalindex < ddi->Level->linePortals.Size())
{
ddi->ProcessActorsInPortal(otherside->getPortal()->mGroup, ddi->in_area);
}
portal = new HWLineToLinePortal(&portalState, lineportal);
ddi->Portals.Push(portal);
}
portal->AddLine(this);
break;
case PORTALTYPE_SKY:
sky = portalState.UniqueSkies.Get(sky);
portal = ddi->FindPortal(sky);
if (!portal)
{
portal = new HWSkyPortal(screen->mSkyData, &portalState, sky);
ddi->Portals.Push(portal);
}
portal->AddLine(this);
break;
}
vertcount = 0;
if (plane != -1 && portal)
{
portal = new HWSkyPortal(screen->mSkyData, &portalState, sky);
di->Portals.Push(portal);
portal->planesused |= (1 << plane);
}
portal->AddLine(this);
break;
}
vertcount = 0;
if (plane != -1 && portal)
else
{
portal->planesused |= (1<<plane);
portaltype = ptype;
portalplane = plane;
di->AddPortal(this);
}
}
@ -679,7 +699,7 @@ void HWWall::PutPortal(HWDrawInfo *di, int ptype, int plane)
//
//==========================================================================
void HWWall::Put3DWall(HWDrawInfo *di, lightlist_t * lightlist, bool translucent)
void HWWall::Put3DWall(HWWallDispatcher *di, lightlist_t * lightlist, bool translucent)
{
// only modify the light di->Level-> if it doesn't originate from the seg's frontsector. This is to account for light transferring effects
if (lightlist->p_lightlevel != &seg->sidedef->sector->lightlevel)
@ -699,7 +719,7 @@ void HWWall::Put3DWall(HWDrawInfo *di, lightlist_t * lightlist, bool translucent
//
//==========================================================================
bool HWWall::SplitWallComplex(HWDrawInfo *di, sector_t * frontsector, bool translucent, float& maplightbottomleft, float& maplightbottomright)
bool HWWall::SplitWallComplex(HWWallDispatcher *di, sector_t * frontsector, bool translucent, float& maplightbottomleft, float& maplightbottomright)
{
// check for an intersection with the upper plane
if ((maplightbottomleft<ztop[0] && maplightbottomright>ztop[1]) ||
@ -793,7 +813,7 @@ bool HWWall::SplitWallComplex(HWDrawInfo *di, sector_t * frontsector, bool trans
return false;
}
void HWWall::SplitWall(HWDrawInfo *di, sector_t * frontsector, bool translucent)
void HWWall::SplitWall(HWWallDispatcher *di, sector_t * frontsector, bool translucent)
{
float maplightbottomleft;
float maplightbottomright;
@ -908,7 +928,7 @@ out:
//
//
//==========================================================================
bool HWWall::DoHorizon(HWDrawInfo *di, seg_t * seg,sector_t * fs, vertex_t * v1,vertex_t * v2)
bool HWWall::DoHorizon(HWWallDispatcher *di, seg_t * seg,sector_t * fs, vertex_t * v1,vertex_t * v2)
{
HWHorizonInfo hi;
lightlist_t * light;
@ -917,64 +937,73 @@ bool HWWall::DoHorizon(HWDrawInfo *di, seg_t * seg,sector_t * fs, vertex_t * v1,
ztop[1] = ztop[0] = fs->GetPlaneTexZ(sector_t::ceiling);
zbottom[1] = zbottom[0] = fs->GetPlaneTexZ(sector_t::floor);
auto vpz = di->Viewpoint.Pos.Z;
if (vpz < fs->GetPlaneTexZ(sector_t::ceiling))
auto ddi = di->di;
if (ddi)
{
auto vpz = ddi->Viewpoint.Pos.Z;
if (vpz < fs->GetPlaneTexZ(sector_t::ceiling))
{
if (vpz > fs->GetPlaneTexZ(sector_t::floor))
zbottom[1] = zbottom[0] = vpz;
if (fs->GetTexture(sector_t::ceiling) == skyflatnum)
{
SkyPlane(di, fs, sector_t::ceiling, false);
}
else
{
hi.plane.GetFromSector(fs, sector_t::ceiling);
hi.lightlevel = hw_ClampLight(fs->GetCeilingLight());
hi.colormap = fs->Colormap;
hi.specialcolor = fs->SpecialColors[sector_t::ceiling];
if (fs->e->XFloor.ffloors.Size())
{
light = P_GetPlaneLight(fs, &fs->ceilingplane, true);
if (!(fs->GetFlags(sector_t::ceiling) & PLANEF_ABSLIGHTING)) hi.lightlevel = hw_ClampLight(*light->p_lightlevel);
hi.colormap.CopyLight(light->extra_colormap);
}
if (ddi->isFullbrightScene()) hi.colormap.Clear();
horizon = &hi;
PutPortal(di, PORTALTYPE_HORIZON, -1);
}
ztop[1] = ztop[0] = zbottom[0];
}
if (vpz > fs->GetPlaneTexZ(sector_t::floor))
zbottom[1] = zbottom[0] = vpz;
if (fs->GetTexture(sector_t::ceiling) == skyflatnum)
{
SkyPlane(di, fs, sector_t::ceiling, false);
}
else
{
hi.plane.GetFromSector(fs, sector_t::ceiling);
hi.lightlevel = hw_ClampLight(fs->GetCeilingLight());
hi.colormap = fs->Colormap;
hi.specialcolor = fs->SpecialColors[sector_t::ceiling];
if (fs->e->XFloor.ffloors.Size())
zbottom[1] = zbottom[0] = fs->GetPlaneTexZ(sector_t::floor);
if (fs->GetTexture(sector_t::floor) == skyflatnum)
{
light = P_GetPlaneLight(fs, &fs->ceilingplane, true);
if(!(fs->GetFlags(sector_t::ceiling)&PLANEF_ABSLIGHTING)) hi.lightlevel = hw_ClampLight(*light->p_lightlevel);
hi.colormap.CopyLight(light->extra_colormap);
SkyPlane(di, fs, sector_t::floor, false);
}
else
{
hi.plane.GetFromSector(fs, sector_t::floor);
hi.lightlevel = hw_ClampLight(fs->GetFloorLight());
hi.colormap = fs->Colormap;
hi.specialcolor = fs->SpecialColors[sector_t::floor];
if (di->isFullbrightScene()) hi.colormap.Clear();
horizon = &hi;
PutPortal(di, PORTALTYPE_HORIZON, -1);
if (fs->e->XFloor.ffloors.Size())
{
light = P_GetPlaneLight(fs, &fs->floorplane, false);
if (!(fs->GetFlags(sector_t::floor) & PLANEF_ABSLIGHTING)) hi.lightlevel = hw_ClampLight(*light->p_lightlevel);
hi.colormap.CopyLight(light->extra_colormap);
}
if (ddi->isFullbrightScene()) hi.colormap.Clear();
horizon = &hi;
PutPortal(di, PORTALTYPE_HORIZON, -1);
}
}
ztop[1] = ztop[0] = zbottom[0];
}
if (vpz > fs->GetPlaneTexZ(sector_t::floor))
}
else
{
zbottom[1] = zbottom[0] = fs->GetPlaneTexZ(sector_t::floor);
if (fs->GetTexture(sector_t::floor) == skyflatnum)
{
SkyPlane(di, fs, sector_t::floor, false);
}
else
{
hi.plane.GetFromSector(fs, sector_t::floor);
hi.lightlevel = hw_ClampLight(fs->GetFloorLight());
hi.colormap = fs->Colormap;
hi.specialcolor = fs->SpecialColors[sector_t::floor];
if (fs->e->XFloor.ffloors.Size())
{
light = P_GetPlaneLight(fs, &fs->floorplane, false);
if(!(fs->GetFlags(sector_t::floor)&PLANEF_ABSLIGHTING)) hi.lightlevel = hw_ClampLight(*light->p_lightlevel);
hi.colormap.CopyLight(light->extra_colormap);
}
if (di->isFullbrightScene()) hi.colormap.Clear();
horizon = &hi;
PutPortal(di, PORTALTYPE_HORIZON, -1);
}
// we cannot build the real portal yet, the mesh builder just needs a generic 'horizon' portal that needs to be filled in in the render pass.
PutPortal(di, PORTALTYPE_HORIZON, -1);
}
return true;
}
@ -1225,7 +1254,7 @@ static void GetTexCoordInfo(FGameTexture *tex, FTexCoordInfo *tci, side_t *side,
// Handle one sided walls, upper and lower texture
//
//==========================================================================
void HWWall::DoTexture(HWDrawInfo *di, int _type,seg_t * seg, int peg,
void HWWall::DoTexture(HWWallDispatcher *di, int _type,seg_t * seg, int peg,
float ceilingrefheight,float floorrefheight,
float topleft,float topright,
float bottomleft,float bottomright,
@ -1284,7 +1313,7 @@ void HWWall::DoTexture(HWDrawInfo *di, int _type,seg_t * seg, int peg,
// Add this wall to the render list
sector_t * sec = sub ? sub->sector : seg->frontsector;
if (sec->e->XFloor.lightlist.Size()==0 || di->isFullbrightScene()) PutWall(di, false);
if (sec->e->XFloor.lightlist.Size()==0 || di->isFullbrightScene()) PutWall(di, false);
else SplitWall(di, sec, false);
}
@ -1299,7 +1328,7 @@ void HWWall::DoTexture(HWDrawInfo *di, int _type,seg_t * seg, int peg,
//
//==========================================================================
void HWWall::DoMidTexture(HWDrawInfo *di, seg_t * seg, bool drawfogboundary,
void HWWall::DoMidTexture(HWWallDispatcher *di, seg_t * seg, bool drawfogboundary,
sector_t * front, sector_t * back,
sector_t * realfront, sector_t * realback,
float fch1, float fch2, float ffh1, float ffh2,
@ -1634,7 +1663,7 @@ void HWWall::DoMidTexture(HWDrawInfo *di, seg_t * seg, bool drawfogboundary,
//
//
//==========================================================================
void HWWall::BuildFFBlock(HWDrawInfo *di, seg_t * seg, F3DFloor * rover, int roverIndex,
void HWWall::BuildFFBlock(HWWallDispatcher *di, seg_t * seg, F3DFloor * rover, int roverIndex,
float ff_topleft, float ff_topright,
float ff_bottomleft, float ff_bottomright)
{
@ -1788,7 +1817,7 @@ __forceinline void HWWall::GetPlanePos(F3DFloor::planeref *planeref, float &left
//
//
//==========================================================================
void HWWall::InverseFloors(HWDrawInfo *di, seg_t * seg, sector_t * frontsector,
void HWWall::InverseFloors(HWWallDispatcher *di, seg_t * seg, sector_t * frontsector,
float topleft, float topright,
float bottomleft, float bottomright)
{
@ -1839,7 +1868,7 @@ void HWWall::InverseFloors(HWDrawInfo *di, seg_t * seg, sector_t * frontsector,
//
//
//==========================================================================
void HWWall::ClipFFloors(HWDrawInfo *di, seg_t * seg, F3DFloor * ffloor, int ffloorIndex, sector_t * frontsector,
void HWWall::ClipFFloors(HWWallDispatcher *di, seg_t * seg, F3DFloor * ffloor, int ffloorIndex, sector_t * frontsector,
float topleft, float topright,
float bottomleft, float bottomright)
{
@ -1913,7 +1942,7 @@ done:
//
//
//==========================================================================
void HWWall::DoFFloorBlocks(HWDrawInfo *di, seg_t * seg, sector_t * frontsector, sector_t * backsector,
void HWWall::DoFFloorBlocks(HWWallDispatcher *di, seg_t * seg, sector_t * frontsector, sector_t * backsector,
float fch1, float fch2, float ffh1, float ffh2,
float bch1, float bch2, float bfh1, float bfh2)
@ -2018,7 +2047,7 @@ inline int CalcRelLight(int lightlevel, int orglightlevel, int rel)
//
//
//==========================================================================
void HWWall::Process(HWDrawInfo *di, seg_t *seg, sector_t * frontsector, sector_t * backsector)
void HWWall::Process(HWWallDispatcher *di, seg_t *seg, sector_t * frontsector, sector_t * backsector)
{
vertex_t * v1, *v2;
float fch1;
@ -2273,7 +2302,7 @@ void HWWall::Process(HWDrawInfo *di, seg_t *seg, sector_t * frontsector, sector_
/* mid texture */
sector_t *backsec = isportal? seg->linedef->getPortalDestination()->frontsector : backsector;
bool drawfogboundary = !di->isFullbrightScene() && di->CheckFog(frontsector, backsec);
bool drawfogboundary = !di->isFullbrightScene() && CheckFog(di->Level, frontsector, backsec, di->lightmode);
auto tex = TexMan.GetGameTexture(seg->sidedef->GetTexture(side_t::mid), true);
if (tex != NULL && tex->isValid())
{
@ -2378,7 +2407,7 @@ void HWWall::Process(HWDrawInfo *di, seg_t *seg, sector_t * frontsector, sector_
//
//
//==========================================================================
void HWWall::ProcessLowerMiniseg(HWDrawInfo *di, seg_t *seg, sector_t * frontsector, sector_t * backsector)
void HWWall::ProcessLowerMiniseg(HWWallDispatcher *di, seg_t *seg, sector_t * frontsector, sector_t * backsector)
{
if (frontsector->GetTexture(sector_t::floor) == skyflatnum) return;
lightlist = NULL;