- sector rendering refactoring for sections - work in progress.

This commit is contained in:
Christoph Oelckers 2018-11-05 01:01:48 +01:00
parent 0deb388a75
commit d7db00d92e
9 changed files with 185 additions and 12 deletions

View file

@ -53,6 +53,7 @@ struct FBlockNode;
struct FPortalGroupArray;
struct visstyle_t;
class FLightDefaults;
struct FSection;
//
// NOTES: AActor
//

View file

@ -34,6 +34,7 @@
#include "p_setup.h"
#include "c_dispatch.h"
#include "memarena.h"
#include "flatvertices.h"
using DoublePoint = std::pair<DVector2, DVector2>;
@ -611,6 +612,114 @@ public:
return false;
}
//=============================================================================
//
//
//
//=============================================================================
// Temporary data for creating an indexed buffer
struct VertexIndexGenerationInfo
{
TArray<vertex_t *> vertices;
TMap<vertex_t*, uint32_t> vertexmap;
TArray<uint32_t> indices;
uint32_t AddVertex(vertex_t *vert)
{
auto check = vertexmap.CheckKey(vert);
if (check != nullptr) return *check;
auto index = vertices.Push(vert);
vertexmap[vert] = index;
return index;
}
uint32_t GetIndex(vertex_t *vert)
{
auto check = vertexmap.CheckKey(vert);
if (check != nullptr) return *check;
return ~0u;
}
uint32_t AddIndexForVertex(vertex_t *vert)
{
return indices.Push(GetIndex(vert));
}
uint32_t AddIndex(uint32_t indx)
{
return indices.Push(indx);
}
};
//=============================================================================
//
//
//
//=============================================================================
void CreateIndexedSubsectorVertices(subsector_t *sub, VertexIndexGenerationInfo &gen)
{
if (sub->numlines < 3) return;
uint32_t startindex = gen.indices.Size();
if ((sub->flags & SSECF_HOLE) && sub->numlines > 3)
{
// Hole filling "subsectors" are not necessarily convex so they require real triangulation.
// These things are extremely rare so performance is secondary here.
using Point = std::pair<double, double>;
std::vector<std::vector<Point>> polygon;
std::vector<Point> *curPoly;
for (unsigned i = 0; i < sub->numlines; i++)
{
polygon.resize(1);
curPoly = &polygon.back();
curPoly->push_back({ sub->firstline[i].v1->fX(), sub->firstline[i].v1->fY() });
}
auto indices = mapbox::earcut(polygon);
for (auto vti : indices)
{
gen.AddIndexForVertex(sub->firstline[vti].v1);
}
}
else
{
int firstndx = gen.GetIndex(sub->firstline[0].v1);
int secondndx = gen.GetIndex(sub->firstline[1].v1);
for (unsigned int k = 2; k < sub->numlines; k++)
{
gen.AddIndex(firstndx);
gen.AddIndex(secondndx);
auto ndx = gen.GetIndex(sub->firstline[k].v1);
gen.AddIndex(ndx);
secondndx = ndx;
}
}
}
void CreateVerticesForSection(FSectionContainer &output, FSection &section)
{
VertexIndexGenerationInfo gen;
for (auto sub : section.subsectors)
{
CreateIndexedSubsectorVertices(sub, gen);
}
section.vertexindex = output.allVertices.Size();
section.vertexcount = gen.vertices.Size();
section.indexindex = output.allVertexIndices.Size();
section.indexcount = gen.indices.Size();
output.allVertices.Append(gen.vertices);
output.allVertexIndices.Append(gen.indices);
}
//=============================================================================
//
//
@ -620,10 +729,14 @@ public:
void ConstructOutput(FSectionContainer &output)
{
output.allSections.Resize(groups.Size());
output.allIndices.Resize(level.subsectors.Size() + level.sides.Size());
output.allIndices.Resize(level.subsectors.Size() + level.sides.Size() + 2*level.sectors.Size());
output.sectionForSubsectorPtr = &output.allIndices[0];
output.sectionForSidedefPtr = &output.allIndices[level.subsectors.Size()];
output.firstSectionForSectorPtr = &output.allIndices[level.subsectors.Size() + level.sides.Size()];
output.numberOfSectionForSectorPtr = &output.allIndices[level.subsectors.Size() + level.sides.Size() + level.sectors.Size()];
memset(output.sectionForSubsectorPtr, -1, sizeof(int) * level.subsectors.Size());
memset(output.firstSectionForSectorPtr, -1, sizeof(int) * level.sectors.Size());
memset(output.numberOfSectionForSectorPtr, 0, sizeof(int) * level.sectors.Size());
unsigned numsegments = 0;
unsigned numsides = 0;
@ -669,10 +782,15 @@ public:
dest.validcount = 0;
dest.segments.Set(&output.allLines[numsegments], group.segments.Size());
dest.sides.Set(&output.allSides[numsides], group.sideMap.CountUsed());
dest.subsectors.Set(&output.allSubsectors[numsubsectors]);
dest.subsectors.Set(&output.allSubsectors[numsubsectors], group.subsectors.Size());
dest.vertexindex = -1;
dest.vertexcount = 0;
dest.bounds = {1e32, 1e32, -1e32, -1e32};
numsegments += group.segments.Size();
if (output.firstSectionForSectorPtr[dest.sector->Index()] == -1)
output.firstSectionForSectorPtr[dest.sector->Index()] = curgroup;
for (auto &segment : group.segments)
{
// Use the indices calculated above to store these elements.
@ -697,6 +815,7 @@ public:
output.sectionForSubsectorPtr[ssi] = curgroup;
}
numsubsectors += group.subsectors.Size();
CreateVerticesForSection(output, dest);
curgroup++;
}
}

View file

@ -80,11 +80,15 @@ struct FSection
{
// tbd: Do we need a list of subsectors here? Ideally the subsectors should not be used anywhere anymore except for finding out where a location is.
TArrayView<FSectionLine> segments;
TArrayView<side_t *> sides; // contains all sidedefs, including the internal ones that do not make up the outer shape. (this list is not exclusive. A sidedef can be in multiple sections!)
TArrayView<subsector_t *> subsectors; // contains all sidedefs, including the internal ones that do not make up the outer shape. (this list is not exclusive. A sidedef can be in multiple sections!)
TArrayView<side_t *> sides; // contains all sidedefs, including the internal ones that do not make up the outer shape.
TArrayView<subsector_t *> subsectors; // contains all subsectors making up this section
sector_t *sector;
FLightNode *lighthead; // Light nodes (blended and additive)
FLightNode *lighthead; // Light nodes (blended and additive)
BoundingRect bounds;
int vertexindex;
int vertexcount; // index and length of this section's entry in the allVertices array
int indexindex;
int indexcount; // index and length of this section's entry in the allVertices array
int validcount;
short mapsection;
char hacked; // 1: is part of a render hack
@ -95,13 +99,16 @@ class FSectionContainer
public:
TArray<FSectionLine> allLines;
TArray<FSection> allSections;
//TArray<vertex_t*> allVertices;
TArray<vertex_t*> allVertices;
TArray<uint32_t> allVertexIndices;
TArray<side_t *> allSides;
TArray<subsector_t *> allSubsectors;
TArray<int> allIndices;
int *sectionForSubsectorPtr; // stored inside allIndices
int *sectionForSidedefPtr; // also stored inside allIndices;
int *firstSectionForSectorPtr; // ditto.
int *numberOfSectionForSectorPtr; // ditto.
FSection *SectionForSubsector(subsector_t *sub)
{
@ -111,6 +118,14 @@ public:
{
return ssindex < 0 ? nullptr : &allSections[sectionForSubsectorPtr[ssindex]];
}
int SectionNumForSubsector(subsector_t *sub)
{
return SectionNumForSubsector(sub->Index());
}
int SectionNumForSubsector(int ssindex)
{
return ssindex < 0 ? -1 : sectionForSubsectorPtr[ssindex];
}
FSection *SectionForSidedef(side_t *side)
{
return SectionForSidedef(side->Index());
@ -119,11 +134,35 @@ public:
{
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());
}
TArrayView<FSection> SectionsForSector(int sindex)
{
return sindex < 0 ? TArrayView<FSection>(0) : TArrayView<FSection>(&allSections[firstSectionForSectorPtr[sindex]], numberOfSectionForSectorPtr[sindex]);
}
int SectionIndex(const FSection *sect)
{
return int(sect - allSections.Data());
}
void Clear()
{
allLines.Clear();
allSections.Clear();
allIndices.Clear();
allVertexIndices.Clear();
allVertices.Clear();
allSides.Clear();
allSubsectors.Clear();
}
void Reset()
{
@ -131,6 +170,10 @@ public:
allLines.ShrinkToFit();
allSections.ShrinkToFit();
allIndices.ShrinkToFit();
allVertexIndices.ShrinkToFit();
allVertices.ShrinkToFit();
allSides.ShrinkToFit();
allSubsectors.ShrinkToFit();
}
};

View file

@ -155,6 +155,7 @@ void HWDrawInfo::WorkerThread()
{
GLFlat flat;
SetupFlat.Clock();
flat.section = level.sections.SectionForSubsector(job->sub);
front = hw_FakeFlat(job->sub->render_sector, &fakefront, in_area, false);
flat.ProcessSector(this, front);
SetupFlat.Unclock();
@ -679,7 +680,8 @@ void HWDrawInfo::DoSubsector(subsector_t * sub)
fakesector = hw_FakeFlat(sector, &fake, in_area, false);
}
uint8_t &srf = sectorrenderflags[sub->render_sector->sectornum];
auto secnum = level.sections.SectionNumForSubsector(sub);
uint8_t &srf = section_renderflags[secnum];
if (!(srf & SSRF_PROCESSED))
{
srf |= SSRF_PROCESSED;
@ -691,6 +693,7 @@ void HWDrawInfo::DoSubsector(subsector_t * sub)
else
{
GLFlat flat;
flat.section = level.sections.SectionForSubsector(sub);
SetupFlat.Clock();
flat.ProcessSector(this, fakesector);
SetupFlat.Unclock();

View file

@ -214,11 +214,11 @@ void HWDrawInfo::ClearBuffers()
CurrentMapSections.Resize(level.NumMapSections);
CurrentMapSections.Zero();
sectorrenderflags.Resize(level.sectors.Size());
section_renderflags.Resize(level.sections.allSections.Size());
ss_renderflags.Resize(level.subsectors.Size());
no_renderflags.Resize(level.subsectors.Size());
memset(&sectorrenderflags[0], 0, level.sectors.Size() * sizeof(sectorrenderflags[0]));
memset(&section_renderflags[0], 0, level.sections.allSections.Size() * sizeof(section_renderflags[0]));
memset(&ss_renderflags[0], 0, level.subsectors.Size() * sizeof(ss_renderflags[0]));
memset(&no_renderflags[0], 0, level.nodes.Size() * sizeof(no_renderflags[0]));

View file

@ -170,7 +170,7 @@ struct HWDrawInfo
TArray<subsector_t *> HandledSubsectors;
TArray<uint8_t> sectorrenderflags;
TArray<uint8_t> section_renderflags;
TArray<uint8_t> ss_renderflags;
TArray<uint8_t> no_renderflags;

View file

@ -27,6 +27,7 @@ struct FSpriteModelFrame;
struct particle_t;
class FRenderState;
struct GLDecal;
struct FSection;
enum area_t : int;
enum HWRenderStyle
@ -293,6 +294,7 @@ class GLFlat
{
public:
sector_t * sector;
FSection *section;
float z; // the z position of the flat (only valid for non-sloped planes)
FMaterial *gltexture;

View file

@ -189,6 +189,8 @@ void GLFlat::DrawSubsectors(HWDrawInfo *di, FRenderState &state)
SetupLights(di, sector->lighthead, lightdata, sector->PortalGroup);
}
state.SetLightIndex(dynlightindex);
if (vcount > 0 && !di->ClipLineShouldBeActive())
{
state.DrawIndexed(DT_Triangles, iboindex, vcount);
@ -197,6 +199,7 @@ void GLFlat::DrawSubsectors(HWDrawInfo *di, FRenderState &state)
}
else
{
/*
int index = iboindex;
bool applied = false;
for (int i = 0; i < sector->subsectorcount; i++)
@ -213,6 +216,7 @@ void GLFlat::DrawSubsectors(HWDrawInfo *di, FRenderState &state)
}
index += (sub->numlines - 2) * 3;
}
*/
}
if (!(renderflags&SSRF_RENDER3DPLANES))
@ -473,7 +477,7 @@ void GLFlat::ProcessSector(HWDrawInfo *di, sector_t * frontsector)
extsector_t::xfloor &x = sector->e->XFloor;
dynlightindex = -1;
uint8_t &srf = di->sectorrenderflags[sector->sectornum];
uint8_t &srf = di->section_renderflags[level.sections.SectionIndex(section)];
const auto &vp = di->Viewpoint;
//

View file

@ -850,7 +850,8 @@ void HWDrawInfo::PrepareUnhandledMissingTextures()
if (seg->linedef->validcount == validcount) continue; // already done
seg->linedef->validcount = validcount;
if (!(sectorrenderflags[seg->backsector->sectornum] & SSRF_RENDERFLOOR)) continue;
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;