From f7404d20fb77b6a2fdcee179e54828e1618c27fd Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 11 May 2014 01:23:27 +0200 Subject: [PATCH] - add vertex buffer based drawing for all walls and flats. --- src/gl/data/gl_vertexbuffer.cpp | 1 + src/gl/data/gl_vertexbuffer.h | 18 +++++ src/gl/scene/gl_flats.cpp | 68 +++++++++++++++--- src/gl/scene/gl_scene.cpp | 3 + src/gl/scene/gl_vertex.cpp | 121 ++++++++++++++++++++++++++++++++ src/gl/scene/gl_wall.h | 6 ++ src/gl/scene/gl_walls_draw.cpp | 86 +++++++++++++++++------ 7 files changed, 273 insertions(+), 30 deletions(-) diff --git a/src/gl/data/gl_vertexbuffer.cpp b/src/gl/data/gl_vertexbuffer.cpp index c5703a8ef..a0f9aa849 100644 --- a/src/gl/data/gl_vertexbuffer.cpp +++ b/src/gl/data/gl_vertexbuffer.cpp @@ -296,6 +296,7 @@ void FFlatVertexBuffer::CreateVBO() { CreateFlatVBO(); memcpy(map, &vbo_shadowdata[0], vbo_shadowdata.Size() * sizeof(FFlatVertex)); + mIndex = vbo_shadowdata.Size(); } else if (sectors) { diff --git a/src/gl/data/gl_vertexbuffer.h b/src/gl/data/gl_vertexbuffer.h index 2755b6494..24fe5b4d5 100644 --- a/src/gl/data/gl_vertexbuffer.h +++ b/src/gl/data/gl_vertexbuffer.h @@ -35,6 +35,7 @@ class FFlatVertexBuffer : public FVertexBuffer { FFlatVertex *map; unsigned int mIndex; + unsigned int mCurIndex; void CheckPlanes(sector_t *sector); @@ -49,6 +50,23 @@ public: void BindVBO(); void CheckUpdate(sector_t *sector); + FFlatVertex *GetBuffer() + { + return &map[mCurIndex]; + } + unsigned int GetCount(FFlatVertex *newptr, unsigned int *poffset) + { + unsigned int newofs = unsigned int(newptr - map); + unsigned int diff = newofs - mCurIndex; + *poffset = mCurIndex; + mCurIndex = newofs; + return diff; + } + void Reset() + { + mCurIndex = mIndex; + } + private: int CreateSubsectorVertices(subsector_t *sub, const secplane_t &plane, int floor); int CreateSectorVertices(sector_t *sec, const secplane_t &plane, int floor); diff --git a/src/gl/scene/gl_flats.cpp b/src/gl/scene/gl_flats.cpp index 7ff3d7110..c32011998 100644 --- a/src/gl/scene/gl_flats.cpp +++ b/src/gl/scene/gl_flats.cpp @@ -238,21 +238,72 @@ bool GLFlat::SetupSubsectorLights(bool lightsapplied, subsector_t * sub) void GLFlat::DrawSubsector(subsector_t * sub) { - glBegin(GL_TRIANGLE_FAN); - - for(unsigned int k=0; knumlines; k++) + if (!gl_usevbo) { - vertex_t *vt = sub->firstline[k].v1; - glTexCoord2f(vt->fx/64.f, -vt->fy/64.f); - float zc = plane.plane.ZatPoint(vt->fx, vt->fy) + dz; - glVertex3f(vt->fx, zc, vt->fy); + glBegin(GL_TRIANGLE_FAN); + + if (plane.plane.a | plane.plane.b) + { + for (unsigned int k = 0; k < sub->numlines; k++) + { + vertex_t *vt = sub->firstline[k].v1; + glTexCoord2f(vt->fx / 64.f, -vt->fy / 64.f); + float zc = plane.plane.ZatPoint(vt->fx, vt->fy) + dz; + glVertex3f(vt->fx, zc, vt->fy); + } + } + else + { + float zc = FIXED2FLOAT(plane.plane.Zat0()) + dz; + for (unsigned int k = 0; k < sub->numlines; k++) + { + vertex_t *vt = sub->firstline[k].v1; + glTexCoord2f(vt->fx / 64.f, -vt->fy / 64.f); + glVertex3f(vt->fx, zc, vt->fy); + } + } + glEnd(); + } + else + { + FFlatVertex *ptr = GLRenderer->mVBO->GetBuffer(); + if (plane.plane.a | plane.plane.b) + { + for (unsigned int k = 0; k < sub->numlines; k++) + { + vertex_t *vt = sub->firstline[k].v1; + ptr->x = vt->fx; + ptr->y = vt->fy; + ptr->z = plane.plane.ZatPoint(vt->fx, vt->fy) + dz; + ptr->u = vt->fx / 64.f; + ptr->v = -vt->fy / 64.f; + ptr++; + } + } + else + { + float zc = FIXED2FLOAT(plane.plane.Zat0()) + dz; + for (unsigned int k = 0; k < sub->numlines; k++) + { + vertex_t *vt = sub->firstline[k].v1; + ptr->x = vt->fx; + ptr->y = vt->fy; + ptr->z = zc; + ptr->u = vt->fx / 64.f; + ptr->v = -vt->fy / 64.f; + ptr++; + } + } + unsigned int offset; + unsigned int count = GLRenderer->mVBO->GetCount(ptr, &offset); + glDrawArrays(GL_TRIANGLE_FAN, offset, count); } - glEnd(); flatvertices += sub->numlines; flatprimitives++; } + //========================================================================== // // @@ -292,7 +343,6 @@ void GLFlat::DrawSubsectors(int pass, bool istrans) } else { - //glColor3f( .5f,1.f,.5f); // these are for testing the VBO stuff. // Draw the subsectors belonging to this sector for (int i=0; isubsectorcount; i++) { diff --git a/src/gl/scene/gl_scene.cpp b/src/gl/scene/gl_scene.cpp index 47f990796..1aa3c2b3f 100644 --- a/src/gl/scene/gl_scene.cpp +++ b/src/gl/scene/gl_scene.cpp @@ -931,6 +931,7 @@ void FGLRenderer::RenderView (player_t* player) } gl_RenderState.SetVertexBuffer(mVBO); + GLRenderer->mVBO->Reset(); // reset statistics counters ResetProfilingData(); @@ -991,6 +992,8 @@ void FGLRenderer::WriteSavePic (player_t *player, FILE *file, int width, int hei bounds.height=height; glFlush(); SetFixedColormap(player); + gl_RenderState.SetVertexBuffer(mVBO); + GLRenderer->mVBO->Reset(); // Check if there's some lights. If not some code can be skipped. TThinkerIterator it(STAT_DLIGHT); diff --git a/src/gl/scene/gl_vertex.cpp b/src/gl/scene/gl_vertex.cpp index 3aff28d1f..03f7df520 100644 --- a/src/gl/scene/gl_vertex.cpp +++ b/src/gl/scene/gl_vertex.cpp @@ -45,6 +45,7 @@ #include "gl/renderer/gl_renderer.h" #include "gl/renderer/gl_lightdata.h" #include "gl/data/gl_data.h" +#include "gl/data/gl_vertexbuffer.h" #include "gl/dynlights/gl_glow.h" #include "gl/scene/gl_drawinfo.h" #include "gl/scene/gl_portal.h" @@ -88,6 +89,37 @@ void GLWall::SplitUpperEdge(texcoord * tcs) vertexcount += sidedef->numsegs-1; } +void GLWall::SplitUpperEdge(texcoord * tcs, FFlatVertex *&ptr) +{ + if (seg == NULL || seg->sidedef == NULL || (seg->sidedef->Flags & WALLF_POLYOBJ) || seg->sidedef->numsegs == 1) return; + + side_t *sidedef = seg->sidedef; + float polyw = glseg.fracright - glseg.fracleft; + float facu = (tcs[2].u - tcs[1].u) / polyw; + float facv = (tcs[2].v - tcs[1].v) / polyw; + float fact = (ztop[1] - ztop[0]) / polyw; + float facc = (zceil[1] - zceil[0]) / polyw; + float facf = (zfloor[1] - zfloor[0]) / polyw; + + for (int i = 0; i < sidedef->numsegs - 1; i++) + { + seg_t *cseg = sidedef->segs[i]; + float sidefrac = cseg->sidefrac; + if (sidefrac <= glseg.fracleft) continue; + if (sidefrac >= glseg.fracright) return; + + float fracfac = sidefrac - glseg.fracleft; + + ptr->x = cseg->v2->fx; + ptr->y = cseg->v2->fy; + ptr->z = ztop[0] + fact * fracfac; + ptr->u = tcs[1].u + facu * fracfac; + ptr->v = tcs[1].v + facv * fracfac; + ptr++; + } + vertexcount += sidedef->numsegs - 1; +} + //========================================================================== // // Split upper edge of wall @@ -121,6 +153,37 @@ void GLWall::SplitLowerEdge(texcoord * tcs) vertexcount += sidedef->numsegs-1; } +void GLWall::SplitLowerEdge(texcoord * tcs, FFlatVertex *&ptr) +{ + if (seg == NULL || seg->sidedef == NULL || (seg->sidedef->Flags & WALLF_POLYOBJ) || seg->sidedef->numsegs == 1) return; + + side_t *sidedef = seg->sidedef; + float polyw = glseg.fracright - glseg.fracleft; + float facu = (tcs[3].u - tcs[0].u) / polyw; + float facv = (tcs[3].v - tcs[0].v) / polyw; + float facb = (zbottom[1] - zbottom[0]) / polyw; + float facc = (zceil[1] - zceil[0]) / polyw; + float facf = (zfloor[1] - zfloor[0]) / polyw; + + for (int i = sidedef->numsegs - 2; i >= 0; i--) + { + seg_t *cseg = sidedef->segs[i]; + float sidefrac = cseg->sidefrac; + if (sidefrac >= glseg.fracright) continue; + if (sidefrac <= glseg.fracleft) return; + + float fracfac = sidefrac - glseg.fracleft; + + ptr->x = cseg->v2->fx; + ptr->y = cseg->v2->fy; + ptr->z = zbottom[0] + facb * fracfac; + ptr->u = tcs[0].u + facu * fracfac; + ptr->v = tcs[0].v + facv * fracfac; + ptr++; + } + vertexcount += sidedef->numsegs - 1; +} + //========================================================================== // // Split left edge of wall @@ -153,6 +216,35 @@ void GLWall::SplitLeftEdge(texcoord * tcs) } } +void GLWall::SplitLeftEdge(texcoord * tcs, FFlatVertex *&ptr) +{ + if (vertexes[0] == NULL) return; + + vertex_t * vi = vertexes[0]; + + if (vi->numheights) + { + int i = 0; + + float polyh1 = ztop[0] - zbottom[0]; + float factv1 = polyh1 ? (tcs[1].v - tcs[0].v) / polyh1 : 0; + float factu1 = polyh1 ? (tcs[1].u - tcs[0].u) / polyh1 : 0; + + while (inumheights && vi->heightlist[i] <= zbottom[0]) i++; + while (inumheights && vi->heightlist[i] < ztop[0]) + { + ptr->x = glseg.x1; + ptr->y = glseg.y1; + ptr->z = vi->heightlist[i]; + ptr->u = factu1*(vi->heightlist[i] - ztop[0]) + tcs[1].u; + ptr->v = factv1*(vi->heightlist[i] - ztop[0]) + tcs[1].v; + ptr++; + i++; + } + vertexcount += i; + } +} + //========================================================================== // // Split right edge of wall @@ -185,3 +277,32 @@ void GLWall::SplitRightEdge(texcoord * tcs) } } +void GLWall::SplitRightEdge(texcoord * tcs, FFlatVertex *&ptr) +{ + if (vertexes[1] == NULL) return; + + vertex_t * vi = vertexes[1]; + + if (vi->numheights) + { + int i = vi->numheights - 1; + + float polyh2 = ztop[1] - zbottom[1]; + float factv2 = polyh2 ? (tcs[2].v - tcs[3].v) / polyh2 : 0; + float factu2 = polyh2 ? (tcs[2].u - tcs[3].u) / polyh2 : 0; + + while (i>0 && vi->heightlist[i] >= ztop[1]) i--; + while (i>0 && vi->heightlist[i] > zbottom[1]) + { + ptr->x = glseg.x2; + ptr->y = glseg.y2; + ptr->z = vi->heightlist[i]; + ptr->u = factu2*(vi->heightlist[i] - ztop[1]) + tcs[2].u; + ptr->v = factv2*(vi->heightlist[i] - ztop[1]) + tcs[2].v; + ptr++; + i--; + } + vertexcount += i; + } +} + diff --git a/src/gl/scene/gl_wall.h b/src/gl/scene/gl_wall.h index e53513167..207b7bdbf 100644 --- a/src/gl/scene/gl_wall.h +++ b/src/gl/scene/gl_wall.h @@ -20,6 +20,7 @@ struct GLDrawList; struct GLSkyInfo; struct FTexCoordInfo; struct FPortal; +struct FFlatVertex; enum WallTypes @@ -215,6 +216,11 @@ private: void SplitUpperEdge(texcoord * tcs); void SplitLowerEdge(texcoord * tcs); + void SplitLeftEdge(texcoord * tcs, FFlatVertex *&ptr); + void SplitRightEdge(texcoord * tcs, FFlatVertex *&ptr); + void SplitUpperEdge(texcoord * tcs, FFlatVertex *&ptr); + void SplitLowerEdge(texcoord * tcs, FFlatVertex *&ptr); + public: void Process(seg_t *seg, sector_t *frontsector, sector_t *backsector); diff --git a/src/gl/scene/gl_walls_draw.cpp b/src/gl/scene/gl_walls_draw.cpp index d7edc6ef7..63e5086a7 100644 --- a/src/gl/scene/gl_walls_draw.cpp +++ b/src/gl/scene/gl_walls_draw.cpp @@ -48,7 +48,9 @@ #include "gl/system/gl_cvars.h" #include "gl/renderer/gl_lightdata.h" #include "gl/renderer/gl_renderstate.h" +#include "gl/renderer/gl_renderer.h" #include "gl/data/gl_data.h" +#include "gl/data/gl_vertexbuffer.h" #include "gl/dynlights/gl_dynlight.h" #include "gl/dynlights/gl_glow.h" #include "gl/scene/gl_drawinfo.h" @@ -248,38 +250,80 @@ void GLWall::RenderWall(int textured, float * color2, ADynamicLight * light) // the rest of the code is identical for textured rendering and lights - glBegin(GL_TRIANGLE_FAN); - // lower left corner - if (textured&1) glTexCoord2f(tcs[0].u,tcs[0].v); - glVertex3f(glseg.x1,zbottom[0],glseg.y1); + if (!gl_usevbo) + { + glBegin(GL_TRIANGLE_FAN); - if (split && glseg.fracleft==0) SplitLeftEdge(tcs); + // lower left corner + if (textured & 1) glTexCoord2f(tcs[0].u, tcs[0].v); + glVertex3f(glseg.x1, zbottom[0], glseg.y1); - // upper left corner - if (textured&1) glTexCoord2f(tcs[1].u,tcs[1].v); - glVertex3f(glseg.x1,ztop[0],glseg.y1); + if (split && glseg.fracleft == 0) SplitLeftEdge(tcs); - if (split && !(flags & GLWF_NOSPLITUPPER)) SplitUpperEdge(tcs); + // upper left corner + if (textured & 1) glTexCoord2f(tcs[1].u, tcs[1].v); + glVertex3f(glseg.x1, ztop[0], glseg.y1); - // color for right side - if (color2) glColor4fv(color2); + if (split && !(flags & GLWF_NOSPLITUPPER)) SplitUpperEdge(tcs); - // upper right corner - if (textured&1) glTexCoord2f(tcs[2].u,tcs[2].v); - glVertex3f(glseg.x2,ztop[1],glseg.y2); + // color for right side + if (color2) glColor4fv(color2); - if (split && glseg.fracright==1) SplitRightEdge(tcs); + // upper right corner + if (textured & 1) glTexCoord2f(tcs[2].u, tcs[2].v); + glVertex3f(glseg.x2, ztop[1], glseg.y2); - // lower right corner - if (textured&1) glTexCoord2f(tcs[3].u,tcs[3].v); - glVertex3f(glseg.x2,zbottom[1],glseg.y2); + if (split && glseg.fracright == 1) SplitRightEdge(tcs); - if (split && !(flags & GLWF_NOSPLITLOWER)) SplitLowerEdge(tcs); + // lower right corner + if (textured & 1) glTexCoord2f(tcs[3].u, tcs[3].v); + glVertex3f(glseg.x2, zbottom[1], glseg.y2); - glEnd(); + if (split && !(flags & GLWF_NOSPLITLOWER)) SplitLowerEdge(tcs); + + glEnd(); + + vertexcount += 4; + } + else + { + FFlatVertex *ptr = GLRenderer->mVBO->GetBuffer(); + + ptr->x = glseg.x1; + ptr->y = glseg.y1; + ptr->z = zbottom[0]; + ptr->u = tcs[0].u; + ptr->v = tcs[0].v; + ptr++; + if (split && glseg.fracleft == 0) SplitLeftEdge(tcs, ptr); + ptr->x = glseg.x1; + ptr->y = glseg.y1; + ptr->z = ztop[0]; + ptr->u = tcs[1].u; + ptr->v = tcs[1].v; + ptr++; + if (split && !(flags & GLWF_NOSPLITUPPER)) SplitUpperEdge(tcs, ptr); + ptr->x = glseg.x2; + ptr->y = glseg.y2; + ptr->z = ztop[1]; + ptr->u = tcs[2].u; + ptr->v = tcs[2].v; + ptr++; + if (split && glseg.fracright == 1) SplitRightEdge(tcs, ptr); + ptr->x = glseg.x2; + ptr->y = glseg.y2; + ptr->z = zbottom[1]; + ptr->u = tcs[3].u; + ptr->v = tcs[3].v; + ptr++; + if (split && !(flags & GLWF_NOSPLITLOWER)) SplitLowerEdge(tcs, ptr); + unsigned int offset; + unsigned int count = GLRenderer->mVBO->GetCount(ptr, &offset); + glDrawArrays(GL_TRIANGLE_FAN, offset, count); + vertexcount += 4; + } - vertexcount+=4; }