From a6e77ae0944d47d71d00952b635c90eeb80bdd5c Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 6 Nov 2018 18:20:59 +0100 Subject: [PATCH] Refactored the render hack storage so that it can be decoupled from the regular GLFlat render items. Having these in there makes it impossible to change render techniques so these are better done as separate items. --- src/hwrenderer/scene/hw_drawinfo.cpp | 27 +--- src/hwrenderer/scene/hw_drawinfo.h | 36 +---- src/hwrenderer/scene/hw_drawstructs.h | 6 +- src/hwrenderer/scene/hw_flats.cpp | 202 +++++++++++++++--------- src/hwrenderer/scene/hw_renderhacks.cpp | 85 +++++----- 5 files changed, 174 insertions(+), 182 deletions(-) diff --git a/src/hwrenderer/scene/hw_drawinfo.cpp b/src/hwrenderer/scene/hw_drawinfo.cpp index 128b1d8fa..0dd67634e 100644 --- a/src/hwrenderer/scene/hw_drawinfo.cpp +++ b/src/hwrenderer/scene/hw_drawinfo.cpp @@ -56,18 +56,6 @@ sector_t * hw_FakeFlat(sector_t * sec, sector_t * dest, area_t in_area, bool bac // //========================================================================== -template -inline void DeleteLinkedList(T *node) -{ - while (node) - { - auto n = node; - node = node->next; - delete n; - } -} - - class FDrawInfoList { public: @@ -188,17 +176,10 @@ HWDrawInfo *HWDrawInfo::EndDrawInfo() void HWDrawInfo::ClearBuffers() { - for (auto node : otherfloorplanes) DeleteLinkedList(node); - otherfloorplanes.Clear(); - - for (auto node : otherceilingplanes) DeleteLinkedList(node); - otherceilingplanes.Clear(); - - for (auto node : floodfloorsegs) DeleteLinkedList(node); - floodfloorsegs.Clear(); - - for (auto node : floodceilingsegs) DeleteLinkedList(node); - floodceilingsegs.Clear(); + otherFloorPlanes.Clear(); + otherCeilingPlanes.Clear(); + floodFloorSegs.Clear(); + floodCeilingSegs.Clear(); // clear all the lists that might not have been cleared already MissingUpperTextures.Clear(); diff --git a/src/hwrenderer/scene/hw_drawinfo.h b/src/hwrenderer/scene/hw_drawinfo.h index 537c2a202..e40c361ef 100644 --- a/src/hwrenderer/scene/hw_drawinfo.h +++ b/src/hwrenderer/scene/hw_drawinfo.h @@ -68,6 +68,8 @@ enum SectorRenderFlags SSRF_RENDERALL = 7, SSRF_PROCESSED = 8, SSRF_SEEN = 16, + SSRF_PLANEHACK = 32, + SSRF_FLOODHACK = 64 }; enum EPortalClip @@ -160,10 +162,10 @@ struct HWDrawInfo TArray SubsectorHacks; - TArray otherfloorplanes; - TArray otherceilingplanes; - TArray floodfloorsegs; - TArray floodceilingsegs; + TMap otherFloorPlanes; + TMap otherCeilingPlanes; + TMap floodFloorSegs; + TMap floodCeilingSegs; TArray CeilingStacks; TArray FloorStacks; @@ -212,32 +214,6 @@ private: void DrawPSprite(HUDSprite *huds, FRenderState &state); public: - gl_subsectorrendernode * GetOtherFloorPlanes(unsigned int sector) - { - if (sectorvertexindex, section->vertexcount); flatvertices += section->vertexcount; flatprimitives++; - - -#if 0 - //Temporarily disabled until the render hack code can be redone and refactored into its own draw elements - if (!(renderflags&SSRF_RENDER3DPLANES)) - { - // Draw the subsectors assigned to it due to missing textures - gl_subsectorrendernode * node = (renderflags&SSRF_RENDERFLOOR) ? - di->GetOtherFloorPlanes(sector->sectornum) : - di->GetOtherCeilingPlanes(sector->sectornum); - - while (node) - { - state.SetLightIndex(node->lightindex); - auto num = node->sub->numlines; - flatvertices += num; - flatprimitives++; - state.Draw(DT_TriangleFan,node->vertexindex, num); - node = node->next; - } - // Flood gaps with the back side's ceiling/floor texture - // This requires a stencil because the projected plane interferes with - // the depth buffer - gl_floodrendernode * fnode = (renderflags&SSRF_RENDERFLOOR) ? - di->GetFloodFloorSegs(sector->sectornum) : - di->GetFloodCeilingSegs(sector->sectornum); - - state.SetLightIndex(dynlightindex); - while (fnode) - { - flatvertices += 12; - flatprimitives += 3; - - // Push bleeding floor/ceiling textures back a little in the z-buffer - // so they don't interfere with overlapping mid textures. - state.SetDepthBias(1, 128); - - // Create stencil - state.SetEffect(EFF_STENCIL); - state.EnableTexture(false); - state.SetStencil(0, SOP_Increment, SF_ColorMaskOff); - state.Draw(DT_TriangleFan,fnode->vertexindex, 4); - - // Draw projected plane into stencil - state.EnableTexture(true); - state.SetEffect(EFF_NONE); - state.SetStencil(1, SOP_Keep, SF_DepthMaskOff); - state.EnableDepthTest(false); - state.Draw(DT_TriangleFan,fnode->vertexindex + 4, 4); - - // clear stencil - state.SetEffect(EFF_STENCIL); - state.EnableTexture(false); - state.SetStencil(1, SOP_Decrement, SF_ColorMaskOff | SF_DepthMaskOff); - state.Draw(DT_TriangleFan,fnode->vertexindex, 4); - - // restore old stencil op. - state.EnableTexture(true); - state.EnableDepthTest(true); - state.SetEffect(EFF_NONE); - state.SetDepthBias(0, 0); - state.SetStencil(0, SOP_Keep, SF_AllOn); - - fnode = fnode->next; - } - - } -#endif } + +//========================================================================== +// +// Drawer for render hacks +// +//========================================================================== + +void GLFlat::DrawOtherPlanes(HWDrawInfo *di, FRenderState &state) +{ + state.SetMaterial(gltexture, CLAMP_XY, 0, -1); + + // Draw the subsectors assigned to it due to missing textures + auto pNode = (renderflags&SSRF_RENDERFLOOR) ? + di->otherFloorPlanes.CheckKey(sector->sectornum) : di->otherCeilingPlanes.CheckKey(sector->sectornum); + + if (!pNode) return; + auto node = *pNode; + + while (node) + { + state.SetLightIndex(node->lightindex); + auto num = node->sub->numlines; + flatvertices += num; + flatprimitives++; + state.Draw(DT_TriangleFan,node->vertexindex, num); + node = node->next; + } +} + +//========================================================================== +// +// Drawer for render hacks +// +//========================================================================== + +void GLFlat::DrawFloodPlanes(HWDrawInfo *di, FRenderState &state) +{ + // Flood gaps with the back side's ceiling/floor texture + // This requires a stencil because the projected plane interferes with + // the depth buffer + + state.SetMaterial(gltexture, CLAMP_XY, 0, -1); + + // Draw the subsectors assigned to it due to missing textures + auto pNode = (renderflags&SSRF_RENDERFLOOR) ? + di->floodFloorSegs.CheckKey(sector->sectornum) : di->floodCeilingSegs.CheckKey(sector->sectornum); + + if (!pNode) return; + auto node = *pNode; + + while (node) + { + + auto pNode = (renderflags&SSRF_RENDERFLOOR) ? + di->floodFloorSegs.CheckKey(sector->sectornum) : di->floodCeilingSegs.CheckKey(sector->sectornum); + if (!pNode) return; + + auto fnode = *pNode; + + state.SetLightIndex(-1); + while (fnode) + { + flatvertices += 12; + flatprimitives += 3; + + // Push bleeding floor/ceiling textures back a little in the z-buffer + // so they don't interfere with overlapping mid textures. + state.SetDepthBias(1, 128); + + // Create stencil + state.SetEffect(EFF_STENCIL); + state.EnableTexture(false); + state.SetStencil(0, SOP_Increment, SF_ColorMaskOff); + state.Draw(DT_TriangleFan,fnode->vertexindex, 4); + + // Draw projected plane into stencil + state.EnableTexture(true); + state.SetEffect(EFF_NONE); + state.SetStencil(1, SOP_Keep, SF_DepthMaskOff); + state.EnableDepthTest(false); + state.Draw(DT_TriangleFan,fnode->vertexindex + 4, 4); + + // clear stencil + state.SetEffect(EFF_STENCIL); + state.EnableTexture(false); + state.SetStencil(1, SOP_Decrement, SF_ColorMaskOff | SF_DepthMaskOff); + state.Draw(DT_TriangleFan,fnode->vertexindex, 4); + + // restore old stencil op. + state.EnableTexture(true); + state.EnableDepthTest(true); + state.SetEffect(EFF_NONE); + state.SetDepthBias(0, 0); + state.SetStencil(0, SOP_Keep, SF_AllOn); + + fnode = fnode->next; + } + + } +} + + //========================================================================== // // @@ -282,8 +316,7 @@ void GLFlat::DrawFlat(HWDrawInfo *di, FRenderState &state, bool translucent) state.SetColor(lightlevel, rel, di->isFullbrightScene(), Colormap, alpha); state.SetFog(lightlevel, rel, di->isFullbrightScene(), &Colormap, false); - if (!gltexture || !gltexture->tex->isFullbright()) - state.SetObjectColor(FlatColor | 0xff000000); + state.SetObjectColor(FlatColor | 0xff000000); if (!translucent) { @@ -294,7 +327,7 @@ void GLFlat::DrawFlat(HWDrawInfo *di, FRenderState &state, bool translucent) DrawSubsectors(di, state); state.EnableTextureMatrix(false); } - else + else if (!hacktype) { state.SetMaterial(gltexture, CLAMP_XY, 0, -1); state.SetLightIndex(dynlightindex); @@ -302,6 +335,14 @@ void GLFlat::DrawFlat(HWDrawInfo *di, FRenderState &state, bool translucent) flatvertices += 4; flatprimitives++; } + else if (hacktype & SSRF_PLANEHACK) + { + DrawOtherPlanes(di, state); + } + else if (hacktype & SSRF_FLOODHACK) + { + DrawFloodPlanes(di, state); + } state.SetObjectColor(0xffffffff); } else @@ -355,8 +396,6 @@ inline void GLFlat::PutFlat(HWDrawInfo *di, bool fog) //========================================================================== // // This draws one flat -// The passed sector does not indicate the area which is rendered. -// It is only used as source for the plane data. // The whichplane boolean indicates if the flat is a floor(false) or a ceiling(true) // //========================================================================== @@ -394,8 +433,8 @@ void GLFlat::Process(HWDrawInfo *di, sector_t * model, int whichplane, bool fog) iboindex = vert.second; } - - PutFlat(di, fog); + // For hacks this won't go into a render list. + if (hacktype == 0) PutFlat(di, fog); rendered_flats++; } @@ -438,7 +477,7 @@ void GLFlat::SetFrom3DFloor(F3DFloor *rover, bool top, bool underside) // //========================================================================== -void GLFlat::ProcessSector(HWDrawInfo *di, sector_t * frontsector) +void GLFlat::ProcessSector(HWDrawInfo *di, sector_t * frontsector, int which) { lightlist_t * light; FSectorPortal *port; @@ -454,6 +493,7 @@ void GLFlat::ProcessSector(HWDrawInfo *di, sector_t * frontsector) sector = &level.sectors[frontsector->sectornum]; extsector_t::xfloor &x = sector->e->XFloor; dynlightindex = -1; + hacktype = (which & (SSRF_PLANEHACK|SSRF_FLOODHACK)); uint8_t &srf = di->section_renderflags[level.sections.SectionIndex(section)]; const auto &vp = di->Viewpoint; @@ -465,7 +505,7 @@ void GLFlat::ProcessSector(HWDrawInfo *di, sector_t * frontsector) // // // - if (frontsector->floorplane.ZatPoint(vp.Pos) <= vp.Pos.Z) + if ((which & SSRF_RENDERFLOOR) && frontsector->floorplane.ZatPoint(vp.Pos) <= vp.Pos.Z) { // process the original floor first. @@ -477,10 +517,12 @@ void GLFlat::ProcessSector(HWDrawInfo *di, sector_t * frontsector) port = frontsector->ValidatePortal(sector_t::floor); if ((stack = (port != NULL))) { + /* to be redone in a less invasive manner if (port->mType == PORTS_STACKEDSECTORTHING) { di->AddFloorStack(sector); // stacked sector things require visplane merging. } + */ alpha = frontsector->GetAlpha(sector_t::floor); } else @@ -518,7 +560,7 @@ void GLFlat::ProcessSector(HWDrawInfo *di, sector_t * frontsector) // // // - if (frontsector->ceilingplane.ZatPoint(vp.Pos) >= vp.Pos.Z) + if ((which & SSRF_RENDERCEILING) && frontsector->ceilingplane.ZatPoint(vp.Pos) >= vp.Pos.Z) { // process the original ceiling first. @@ -530,10 +572,12 @@ void GLFlat::ProcessSector(HWDrawInfo *di, sector_t * frontsector) port = frontsector->ValidatePortal(sector_t::ceiling); if ((stack = (port != NULL))) { + /* as above for floors if (port->mType == PORTS_STACKEDSECTORTHING) { di->AddCeilingStack(sector); } + */ alpha = frontsector->GetAlpha(sector_t::ceiling); } else @@ -572,7 +616,7 @@ void GLFlat::ProcessSector(HWDrawInfo *di, sector_t * frontsector) // stack = false; - if (x.ffloors.Size()) + if ((which & SSRF_RENDER3DPLANES) && x.ffloors.Size()) { player_t * player = players[consoleplayer].camera->player; diff --git a/src/hwrenderer/scene/hw_renderhacks.cpp b/src/hwrenderer/scene/hw_renderhacks.cpp index 8f3325f2d..6701b0796 100644 --- a/src/hwrenderer/scene/hw_renderhacks.cpp +++ b/src/hwrenderer/scene/hw_renderhacks.cpp @@ -41,6 +41,17 @@ sector_t * hw_FakeFlat(sector_t * sec, sector_t * dest, area_t in_area, bool back); +// Get the nodes from the render data allocator so we don't have to keep track of them ourselves. +static gl_subsectorrendernode *NewSubsectorRenderNode() +{ + return (gl_subsectorrendernode*)RenderDataAllocator.Alloc(sizeof(gl_subsectorrendernode)); +} + +static gl_floodrendernode *NewFloodRenderNode() +{ + return (gl_floodrendernode*)RenderDataAllocator.Alloc(sizeof(gl_floodrendernode)); +} + //========================================================================== // // light setup for render hacks. @@ -110,35 +121,24 @@ int HWDrawInfo::CreateOtherPlaneVertices(subsector_t *sub, const secplane_t *pla void HWDrawInfo::AddOtherFloorPlane(int sector, gl_subsectorrendernode * node) { - int oldcnt = otherfloorplanes.Size(); - - if (oldcnt <= sector) - { - otherfloorplanes.Resize(sector + 1); - for (int i = oldcnt; i <= sector; i++) otherfloorplanes[i] = nullptr; - } - node->next = otherfloorplanes[sector]; + auto pNode = otherFloorPlanes.CheckKey(sector); + + node->next = pNode? *pNode : nullptr; node->lightindex = SetupLightsForOtherPlane(node->sub, lightdata, &level.sectors[sector].floorplane); node->vertexindex = CreateOtherPlaneVertices(node->sub, &level.sectors[sector].floorplane); - otherfloorplanes[sector] = node; + otherFloorPlanes[sector] = node; } void HWDrawInfo::AddOtherCeilingPlane(int sector, gl_subsectorrendernode * node) { - int oldcnt = otherceilingplanes.Size(); - - if (oldcnt <= sector) - { - otherceilingplanes.Resize(sector + 1); - for (int i = oldcnt; i <= sector; i++) otherceilingplanes[i] = nullptr; - } - node->next = otherceilingplanes[sector]; + auto pNode = otherCeilingPlanes.CheckKey(sector); + + node->next = pNode? *pNode : nullptr; node->lightindex = SetupLightsForOtherPlane(node->sub, lightdata, &level.sectors[sector].ceilingplane); node->vertexindex = CreateOtherPlaneVertices(node->sub, &level.sectors[sector].ceilingplane); - otherceilingplanes[sector] = node; + otherCeilingPlanes[sector] = node; } - //========================================================================== // // Collects all sectors that might need a fake ceiling @@ -511,7 +511,7 @@ void HWDrawInfo::HandleMissingTextures(area_t in_area) for (unsigned int j = 0; j < HandledSubsectors.Size(); j++) { - gl_subsectorrendernode * node = new gl_subsectorrendernode; + gl_subsectorrendernode * node = NewSubsectorRenderNode(); node->sub = HandledSubsectors[j]; AddOtherCeilingPlane(sec->sectornum, node); @@ -555,7 +555,7 @@ void HWDrawInfo::HandleMissingTextures(area_t in_area) for (unsigned int j = 0; j < HandledSubsectors.Size(); j++) { - gl_subsectorrendernode * node = new gl_subsectorrendernode; + gl_subsectorrendernode * node = NewSubsectorRenderNode(); node->sub = HandledSubsectors[j]; AddOtherCeilingPlane(fakesector->sectornum, node); } @@ -583,7 +583,7 @@ void HWDrawInfo::HandleMissingTextures(area_t in_area) for (unsigned int j = 0; j < HandledSubsectors.Size(); j++) { - gl_subsectorrendernode * node = new gl_subsectorrendernode; + gl_subsectorrendernode * node = NewSubsectorRenderNode(); node->sub = HandledSubsectors[j]; AddOtherFloorPlane(sec->sectornum, node); } @@ -626,7 +626,7 @@ void HWDrawInfo::HandleMissingTextures(area_t in_area) for (unsigned int j = 0; j < HandledSubsectors.Size(); j++) { - gl_subsectorrendernode * node = new gl_subsectorrendernode; + gl_subsectorrendernode * node = NewSubsectorRenderNode(); node->sub = HandledSubsectors[j]; AddOtherFloorPlane(fakesector->sectornum, node); } @@ -730,19 +730,13 @@ void HWDrawInfo::PrepareUpperGap(seg_t * seg) CreateFloodStencilPoly(&ws, vertices.first); CreateFloodPoly(&ws, vertices.first+4, ws.z2, fakebsector, true); - gl_floodrendernode *node = new gl_floodrendernode; - int oldcnt = floodfloorsegs.Size(); - auto sector = fakebsector->sectornum; - if (oldcnt <= sector) - { - floodfloorsegs.Resize(sector + 1); - for (int i = oldcnt; i <= sector; i++) floodfloorsegs[i] = nullptr; - } + gl_floodrendernode *node = NewFloodRenderNode(); + auto pNode = floodFloorSegs.CheckKey(fakebsector->sectornum); - node->next = floodfloorsegs[sector]; + node->next = pNode? *pNode : nullptr; node->seg = seg; node->vertexindex = vertices.second; - floodfloorsegs[sector] = node; + floodFloorSegs[fakebsector->sectornum] = node; } @@ -794,19 +788,14 @@ void HWDrawInfo::PrepareLowerGap(seg_t * seg) CreateFloodStencilPoly(&ws, vertices.first); CreateFloodPoly(&ws, vertices.first+4, ws.z1, fakebsector, false); - gl_floodrendernode *node = new gl_floodrendernode; - int oldcnt = floodceilingsegs.Size(); - auto sector = fakebsector->sectornum; - if (oldcnt <= sector) - { - floodceilingsegs.Resize(sector + 1); - for (int i = oldcnt; i <= sector; i++) floodceilingsegs[i] = nullptr; - } + gl_floodrendernode *node = NewFloodRenderNode(); + auto pNode = floodCeilingSegs.CheckKey(fakebsector->sectornum); + + node->next = pNode? *pNode : nullptr; - node->next = floodceilingsegs[sector]; node->seg = seg; node->vertexindex = vertices.second; - floodceilingsegs[sector] = node; + floodCeilingSegs[fakebsector->sectornum] = node; } //========================================================================== @@ -1122,8 +1111,7 @@ void HWDrawInfo::HandleHackedSubsectors() { for(unsigned int j=0;jsub = HandledSubsectors[j]; AddOtherFloorPlane(sub->render_sector->sectornum, node); } @@ -1145,8 +1133,7 @@ void HWDrawInfo::HandleHackedSubsectors() { for(unsigned int j=0;jsub = HandledSubsectors[j]; AddOtherCeilingPlane(sub->render_sector->sectornum, node); } @@ -1308,7 +1295,7 @@ void HWDrawInfo::ProcessSectorStacks(area_t in_area) if (sec->GetAlpha(sector_t::ceiling) != 0 && sec->GetTexture(sector_t::ceiling) != skyflatnum) { - gl_subsectorrendernode * node = new gl_subsectorrendernode; + gl_subsectorrendernode * node = NewSubsectorRenderNode(); node->sub = sub; AddOtherCeilingPlane(sec->sectornum, node); } @@ -1353,7 +1340,7 @@ void HWDrawInfo::ProcessSectorStacks(area_t in_area) if (sec->GetAlpha(sector_t::floor) != 0 && sec->GetTexture(sector_t::floor) != skyflatnum) { - gl_subsectorrendernode * node = new gl_subsectorrendernode; + gl_subsectorrendernode * node = NewSubsectorRenderNode(); node->sub = sub; AddOtherFloorPlane(sec->sectornum, node); }