- made the common render hacks functional again as separate render items.

This commit is contained in:
Christoph Oelckers 2018-11-06 20:31:44 +01:00
parent a6e77ae094
commit ddc75f7ba5
9 changed files with 122 additions and 113 deletions

View file

@ -632,10 +632,9 @@ public:
void ConstructOutput(FSectionContainer &output) void ConstructOutput(FSectionContainer &output)
{ {
output.allSections.Resize(groups.Size()); output.allSections.Resize(groups.Size());
output.allIndices.Resize(level.subsectors.Size() + level.sides.Size() + 2*level.sectors.Size()); output.allIndices.Resize(2*level.sectors.Size());
output.sectionForSidedefPtr = &output.allIndices[0]; output.firstSectionForSectorPtr = &output.allIndices[0];
output.firstSectionForSectorPtr = &output.allIndices[level.sides.Size()]; output.numberOfSectionForSectorPtr = &output.allIndices[level.sectors.Size()];
output.numberOfSectionForSectorPtr = &output.allIndices[level.sides.Size() + level.sectors.Size()];
memset(output.firstSectionForSectorPtr, -1, sizeof(int) * level.sectors.Size()); memset(output.firstSectionForSectorPtr, -1, sizeof(int) * level.sectors.Size());
memset(output.numberOfSectionForSectorPtr, 0, sizeof(int) * level.sectors.Size()); memset(output.numberOfSectionForSectorPtr, 0, sizeof(int) * level.sectors.Size());
@ -713,7 +712,6 @@ public:
while (it.NextPair(pair)) while (it.NextPair(pair))
{ {
output.allSides[numsides++] = &level.sides[pair->Key]; output.allSides[numsides++] = &level.sides[pair->Key];
output.sectionForSidedefPtr[pair->Key] = curgroup;
} }
for (auto ssi : group.subsectors) for (auto ssi : group.subsectors)
{ {

View file

@ -102,26 +102,9 @@ public:
TArray<subsector_t *> allSubsectors; TArray<subsector_t *> allSubsectors;
TArray<int> allIndices; TArray<int> allIndices;
int *sectionForSidedefPtr; // also stored inside allIndices;
int *firstSectionForSectorPtr; // ditto. int *firstSectionForSectorPtr; // ditto.
int *numberOfSectionForSectorPtr; // 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<FSection> SectionsForSector(sector_t *sec) TArrayView<FSection> SectionsForSector(sector_t *sec)
{ {
return SectionsForSector(sec->Index()); return SectionsForSector(sec->Index());

View file

@ -441,8 +441,8 @@ void HWDrawInfo::CreateScene()
HandleMissingTextures(in_area); // Missing upper/lower textures HandleMissingTextures(in_area); // Missing upper/lower textures
HandleHackedSubsectors(); // open sector hacks for deep water HandleHackedSubsectors(); // open sector hacks for deep water
ProcessSectorStacks(in_area); // merge visplanes of sector stacks
PrepareUnhandledMissingTextures(); PrepareUnhandledMissingTextures();
DispatchRenderHacks();
screen->mLights->Unmap(); screen->mLights->Unmap();
screen->mVertexData->Unmap(); screen->mVertexData->Unmap();

View file

@ -264,6 +264,7 @@ public:
void CollectSectorStacksCeiling(subsector_t * sub, sector_t * anchor, area_t in_area); 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 CollectSectorStacksFloor(subsector_t * sub, sector_t * anchor, area_t in_area);
void DispatchRenderHacks();
void AddUpperMissingTexture(side_t * side, subsector_t *sub, float backheight); void AddUpperMissingTexture(side_t * side, subsector_t *sub, float backheight);
void AddLowerMissingTexture(side_t * side, subsector_t *sub, float backheight); void AddLowerMissingTexture(side_t * side, subsector_t *sub, float backheight);
void HandleMissingTextures(area_t in_area); void HandleMissingTextures(area_t in_area);

View file

@ -116,7 +116,7 @@ void HWDrawInfo::AddFlat(GLFlat *flat, bool fog)
list = GLDL_PLAINFLATS; 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); bool masked = flat->gltexture->isMasked() && ((flat->renderflags&SSRF_RENDER3DPLANES) || flat->stack);
list = masked ? GLDL_MASKEDFLATS : GLDL_PLAINFLATS; list = masked ? GLDL_MASKEDFLATS : GLDL_PLAINFLATS;

View file

@ -320,7 +320,7 @@ public:
void PutFlat(HWDrawInfo *di, bool fog = false); void PutFlat(HWDrawInfo *di, bool fog = false);
void Process(HWDrawInfo *di, sector_t * model, int whichplane, bool notexture); void Process(HWDrawInfo *di, sector_t * model, int whichplane, bool notexture);
void SetFrom3DFloor(F3DFloor *rover, bool top, bool underside); 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 DrawSubsectors(HWDrawInfo *di, FRenderState &state);
void DrawFlat(HWDrawInfo *di, FRenderState &state, bool translucent); void DrawFlat(HWDrawInfo *di, FRenderState &state, bool translucent);

View file

@ -203,7 +203,7 @@ void GLFlat::DrawSubsectors(HWDrawInfo *di, FRenderState &state)
void GLFlat::DrawOtherPlanes(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 // Draw the subsectors assigned to it due to missing textures
auto pNode = (renderflags&SSRF_RENDERFLOOR) ? auto pNode = (renderflags&SSRF_RENDERFLOOR) ?
@ -231,68 +231,58 @@ void GLFlat::DrawOtherPlanes(HWDrawInfo *di, FRenderState &state)
void GLFlat::DrawFloodPlanes(HWDrawInfo *di, FRenderState &state) void GLFlat::DrawFloodPlanes(HWDrawInfo *di, FRenderState &state)
{ {
// Flood gaps with the back side's ceiling/floor texture // Flood gaps with the back side's ceiling/floor texture
// This requires a stencil because the projected plane interferes with // This requires a stencil because the projected plane interferes with
// the depth buffer // the depth buffer
state.SetMaterial(gltexture, CLAMP_XY, 0, -1); state.SetMaterial(gltexture, CLAMP_NONE, 0, -1);
// Draw the subsectors assigned to it due to missing textures // Draw the subsectors assigned to it due to missing textures
auto pNode = (renderflags&SSRF_RENDERFLOOR) ? auto pNode = (renderflags&SSRF_RENDERFLOOR) ?
di->floodFloorSegs.CheckKey(sector->sectornum) : di->floodCeilingSegs.CheckKey(sector->sectornum); di->floodFloorSegs.CheckKey(sector->sectornum) : di->floodCeilingSegs.CheckKey(sector->sectornum);
if (!pNode) return;
if (!pNode) return; auto fnode = *pNode;
auto node = *pNode;
while (node) state.SetLightIndex(-1);
{ while (fnode)
{
flatvertices += 12;
flatprimitives += 3;
auto pNode = (renderflags&SSRF_RENDERFLOOR) ? // Push bleeding floor/ceiling textures back a little in the z-buffer
di->floodFloorSegs.CheckKey(sector->sectornum) : di->floodCeilingSegs.CheckKey(sector->sectornum); // so they don't interfere with overlapping mid textures.
if (!pNode) return; state.SetDepthBias(1, 128);
auto fnode = *pNode; // Create stencil
state.SetEffect(EFF_STENCIL);
state.EnableTexture(false);
state.SetStencil(0, SOP_Increment, SF_ColorMaskOff);
state.Draw(DT_TriangleFan, fnode->vertexindex, 4);
state.SetLightIndex(-1); // Draw projected plane into stencil
while (fnode) state.EnableTexture(true);
{ state.SetEffect(EFF_NONE);
flatvertices += 12; state.SetStencil(1, SOP_Keep, SF_DepthMaskOff);
flatprimitives += 3; state.EnableDepthTest(false);
state.Draw(DT_TriangleFan, fnode->vertexindex + 4, 4);
// Push bleeding floor/ceiling textures back a little in the z-buffer // clear stencil
// so they don't interfere with overlapping mid textures. state.SetEffect(EFF_STENCIL);
state.SetDepthBias(1, 128); state.EnableTexture(false);
state.SetStencil(1, SOP_Decrement, SF_ColorMaskOff | SF_DepthMaskOff);
state.Draw(DT_TriangleFan, fnode->vertexindex, 4);
// Create stencil // restore old stencil op.
state.SetEffect(EFF_STENCIL); state.EnableTexture(true);
state.EnableTexture(false); state.EnableDepthTest(true);
state.SetStencil(0, SOP_Increment, SF_ColorMaskOff); state.SetEffect(EFF_NONE);
state.Draw(DT_TriangleFan,fnode->vertexindex, 4); state.SetDepthBias(0, 0);
state.SetStencil(0, SOP_Keep, SF_AllOn);
// Draw projected plane into stencil fnode = fnode->next;
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.SetFog(lightlevel, rel, di->isFullbrightScene(), &Colormap, false);
state.SetObjectColor(FlatColor | 0xff000000); 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) if (sector->special != GLSector_Skybox)
{ {
@ -335,14 +333,6 @@ void GLFlat::DrawFlat(HWDrawInfo *di, FRenderState &state, bool translucent)
flatvertices += 4; flatvertices += 4;
flatprimitives++; flatprimitives++;
} }
else if (hacktype & SSRF_PLANEHACK)
{
DrawOtherPlanes(di, state);
}
else if (hacktype & SSRF_FLOODHACK)
{
DrawFloodPlanes(di, state);
}
state.SetObjectColor(0xffffffff); state.SetObjectColor(0xffffffff);
} }
else else
@ -385,7 +375,7 @@ inline void GLFlat::PutFlat(HWDrawInfo *di, bool fog)
} }
else if (!screen->BuffersArePersistent()) 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); 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. // For hacks this won't go into a render list.
if (hacktype == 0) PutFlat(di, fog); PutFlat(di, fog);
rendered_flats++; rendered_flats++;
} }
@ -495,7 +485,8 @@ void GLFlat::ProcessSector(HWDrawInfo *di, sector_t * frontsector, int which)
dynlightindex = -1; dynlightindex = -1;
hacktype = (which & (SSRF_PLANEHACK|SSRF_FLOODHACK)); 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; const auto &vp = di->Viewpoint;
// //

View file

@ -41,7 +41,55 @@
sector_t * hw_FakeFlat(sector_t * sec, sector_t * dest, area_t in_area, bool back); 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<int, gl_subsectorrendernode*>::Pair *pair;
TMap<int, gl_floodrendernode*>::Pair *fpair;
TMap<int, gl_subsectorrendernode*>::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<int, gl_subsectorrendernode*>::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<int, gl_floodrendernode*>::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<int, gl_floodrendernode*>::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. // Get the nodes from the render data allocator so we don't have to keep track of them ourselves.
//
//==========================================================================
static gl_subsectorrendernode *NewSubsectorRenderNode() static gl_subsectorrendernode *NewSubsectorRenderNode()
{ {
return (gl_subsectorrendernode*)RenderDataAllocator.Alloc(sizeof(gl_subsectorrendernode)); 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)) if (DoOneSectorUpper(MissingUpperTextures[i].sub, MissingUpperTextures[i].Planez, in_area))
{ {
sector_t * sec = MissingUpperTextures[i].seg->backsector; 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++) for (unsigned int j = 0; j < HandledSubsectors.Size(); j++)
{ {
gl_subsectorrendernode * node = NewSubsectorRenderNode(); gl_subsectorrendernode * node = NewSubsectorRenderNode();
@ -550,9 +595,6 @@ void HWDrawInfo::HandleMissingTextures(area_t in_area)
backsub->validcount = validcount; backsub->validcount = validcount;
if (DoFakeCeilingBridge(backsub, planez, in_area)) 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++) for (unsigned int j = 0; j < HandledSubsectors.Size(); j++)
{ {
gl_subsectorrendernode * node = NewSubsectorRenderNode(); 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)) if (DoOneSectorLower(MissingLowerTextures[i].sub, MissingLowerTextures[i].Planez, in_area))
{ {
sector_t * sec = MissingLowerTextures[i].seg->backsector; 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++) for (unsigned int j = 0; j < HandledSubsectors.Size(); j++)
{ {
@ -621,9 +661,6 @@ void HWDrawInfo::HandleMissingTextures(area_t in_area)
backsub->validcount = validcount; backsub->validcount = validcount;
if (DoFakeBridge(backsub, planez, in_area)) 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++) for (unsigned int j = 0; j < HandledSubsectors.Size(); j++)
{ {
gl_subsectorrendernode * node = NewSubsectorRenderNode(); gl_subsectorrendernode * node = NewSubsectorRenderNode();
@ -840,8 +877,6 @@ void HWDrawInfo::PrepareUnhandledMissingTextures()
if (seg->linedef->validcount == validcount) continue; // already done if (seg->linedef->validcount == validcount) continue; // already done
seg->linedef->validcount = validcount; 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->frontsector->GetPlaneTexZ(sector_t::floor) > Viewpoint.Pos.Z) continue; // out of sight
if (seg->backsector->transdoor) continue; if (seg->backsector->transdoor) continue;
if (seg->backsector->GetTexture(sector_t::floor) == skyflatnum) continue; if (seg->backsector->GetTexture(sector_t::floor) == skyflatnum) continue;

View file

@ -536,8 +536,9 @@ public:
} }
}; };
// This is not a real dynamic array but just a wrapper around a pointer reference. // This is only used for exposing the sector's Lines array to ZScript.
// Used for wrapping some memory allocated elsewhere into a VM compatible data structure. // This also must be trivial so that sector_t remains trivial.
// For other uses TArrayView should be preferred.
template <class T> template <class T>
class TStaticPointedArray class TStaticPointedArray