- use an indexed vertex buffer to render the flats.

Right now this has no advantage but it allows optimizing the data, e.g. rendering an entire sector in one go instead of per subsector.
This commit is contained in:
Christoph Oelckers 2018-05-19 13:33:28 +02:00
parent 5ec47d8b4f
commit fd3681dae2
10 changed files with 202 additions and 9 deletions

View file

@ -588,6 +588,7 @@ bool FDrawInfo::PutFlatCompat(GLFlat *flat, bool fog)
int list = list_indices[masked][foggy];
auto newflat = gl_drawinfo->dldrawlists[list].NewFlat();
*newflat = *flat;
newflat->vboindex = -1; // don't use the vertex buffer with legacy lights to ensure all passes use the same render logic.
return true;
}

View file

@ -125,6 +125,8 @@ void FSimpleVertexBuffer::set(FSimpleVertex *verts, int count)
FFlatVertexBuffer::FFlatVertexBuffer(int width, int height)
: FVertexBuffer(!gl.legacyMode), FFlatVertexGenerator(width, height)
{
ibo_id = 0;
if (gl.buffermethod != BM_LEGACY) glGenBuffers(1, &ibo_id);
switch (gl.buffermethod)
{
case BM_PERSISTENT:
@ -170,6 +172,11 @@ FFlatVertexBuffer::~FFlatVertexBuffer()
glUnmapBuffer(GL_ARRAY_BUFFER);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
if (ibo_id != 0)
{
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glDeleteBuffers(1, &ibo_id);
}
if (gl.legacyMode)
{
delete[] map;
@ -188,6 +195,7 @@ void FFlatVertexBuffer::OutputResized(int width, int height)
void FFlatVertexBuffer::BindVBO()
{
glBindBuffer(GL_ARRAY_BUFFER, vbo_id);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo_id);
if (!gl.legacyMode)
{
glVertexAttribPointer(VATTR_VERTEX, 3, GL_FLOAT, false, sizeof(FFlatVertex), &VTO->x);
@ -245,4 +253,9 @@ void FFlatVertexBuffer::CreateVBO()
Map();
memcpy(map, &vbo_shadowdata[0], vbo_shadowdata.Size() * sizeof(FFlatVertex));
Unmap();
if (ibo_id > 0)
{
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo_id);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, ibo_data.Size() * sizeof(uint32_t), &ibo_data[0], GL_STATIC_DRAW);
}
}

View file

@ -95,6 +95,7 @@ public:
class FFlatVertexBuffer : public FVertexBuffer, public FFlatVertexGenerator
{
unsigned int ibo_id;
FFlatVertex *map;
unsigned int mIndex;
std::atomic<unsigned int> mCurIndex;
@ -177,6 +178,11 @@ public:
#endif
uint32_t *GetIndexPointer() const
{
return ibo_id == 0 ? &ibo_data[0] : nullptr;
}
void CheckPlanes(sector_t *sector)
{
FFlatVertexGenerator::CheckPlanes(sector, map);

View file

@ -186,7 +186,8 @@ void FDrawInfo::DrawSubsectors(GLFlat *flat, int pass, bool processlights, bool
{
if (processlights) SetupSubsectorLights(flat, GLPASS_ALL, sub, &dli);
drawcalls.Clock();
glDrawArrays(GL_TRIANGLE_FAN, index, sub->numlines);
//glDrawArrays(GL_TRIANGLE_FAN, index, sub->numlines);
glDrawElements(GL_TRIANGLE_FAN, sub->numlines, GL_UNSIGNED_INT, GLRenderer->mVBO->GetIndexPointer() + index);
drawcalls.Unclock();
flatvertices += sub->numlines;
flatprimitives++;

View file

@ -181,10 +181,9 @@ int FFlatVertexGenerator::CreateVertices(int h, sector_t *sec, const secplane_t
if (dotop || dobottom)
{
if (dotop) ffloor->top.vindex = vbo_shadowdata.Size();
if (dobottom) ffloor->bottom.vindex = vbo_shadowdata.Size();
CreateSectorVertices(fsec, plane, false);
auto ndx = CreateSectorVertices(fsec, plane, false);
if (dotop) ffloor->top.vindex = ndx;
if (dobottom) ffloor->bottom.vindex = ndx;
}
}
}
@ -227,6 +226,147 @@ void FFlatVertexGenerator::CreateFlatVertices()
}
}
//==========================================================================
//
// Creates the vertices for one plane in one subsector
//
//==========================================================================
int FFlatVertexGenerator::CreateIndexedSubsectorVertices(subsector_t *sub, const secplane_t &plane, int floor, int vi, FFlatVertexGenerator::FIndexGenerationInfo &gen)
{
int idx = ibo_data.Reserve(sub->numlines);
for (unsigned int k = 0; k<sub->numlines; k++)
{
auto ndx = gen.GetIndex(sub->firstline[k].v1);
ibo_data[idx + k] = vi + ndx;
}
return idx;
}
//==========================================================================
//
// Creates the vertices for one plane in one subsector
//
//==========================================================================
int FFlatVertexGenerator::CreateIndexedSectorVertices(sector_t *sec, const secplane_t &plane, int floor, FFlatVertexGenerator::FIndexGenerationInfo &gen)
{
int rt = ibo_data.Size();
int vi = vbo_shadowdata.Reserve(gen.vertices.Size());
float diff;
// Create the actual vertices.
if (sec->transdoor && floor) diff = -1.f;
else diff = 0.f;
for (unsigned i = 0; i < gen.vertices.Size(); i++)
{
vbo_shadowdata[vi + i].SetFlatVertex(gen.vertices[i], plane);
vbo_shadowdata[vi + i].z += diff;
}
// Create the indices for the subsectors
for (int j = 0; j<sec->subsectorcount; j++)
{
subsector_t *sub = sec->subsectors[j];
CreateIndexedSubsectorVertices(sub, plane, floor, vi, gen);
}
return rt;
}
//==========================================================================
//
//
//
//==========================================================================
int FFlatVertexGenerator::CreateIndexedVertices(int h, sector_t *sec, const secplane_t &plane, int floor, TArray<FFlatVertexGenerator::FIndexGenerationInfo> &gen)
{
// First calculate the vertices for the sector itself
sec->vboheight[h] = sec->GetPlaneTexZ(h);
sec->vboindex[h] = CreateIndexedSectorVertices(sec, plane, floor, gen[sec->Index()]);
// Next are all sectors using this one as heightsec
TArray<sector_t *> &fakes = sec->e->FakeFloor.Sectors;
for (unsigned g = 0; g<fakes.Size(); g++)
{
sector_t *fsec = fakes[g];
fsec->vboindex[2 + h] = CreateIndexedSectorVertices(fsec, plane, false, gen[fsec->Index()]);
}
// and finally all attached 3D floors
TArray<sector_t *> &xf = sec->e->XFloor.attached;
for (unsigned g = 0; g<xf.Size(); g++)
{
sector_t *fsec = xf[g];
F3DFloor *ffloor = Find3DFloor(fsec, sec);
if (ffloor != NULL && ffloor->flags & FF_RENDERPLANES)
{
bool dotop = (ffloor->top.model == sec) && (ffloor->top.isceiling == h);
bool dobottom = (ffloor->bottom.model == sec) && (ffloor->bottom.isceiling == h);
if (dotop || dobottom)
{
auto ndx = CreateIndexedSectorVertices(fsec, plane, false, gen[fsec->Index()]);
if (dotop) ffloor->top.vindex = ndx;
if (dobottom) ffloor->bottom.vindex = ndx;
}
}
}
sec->vbocount[h] = vbo_shadowdata.Size() - sec->vboindex[h];
return sec->vboindex[h];
}
//==========================================================================
//
//
//
//==========================================================================
void FFlatVertexGenerator::CreateIndexedFlatVertices()
{
TArray<FIndexGenerationInfo> gen;
gen.Resize(level.sectors.Size());
// This must be generated up front so that the following code knows how many vertices a sector contains.
for (unsigned i = 0; i < level.sectors.Size(); i++)
{
for (int j = 0; j < level.sectors[i].subsectorcount; j++)
{
auto sub = level.sectors[i].subsectors[j];
for (unsigned k = 0; k < sub->numlines; k++)
{
auto vert = sub->firstline[k].v1;
gen[i].AddVertex(vert);
}
}
}
for (int h = sector_t::floor; h <= sector_t::ceiling; h++)
{
for (auto &sec : level.sectors)
{
CreateIndexedVertices(h, &sec, sec.GetSecPlane(h), h == sector_t::floor, gen);
}
}
// We need to do a final check for Vavoom water and FF_FIX sectors.
// No new vertices are needed here. The planes come from the actual sector
for (auto &sec : level.sectors)
{
for (auto ff : sec.e->XFloor.ffloors)
{
if (ff->top.model == &sec)
{
ff->top.vindex = sec.vboindex[ff->top.isceiling];
}
if (ff->bottom.model == &sec)
{
ff->bottom.vindex = sec.vboindex[ff->top.isceiling];
}
}
}
}
//==========================================================================
//
//
@ -257,7 +397,7 @@ void FFlatVertexGenerator::UpdatePlaneVertices(sector_t *sec, int plane, FFlatVe
void FFlatVertexGenerator::CreateVertices()
{
vbo_shadowdata.Resize(NUM_RESERVED);
CreateFlatVertices();
CreateIndexedFlatVertices();
}
//==========================================================================

View file

@ -45,9 +45,31 @@ class FFlatVertexGenerator
{
protected:
TArray<FFlatVertex> vbo_shadowdata;
TArray<uint32_t> ibo_data;
// Temporary data for creating an indexed buffer
struct FIndexGenerationInfo
{
TArray<vertex_t *> vertices;
TMap<vertex_t*, uint32_t> vertexmap;
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 ~0;
}
};
void CheckPlanes(sector_t *sector);
public:
enum
@ -70,6 +92,12 @@ private:
int CreateSectorVertices(sector_t *sec, const secplane_t &plane, int floor);
int CreateVertices(int h, sector_t *sec, const secplane_t &plane, int floor);
void CreateFlatVertices();
int CreateIndexedSubsectorVertices(subsector_t *sub, const secplane_t &plane, int floor, int vi, FIndexGenerationInfo &gen);
int CreateIndexedSectorVertices(sector_t *sec, const secplane_t &plane, int floor, FIndexGenerationInfo &gen);
int CreateIndexedVertices(int h, sector_t *sec, const secplane_t &plane, int floor, TArray<FIndexGenerationInfo> &gen);
void CreateIndexedFlatVertices();
void UpdatePlaneVertices(sector_t *sec, int plane, FFlatVertex *map);
protected:
void CreateVertices();

View file

@ -120,6 +120,7 @@ static void P_Add3DFloor(sector_t* sec, sector_t* sec2, line_t* master, int flag
ffloor->top.copied = ffloor->bottom.copied = false;
ffloor->top.model = ffloor->bottom.model = ffloor->model = sec2;
ffloor->target = sec;
ffloor->top.vindex = ffloor->bottom.vindex = -1;
if (!(flags&FF_THINFLOOR))
{

View file

@ -1510,6 +1510,7 @@ void P_LoadSectors (MapData *map, FMissingTextureTracker &missingtex)
ss->friction = ORIG_FRICTION;
ss->movefactor = ORIG_FRICTION_FACTOR;
ss->sectornum = i;
ss->ibocount = -1;
}
delete[] msp;
}

View file

@ -1375,6 +1375,7 @@ public:
sec->sectornum = index;
sec->damageinterval = 32;
sec->terrainnum[sector_t::ceiling] = sec->terrainnum[sector_t::floor] = -1;
sec->ibocount = -1;
memset(sec->SpecialColors, -1, sizeof(sec->SpecialColors));
if (floordrop) sec->Flags = SECF_FLOORDROP;
// killough 3/7/98: end changes

View file

@ -1087,9 +1087,10 @@ public:
vbo_fakeceiling = ceiling+2,
};
int vboindex[4]; // VBO indices of the 4 planes this sector uses during rendering
int vboindex[4]; // VBO/IBO indices of the 4 planes this sector uses during rendering
double vboheight[2]; // Last calculated height for the 2 planes of this actual sector
int vbocount[2]; // Total count of vertices belonging to this sector's planes
int vbocount[2]; // Total count of vertices belonging to this sector's planes. This is used when a sector height changes and also contains all attached planes.
int ibocount; // number of indices per plane (identical for all planes.) If this is -1 the index buffer is not in use.
float GetReflect(int pos) { return gl_plane_reflection_i? reflect[pos] : 0; }
bool VBOHeightcheck(int pos) const { return vboheight[pos] == GetPlaneTexZ(pos); }