diff --git a/src/rendering/hwrenderer/scene/hw_bsp.cpp b/src/rendering/hwrenderer/scene/hw_bsp.cpp index 4110063e8..c79e34110 100644 --- a/src/rendering/hwrenderer/scene/hw_bsp.cpp +++ b/src/rendering/hwrenderer/scene/hw_bsp.cpp @@ -42,6 +42,7 @@ #include "hw_clock.h" #include "flatvertices.h" #include "hw_vertexbuilder.h" +#include "hw_walldispatcher.h" #ifdef ARCH_IA32 #include @@ -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(); } diff --git a/src/rendering/hwrenderer/scene/hw_drawinfo.h b/src/rendering/hwrenderer/scene/hw_drawinfo.h index 68afcb246..af043f035 100644 --- a/src/rendering/hwrenderer/scene/hw_drawinfo.h +++ b/src/rendering/hwrenderer/scene/hw_drawinfo.h @@ -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); diff --git a/src/rendering/hwrenderer/scene/hw_drawstructs.h b/src/rendering/hwrenderer/scene/hw_drawstructs.h index 1ccd2603d..af65baf09 100644 --- a/src/rendering/hwrenderer/scene/hw_drawstructs.h +++ b/src/rendering/hwrenderer/scene/hw_drawstructs.h @@ -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; - LightmapSurface *lightmap; + vertex_t* vertexes[2]; // required for polygon splitting + FGameTexture* texture; + TArray* 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 &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& 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); }; diff --git a/src/rendering/hwrenderer/scene/hw_lighting.cpp b/src/rendering/hwrenderer/scene/hw_lighting.cpp index ca8fa546d..84cf1dc13 100644 --- a/src/rendering/hwrenderer/scene/hw_lighting.cpp +++ b/src/rendering/hwrenderer/scene/hw_lighting.cpp @@ -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. diff --git a/src/rendering/hwrenderer/scene/hw_renderhacks.cpp b/src/rendering/hwrenderer/scene/hw_renderhacks.cpp index d0775d109..6cb221752 100644 --- a/src/rendering/hwrenderer/scene/hw_renderhacks.cpp +++ b/src/rendering/hwrenderer/scene/hw_renderhacks.cpp @@ -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 &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++; } } diff --git a/src/rendering/hwrenderer/scene/hw_sky.cpp b/src/rendering/hwrenderer/scene/hw_sky.cpp index 0af7309b2..830bb7b9c 100644 --- a/src/rendering/hwrenderer/scene/hw_sky.cpp +++ b/src/rendering/hwrenderer/scene/hw_sky.cpp @@ -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 ? §or->ceilingplane : §or->floorplane; + } ptype = PORTALTYPE_PLANEMIRROR; - planemirror = plane == sector_t::ceiling ? §or->ceilingplane : §or->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; diff --git a/src/rendering/hwrenderer/scene/hw_walldispatcher.h b/src/rendering/hwrenderer/scene/hw_walldispatcher.h new file mode 100644 index 000000000..4a2855391 --- /dev/null +++ b/src/rendering/hwrenderer/scene/hw_walldispatcher.h @@ -0,0 +1,80 @@ +#pragma once + +struct HWMissing +{ + side_t* side; + subsector_t* sub; + double plane; +}; + +struct HWMeshHelper +{ + TArray list; + TArray translucent; + TArray portals; + TArray lower; + TArray 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); + } + +}; diff --git a/src/rendering/hwrenderer/scene/hw_walls.cpp b/src/rendering/hwrenderer/scene/hw_walls.cpp index b049ee172..c92481102 100644 --- a/src/rendering/hwrenderer/scene/hw_walls.cpp +++ b/src/rendering/hwrenderer/scene/hw_walls.cpp @@ -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<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 ((maplightbottomleftztop[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;