Merge branch 'indexbuffer'

# Conflicts:
#	src/gl/data/gl_vertexbuffer.h
#	src/gl/scene/gl_flats.cpp
#	src/hwrenderer/data/flatvertices.h
This commit is contained in:
Christoph Oelckers 2018-05-22 22:10:21 +02:00
commit b612e182b4
19 changed files with 211 additions and 45 deletions

View file

@ -588,6 +588,7 @@ bool FDrawInfo::PutFlatCompat(GLFlat *flat, bool fog)
int list = list_indices[masked][foggy];
auto newflat = 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:
@ -171,6 +173,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;
@ -189,6 +196,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);
@ -246,4 +254,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 Reset()
{
mCurIndex = mIndex;

View file

@ -62,7 +62,7 @@ static void matrixToGL(const VSMatrix &mat, int loc)
void FRenderState::Reset()
{
mTextureEnabled = true;
mClipLineEnabled = mSplitEnabled = mBrightmapEnabled = mFogEnabled = mGlowEnabled = false;
mClipLineShouldBeActive = mClipLineEnabled = mSplitEnabled = mBrightmapEnabled = mFogEnabled = mGlowEnabled = false;
mColorMask[0] = mColorMask[1] = mColorMask[2] = mColorMask[3] = true;
currentColorMask[0] = currentColorMask[1] = currentColorMask[2] = currentColorMask[3] = true;
mFogColor.d = -1;

View file

@ -81,6 +81,7 @@ class FRenderState
bool mGlowEnabled;
bool mSplitEnabled;
bool mClipLineEnabled;
bool mClipLineShouldBeActive;
bool mBrightmapEnabled;
bool mColorMask[4];
bool currentColorMask[4];
@ -201,6 +202,11 @@ public:
return mClipLineEnabled;
}
bool GetClipLineShouldBeActive()
{
return mClipLineShouldBeActive;
}
void SetClipHeight(float height, float direction);
void SetNormal(FVector3 norm)
@ -326,6 +332,11 @@ public:
glDisable(GL_CLIP_DISTANCE0);
}
}
else
{
// this needs to be flagged because in this case per-sector plane rendering needs to be disabled if a clip plane is active.
mClipLineShouldBeActive = on;
}
}
void EnableBrightmap(bool on)

View file

@ -121,6 +121,7 @@ struct FDrawInfo : public HWDrawInfo
void ProcessLights(GLFlat *flat, bool istrans);
void DrawSubsector(GLFlat *flat, subsector_t * sub);
void SetupSubsectorLights(GLFlat *flat, int pass, subsector_t * sub, int *dli);
void SetupSectorLights(GLFlat *flat, int pass, int *dli);
// Sprite drawer
void DrawSprite(GLSprite *sprite, int pass);

View file

@ -48,6 +48,8 @@
#include "gl/scene/gl_scenedrawer.h"
#include "gl/renderer/gl_quaddrawer.h"
CVAR(Bool, gl_render_subsectors, false, 0)
//==========================================================================
//
// Flats
@ -62,7 +64,35 @@ void FDrawInfo::SetupSubsectorLights(GLFlat *flat, int pass, subsector_t * sub,
(*dli)++;
return;
}
if (flat->SetupSubsectorLights(pass, sub, lightdata))
if (flat->SetupSectorLights(pass, flat->sector, lightdata))
{
int d = GLRenderer->mLights->UploadLights(lightdata);
if (pass == GLPASS_LIGHTSONLY)
{
GLRenderer->mLights->StoreIndex(d);
}
else
{
gl_RenderState.ApplyLightIndex(d);
}
}
}
//==========================================================================
//
//
//
//==========================================================================
void FDrawInfo::SetupSectorLights(GLFlat *flat, int pass, int *dli)
{
if (dli != NULL && *dli != -1)
{
gl_RenderState.ApplyLightIndex(GLRenderer->mLights->GetIndex(*dli));
(*dli)++;
return;
}
if (flat->SetupSectorLights(pass, flat->sector, lightdata))
{
int d = GLRenderer->mLights->UploadLights(lightdata);
if (pass == GLPASS_LIGHTSONLY)
@ -137,15 +167,22 @@ void FDrawInfo::ProcessLights(GLFlat *flat, bool istrans)
{
flat->dynlightindex = GLRenderer->mLights->GetIndexPtr();
if (flat->sector->ibocount > 0 && !gl_render_subsectors && !gl_RenderState.GetClipLineShouldBeActive())
{
SetupSectorLights(flat, GLPASS_LIGHTSONLY, nullptr);
}
else
{
// Draw the subsectors belonging to this sector
for (int i=0; i< flat->sector->subsectorcount; i++)
for (int i = 0; i < flat->sector->subsectorcount; i++)
{
subsector_t * sub = flat->sector->subsectors[i];
if (ss_renderflags[sub->Index()]& flat->renderflags || istrans)
if (ss_renderflags[sub->Index()] & flat->renderflags || istrans)
{
SetupSubsectorLights(flat, GLPASS_LIGHTSONLY, sub, nullptr);
}
}
}
// Draw the subsectors assigned to it due to missing textures
if (!(flat->renderflags&SSRF_RENDER3DPLANES))
@ -175,29 +212,40 @@ void FDrawInfo::DrawSubsectors(GLFlat *flat, int pass, bool processlights, bool
gl_RenderState.Apply();
if (gl.legacyMode) processlights = false;
if (flat->vboindex >= 0)
auto vcount = flat->sector->ibocount;
if (vcount > 0 && !gl_render_subsectors && !gl_RenderState.GetClipLineShouldBeActive())
{
if (processlights) SetupSectorLights(flat, GLPASS_ALL, &dli);
drawcalls.Clock();
glDrawElements(GL_TRIANGLES, vcount, GL_UNSIGNED_INT, GLRenderer->mVBO->GetIndexPointer() + flat->vboindex);
drawcalls.Unclock();
flatvertices += vcount;
flatprimitives++;
}
else if (flat->vboindex >= 0)
{
int index = flat->vboindex;
for (int i=0; i<flat->sector->subsectorcount; i++)
{
subsector_t * sub = flat->sector->subsectors[i];
if (sub->numlines <= 2) continue;
if (ss_renderflags[sub->Index()]& flat->renderflags || istrans)
{
if (processlights) SetupSubsectorLights(flat, GLPASS_ALL, sub, &dli);
drawcalls.Clock();
glDrawArrays(GL_TRIANGLE_FAN, index, sub->numlines);
glDrawElements(GL_TRIANGLES, (sub->numlines - 2) * 3, GL_UNSIGNED_INT, GLRenderer->mVBO->GetIndexPointer() + index);
drawcalls.Unclock();
flatvertices += sub->numlines;
flatprimitives++;
}
index += sub->numlines;
index += (sub->numlines - 2) * 3;
}
}
else
{
// Draw the subsectors belonging to this sector
// (can this case even happen?)
for (int i=0; i<flat->sector->subsectorcount; i++)
{
subsector_t * sub = flat->sector->subsectors[i];

View file

@ -118,13 +118,22 @@ static F3DFloor *Find3DFloor(sector_t *target, sector_t *model)
//
//==========================================================================
int FFlatVertexGenerator::CreateSubsectorVertices(subsector_t *sub, const secplane_t &plane, int floor)
int FFlatVertexGenerator::CreateIndexedSubsectorVertices(subsector_t *sub, const secplane_t &plane, int floor, int vi, FFlatVertexGenerator::FIndexGenerationInfo &gen)
{
int idx = vbo_shadowdata.Reserve(sub->numlines);
for(unsigned int k=0; k<sub->numlines; k++, idx++)
if (sub->numlines < 3) return -1;
int idx = ibo_data.Reserve((sub->numlines - 2) * 3);
int idxc = idx;
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++)
{
vbo_shadowdata[idx].SetFlatVertex(sub->firstline[k].v1, plane);
if (sub->sector->transdoor && floor) vbo_shadowdata[idx].z -= 1.f;
auto ndx = gen.GetIndex(sub->firstline[k].v1);
ibo_data[idx++] = vi + firstndx;
ibo_data[idx++] = vi + secondndx;
ibo_data[idx++] = vi + ndx;
secondndx = ndx;
}
return idx;
}
@ -135,15 +144,28 @@ int FFlatVertexGenerator::CreateSubsectorVertices(subsector_t *sub, const secpla
//
//==========================================================================
int FFlatVertexGenerator::CreateSectorVertices(sector_t *sec, const secplane_t &plane, int floor)
int FFlatVertexGenerator::CreateIndexedSectorVertices(sector_t *sec, const secplane_t &plane, int floor, FFlatVertexGenerator::FIndexGenerationInfo &gen)
{
int rt = vbo_shadowdata.Size();
// First calculate the vertices for the sector itself
for(int j=0; j<sec->subsectorcount; j++)
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];
CreateSubsectorVertices(sub, plane, floor);
CreateIndexedSubsectorVertices(sub, plane, floor, vi, gen);
}
sec->ibocount = ibo_data.Size() - rt;
return rt;
}
@ -153,23 +175,23 @@ int FFlatVertexGenerator::CreateSectorVertices(sector_t *sec, const secplane_t &
//
//==========================================================================
int FFlatVertexGenerator::CreateVertices(int h, sector_t *sec, const secplane_t &plane, int floor)
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] = CreateSectorVertices(sec, plane, floor);
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++)
for (unsigned g = 0; g<fakes.Size(); g++)
{
sector_t *fsec = fakes[g];
fsec->vboindex[2+h] = CreateSectorVertices(fsec, plane, false);
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++)
for (unsigned g = 0; g<xf.Size(); g++)
{
sector_t *fsec = xf[g];
F3DFloor *ffloor = Find3DFloor(fsec, sec);
@ -181,10 +203,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 = CreateIndexedSectorVertices(fsec, plane, false, gen[fsec->Index()]);
if (dotop) ffloor->top.vindex = ndx;
if (dobottom) ffloor->bottom.vindex = ndx;
}
}
}
@ -199,13 +220,28 @@ int FFlatVertexGenerator::CreateVertices(int h, sector_t *sec, const secplane_t
//
//==========================================================================
void FFlatVertexGenerator::CreateFlatVertices()
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)
for (auto &sec : level.sectors)
{
CreateVertices(h, &sec, sec.GetSecPlane(h), h == sector_t::floor);
CreateIndexedVertices(h, &sec, sec.GetSecPlane(h), h == sector_t::floor, gen);
}
}
@ -213,7 +249,7 @@ void FFlatVertexGenerator::CreateFlatVertices()
// 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)
for (auto ff : sec.e->XFloor.ffloors)
{
if (ff->top.model == &sec)
{
@ -257,7 +293,7 @@ void FFlatVertexGenerator::UpdatePlaneVertices(sector_t *sec, int plane)
void FFlatVertexGenerator::CreateVertices()
{
vbo_shadowdata.Resize(NUM_RESERVED);
CreateFlatVertices();
CreateIndexedFlatVertices();
}
//==========================================================================

View file

@ -45,8 +45,32 @@ class FFlatVertexGenerator
{
protected:
TArray<FFlatVertex> vbo_shadowdata;
TArray<uint32_t> ibo_data;
FFlatVertex *mMap;
// 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;
}
};
public:
enum
@ -65,10 +89,11 @@ public:
void OutputResized(int width, int height);
private:
int CreateSubsectorVertices(subsector_t *sub, const secplane_t &plane, int floor);
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);
protected:
void CreateVertices();

View file

@ -311,7 +311,9 @@ public:
int dynlightindex;
bool SetupLights(int pass, FLightNode *head, FDynLightData &lightdata, int portalgroup);
bool SetupSubsectorLights(int pass, subsector_t * sub, FDynLightData &lightdata);
bool SetupSectorLights(int pass, sector_t * sec, FDynLightData &lightdata);
void PutFlat(HWDrawInfo *di, bool fog = false);
void Process(HWDrawInfo *di, sector_t * model, int whichplane, bool notexture);

View file

@ -92,14 +92,13 @@ bool hw_SetPlaneTextureRotation(const GLSectorPlane * secplane, FMaterial * glte
//
//==========================================================================
bool GLFlat::SetupSubsectorLights(int pass, subsector_t * sub, FDynLightData &lightdata)
bool GLFlat::SetupLights(int pass, FLightNode * node, FDynLightData &lightdata, int portalgroup)
{
Plane p;
if (renderstyle == STYLE_Add && !level.lightadditivesurfaces) return false; // no lights on additively blended surfaces.
lightdata.Clear();
FLightNode * node = sub->lighthead;
while (node)
{
ADynamicLight * light = node->lightsource;
@ -121,13 +120,23 @@ bool GLFlat::SetupSubsectorLights(int pass, subsector_t * sub, FDynLightData &li
}
p.Set(plane.plane.Normal(), plane.plane.fD());
lightdata.GetLight(sub->sector->PortalGroup, p, light, false);
lightdata.GetLight(portalgroup, p, light, false);
node = node->nextLight;
}
return true;
}
bool GLFlat::SetupSubsectorLights(int pass, subsector_t * sub, FDynLightData &lightdata)
{
return SetupLights(pass, sub->lighthead, lightdata, sub->sector->PortalGroup);
}
bool GLFlat::SetupSectorLights(int pass, sector_t * sec, FDynLightData &lightdata)
{
return SetupLights(pass, sec->lighthead, lightdata, sec->PortalGroup);
}
//==========================================================================
//
// GLFlat::PutFlat

View file

@ -1090,6 +1090,7 @@ void HWDrawInfo::ProcessSectorStacks(area_t in_area)
{
subsector_t *sub = HandledSubsectors[j];
ss_renderflags[sub->Index()] &= ~SSRF_RENDERCEILING;
sub->sector->ibocount = -1; // cannot render this sector in one go.
if (sub->portalcoverage[sector_t::ceiling].subsectors == NULL)
{
@ -1135,6 +1136,7 @@ void HWDrawInfo::ProcessSectorStacks(area_t in_area)
{
subsector_t *sub = HandledSubsectors[j];
ss_renderflags[sub->Index()] &= ~SSRF_RENDERFLOOR;
sub->sector->ibocount = -1; // cannot render this sector in one go.
if (sub->portalcoverage[sector_t::floor].subsectors == NULL)
{

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

@ -1383,6 +1383,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); }

View file

@ -1159,10 +1159,15 @@ bool SystemFrameBuffer::IsFullscreen()
//
//
//==========================================================================
EXTERN_CVAR(Bool, vid_vsync);
CUSTOM_CVAR(Bool, gl_control_tear, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
{
vid_vsync.Callback();
}
void SystemFrameBuffer::SetVSync (bool vsync)
{
if (myWglSwapIntervalExtProc != NULL) myWglSwapIntervalExtProc(vsync ? SwapInterval : 0);
if (myWglSwapIntervalExtProc != NULL) myWglSwapIntervalExtProc(vsync ? (gl_control_tear? SwapInterval : 1) : 0);
}
void SystemFrameBuffer::SwapBuffers()

View file

@ -10,6 +10,10 @@ vec3 lightContribution(int i, vec3 normal)
if (lightpos.w < lightdistance)
return vec3(0.0); // Early out lights touching surface but not this fragment
vec3 lightdir = normalize(lightpos.xyz - pixelpos.xyz);
float dotprod = dot(normal, lightdir);
if (dotprod < 0.0) return vec3(0.0); // light hits from the backside. This can happen with full sector light lists and must be rejected for all cases.
float attenuation = clamp((lightpos.w - lightdistance) / lightpos.w, 0.0, 1.0);
if (lightspot1.w == 1.0)
@ -17,8 +21,7 @@ vec3 lightContribution(int i, vec3 normal)
if (lightcolor.a < 0.0) // Sign bit is the attenuated light flag
{
vec3 lightdir = normalize(lightpos.xyz - pixelpos.xyz);
attenuation *= clamp(dot(normal, lightdir), 0.0, 1.0);
attenuation *= clamp(dotprod, 0.0, 1.0);
}
if (attenuation > 0.0) // Skip shadow map test if possible

View file

@ -12,7 +12,7 @@ struct SBarInfo native ui
}
// The sole purpose of this wrapper is to elimintate the native dependencies of the status bar object
// The sole purpose of this wrapper is to eliminate the native dependencies of the status bar object
// because those would seriously impede the script conversion of the base class.
class SBarInfoWrapper : BaseStatusBar