- 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)
{
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)
{

View file

@ -102,26 +102,9 @@ public:
TArray<subsector_t *> allSubsectors;
TArray<int> 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<FSection> SectionsForSector(sector_t *sec)
{
return SectionsForSector(sec->Index());

View file

@ -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();

View file

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

View file

@ -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;

View file

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

View file

@ -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
// 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);
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);
// 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;
if (!pNode) return;
auto node = *pNode;
auto fnode = *pNode;
while (node)
{
state.SetLightIndex(-1);
while (fnode)
{
flatvertices += 12;
flatprimitives += 3;
auto pNode = (renderflags&SSRF_RENDERFLOOR) ?
di->floodFloorSegs.CheckKey(sector->sectornum) : di->floodCeilingSegs.CheckKey(sector->sectornum);
if (!pNode) return;
// 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);
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);
while (fnode)
{
flatvertices += 12;
flatprimitives += 3;
// 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);
// 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);
// 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);
// Create stencil
state.SetEffect(EFF_STENCIL);
state.EnableTexture(false);
state.SetStencil(0, SOP_Increment, SF_ColorMaskOff);
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);
// 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);
fnode = fnode->next;
}
// 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;
//

View file

@ -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<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.
//
//==========================================================================
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;

View file

@ -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 T>
class TStaticPointedArray