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); }