diff --git a/src/hwrenderer/data/hw_sections.cpp b/src/hwrenderer/data/hw_sections.cpp index 3ef6502c6..c37b37395 100644 --- a/src/hwrenderer/data/hw_sections.cpp +++ b/src/hwrenderer/data/hw_sections.cpp @@ -632,10 +632,9 @@ public: void ConstructOutput(FSectionContainer &output) { output.allSections.Resize(groups.Size()); - output.allIndices.Resize(level.subsectors.Size() + level.sides.Size() + 2*level.sectors.Size()); - output.sectionForSidedefPtr = &output.allIndices[0]; - output.firstSectionForSectorPtr = &output.allIndices[level.sides.Size()]; - output.numberOfSectionForSectorPtr = &output.allIndices[level.sides.Size() + level.sectors.Size()]; + output.allIndices.Resize(2*level.sectors.Size()); + output.firstSectionForSectorPtr = &output.allIndices[0]; + output.numberOfSectionForSectorPtr = &output.allIndices[level.sectors.Size()]; memset(output.firstSectionForSectorPtr, -1, sizeof(int) * level.sectors.Size()); memset(output.numberOfSectionForSectorPtr, 0, sizeof(int) * level.sectors.Size()); @@ -713,7 +712,6 @@ public: while (it.NextPair(pair)) { output.allSides[numsides++] = &level.sides[pair->Key]; - output.sectionForSidedefPtr[pair->Key] = curgroup; } for (auto ssi : group.subsectors) { diff --git a/src/hwrenderer/data/hw_sections.h b/src/hwrenderer/data/hw_sections.h index 668c2ba39..96ab3c250 100644 --- a/src/hwrenderer/data/hw_sections.h +++ b/src/hwrenderer/data/hw_sections.h @@ -102,26 +102,9 @@ public: TArray allSubsectors; TArray allIndices; - int *sectionForSidedefPtr; // also stored inside allIndices; int *firstSectionForSectorPtr; // ditto. int *numberOfSectionForSectorPtr; // ditto. - FSection *SectionForSidedef(side_t *side) - { - return SectionForSidedef(side->Index()); - } - FSection *SectionForSidedef(int sindex) - { - return sindex < 0 ? nullptr : &allSections[sectionForSidedefPtr[sindex]]; - } - int SectionNumForSidedef(side_t *side) - { - return SectionNumForSidedef(side->Index()); - } - int SectionNumForSidedef(int sindex) - { - return sindex < 0 ? -1 : sectionForSidedefPtr[sindex]; - } TArrayView SectionsForSector(sector_t *sec) { return SectionsForSector(sec->Index()); diff --git a/src/hwrenderer/scene/hw_drawinfo.cpp b/src/hwrenderer/scene/hw_drawinfo.cpp index 0dd67634e..2dc9aef04 100644 --- a/src/hwrenderer/scene/hw_drawinfo.cpp +++ b/src/hwrenderer/scene/hw_drawinfo.cpp @@ -441,8 +441,8 @@ void HWDrawInfo::CreateScene() HandleMissingTextures(in_area); // Missing upper/lower textures HandleHackedSubsectors(); // open sector hacks for deep water - ProcessSectorStacks(in_area); // merge visplanes of sector stacks PrepareUnhandledMissingTextures(); + DispatchRenderHacks(); screen->mLights->Unmap(); screen->mVertexData->Unmap(); diff --git a/src/hwrenderer/scene/hw_drawinfo.h b/src/hwrenderer/scene/hw_drawinfo.h index e40c361ef..58951473b 100644 --- a/src/hwrenderer/scene/hw_drawinfo.h +++ b/src/hwrenderer/scene/hw_drawinfo.h @@ -264,6 +264,7 @@ public: void CollectSectorStacksCeiling(subsector_t * sub, sector_t * anchor, area_t in_area); void CollectSectorStacksFloor(subsector_t * sub, sector_t * anchor, area_t in_area); + void DispatchRenderHacks(); void AddUpperMissingTexture(side_t * side, subsector_t *sub, float backheight); void AddLowerMissingTexture(side_t * side, subsector_t *sub, float backheight); void HandleMissingTextures(area_t in_area); diff --git a/src/hwrenderer/scene/hw_drawlistadd.cpp b/src/hwrenderer/scene/hw_drawlistadd.cpp index a1657b396..0ab682bd7 100644 --- a/src/hwrenderer/scene/hw_drawlistadd.cpp +++ b/src/hwrenderer/scene/hw_drawlistadd.cpp @@ -116,7 +116,7 @@ void HWDrawInfo::AddFlat(GLFlat *flat, bool fog) list = GLDL_PLAINFLATS; } } - else + else //if (flat->hacktype != SSRF_FLOODHACK) // The flood hack may later need different treatment but with the current setup can go into the existing render list. { bool masked = flat->gltexture->isMasked() && ((flat->renderflags&SSRF_RENDER3DPLANES) || flat->stack); list = masked ? GLDL_MASKEDFLATS : GLDL_PLAINFLATS; diff --git a/src/hwrenderer/scene/hw_drawstructs.h b/src/hwrenderer/scene/hw_drawstructs.h index dd63e5bd2..35a6d340e 100644 --- a/src/hwrenderer/scene/hw_drawstructs.h +++ b/src/hwrenderer/scene/hw_drawstructs.h @@ -320,7 +320,7 @@ public: void PutFlat(HWDrawInfo *di, bool fog = false); void Process(HWDrawInfo *di, sector_t * model, int whichplane, bool notexture); void SetFrom3DFloor(F3DFloor *rover, bool top, bool underside); - void ProcessSector(HWDrawInfo *di, sector_t * frontsector, int which = SSRF_RENDERALL); + void ProcessSector(HWDrawInfo *di, sector_t * frontsector, int which = 7 /*SSRF_RENDERALL*/); // cannot use constant due to circular dependencies. void DrawSubsectors(HWDrawInfo *di, FRenderState &state); void DrawFlat(HWDrawInfo *di, FRenderState &state, bool translucent); diff --git a/src/hwrenderer/scene/hw_flats.cpp b/src/hwrenderer/scene/hw_flats.cpp index 4872c6e43..553b934bd 100644 --- a/src/hwrenderer/scene/hw_flats.cpp +++ b/src/hwrenderer/scene/hw_flats.cpp @@ -203,7 +203,7 @@ void GLFlat::DrawSubsectors(HWDrawInfo *di, FRenderState &state) void GLFlat::DrawOtherPlanes(HWDrawInfo *di, FRenderState &state) { - state.SetMaterial(gltexture, CLAMP_XY, 0, -1); + state.SetMaterial(gltexture, CLAMP_NONE, 0, -1); // Draw the subsectors assigned to it due to missing textures auto pNode = (renderflags&SSRF_RENDERFLOOR) ? @@ -231,68 +231,58 @@ void GLFlat::DrawOtherPlanes(HWDrawInfo *di, FRenderState &state) 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) - { + // Flood gaps with the back side's ceiling/floor texture + // This requires a stencil because the projected plane interferes with + // the depth buffer - auto pNode = (renderflags&SSRF_RENDERFLOOR) ? - di->floodFloorSegs.CheckKey(sector->sectornum) : di->floodCeilingSegs.CheckKey(sector->sectornum); - if (!pNode) return; - - auto fnode = *pNode; + state.SetMaterial(gltexture, CLAMP_NONE, 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 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; + } - 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; - } - - } } @@ -318,7 +308,15 @@ void GLFlat::DrawFlat(HWDrawInfo *di, FRenderState &state, bool translucent) state.SetFog(lightlevel, rel, di->isFullbrightScene(), &Colormap, false); state.SetObjectColor(FlatColor | 0xff000000); - if (!translucent) + if (hacktype & SSRF_PLANEHACK) + { + DrawOtherPlanes(di, state); + } + else if (hacktype & SSRF_FLOODHACK) + { + DrawFloodPlanes(di, state); + } + else if (!translucent) { if (sector->special != GLSector_Skybox) { @@ -335,14 +333,6 @@ 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 @@ -385,7 +375,7 @@ inline void GLFlat::PutFlat(HWDrawInfo *di, bool fog) } else if (!screen->BuffersArePersistent()) { - if (level.HasDynamicLights && gltexture != nullptr) + if (level.HasDynamicLights && gltexture != nullptr && !(hacktype & (SSRF_PLANEHACK|SSRF_FLOODHACK)) ) { SetupLights(di, section->lighthead, lightdata, sector->PortalGroup); } @@ -434,7 +424,7 @@ void GLFlat::Process(HWDrawInfo *di, sector_t * model, int whichplane, bool fog) } // For hacks this won't go into a render list. - if (hacktype == 0) PutFlat(di, fog); + PutFlat(di, fog); rendered_flats++; } @@ -495,7 +485,8 @@ void GLFlat::ProcessSector(HWDrawInfo *di, sector_t * frontsector, int which) dynlightindex = -1; hacktype = (which & (SSRF_PLANEHACK|SSRF_FLOODHACK)); - uint8_t &srf = di->section_renderflags[level.sections.SectionIndex(section)]; + uint8_t sink; + uint8_t &srf = hacktype? sink : di->section_renderflags[level.sections.SectionIndex(section)]; const auto &vp = di->Viewpoint; // diff --git a/src/hwrenderer/scene/hw_renderhacks.cpp b/src/hwrenderer/scene/hw_renderhacks.cpp index 6701b0796..82610c792 100644 --- a/src/hwrenderer/scene/hw_renderhacks.cpp +++ b/src/hwrenderer/scene/hw_renderhacks.cpp @@ -41,7 +41,55 @@ sector_t * hw_FakeFlat(sector_t * sec, sector_t * dest, area_t in_area, bool back); +//========================================================================== +// +// Create render list entries from the data generated below +// +//========================================================================== + +void HWDrawInfo::DispatchRenderHacks() +{ + TMap::Pair *pair; + TMap::Pair *fpair; + TMap::Iterator ofi(otherFloorPlanes); + GLFlat glflat; + sector_t fakesec; + glflat.section = nullptr; + while (ofi.NextPair(pair)) + { + auto sec = hw_FakeFlat(&level.sectors[pair->Key], &fakesec, in_area, false); + glflat.ProcessSector(this, sec, SSRF_RENDERFLOOR | SSRF_PLANEHACK); + } + + TMap::Iterator oci(otherCeilingPlanes); + while (ofi.NextPair(pair)) + { + auto sec = hw_FakeFlat(&level.sectors[pair->Key], &fakesec, in_area, false); + glflat.ProcessSector(this, sec, SSRF_RENDERCEILING | SSRF_PLANEHACK); + } + + TMap::Iterator ffi(floodFloorSegs); + while (ffi.NextPair(fpair)) + { + auto sec = hw_FakeFlat(&level.sectors[fpair->Key], &fakesec, in_area, false); + glflat.ProcessSector(this, sec, SSRF_RENDERFLOOR | SSRF_FLOODHACK); + } + + TMap::Iterator fci(floodCeilingSegs); + while (fci.NextPair(fpair)) + { + auto sec = hw_FakeFlat(&level.sectors[fpair->Key], &fakesec, in_area, false); + glflat.ProcessSector(this, sec, SSRF_RENDERCEILING | SSRF_FLOODHACK); + } +} + + +//========================================================================== +// // 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)); @@ -506,9 +554,6 @@ void HWDrawInfo::HandleMissingTextures(area_t in_area) if (DoOneSectorUpper(MissingUpperTextures[i].sub, MissingUpperTextures[i].Planez, in_area)) { sector_t * sec = MissingUpperTextures[i].seg->backsector; - // The mere fact that this seg has been added to the list means that the back sector - // will be rendered so we can safely assume that it is already in the render list - for (unsigned int j = 0; j < HandledSubsectors.Size(); j++) { gl_subsectorrendernode * node = NewSubsectorRenderNode(); @@ -550,9 +595,6 @@ void HWDrawInfo::HandleMissingTextures(area_t in_area) backsub->validcount = validcount; if (DoFakeCeilingBridge(backsub, planez, in_area)) { - // The mere fact that this seg has been added to the list means that the back sector - // will be rendered so we can safely assume that it is already in the render list - for (unsigned int j = 0; j < HandledSubsectors.Size(); j++) { gl_subsectorrendernode * node = NewSubsectorRenderNode(); @@ -578,8 +620,6 @@ void HWDrawInfo::HandleMissingTextures(area_t in_area) if (DoOneSectorLower(MissingLowerTextures[i].sub, MissingLowerTextures[i].Planez, in_area)) { sector_t * sec = MissingLowerTextures[i].seg->backsector; - // The mere fact that this seg has been added to the list means that the back sector - // will be rendered so we can safely assume that it is already in the render list for (unsigned int j = 0; j < HandledSubsectors.Size(); j++) { @@ -621,9 +661,6 @@ void HWDrawInfo::HandleMissingTextures(area_t in_area) backsub->validcount = validcount; if (DoFakeBridge(backsub, planez, in_area)) { - // The mere fact that this seg has been added to the list means that the back sector - // will be rendered so we can safely assume that it is already in the render list - for (unsigned int j = 0; j < HandledSubsectors.Size(); j++) { gl_subsectorrendernode * node = NewSubsectorRenderNode(); @@ -840,8 +877,6 @@ void HWDrawInfo::PrepareUnhandledMissingTextures() if (seg->linedef->validcount == validcount) continue; // already done seg->linedef->validcount = validcount; - int section = level.sections.SectionNumForSidedef(seg->sidedef); - if (!(section_renderflags[section] & SSRF_RENDERFLOOR)) continue; if (seg->frontsector->GetPlaneTexZ(sector_t::floor) > Viewpoint.Pos.Z) continue; // out of sight if (seg->backsector->transdoor) continue; if (seg->backsector->GetTexture(sector_t::floor) == skyflatnum) continue; diff --git a/src/tarray.h b/src/tarray.h index 4a0d1570f..7e8c53f06 100644 --- a/src/tarray.h +++ b/src/tarray.h @@ -536,8 +536,9 @@ public: } }; -// This is not a real dynamic array but just a wrapper around a pointer reference. -// Used for wrapping some memory allocated elsewhere into a VM compatible data structure. +// This is only used for exposing the sector's Lines array to ZScript. +// This also must be trivial so that sector_t remains trivial. +// For other uses TArrayView should be preferred. template class TStaticPointedArray