- add vertex buffer based drawing for all walls and flats.

This commit is contained in:
Christoph Oelckers 2014-05-11 01:23:27 +02:00
parent 7d3beb665b
commit f7404d20fb
7 changed files with 273 additions and 30 deletions

View file

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

View file

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

View file

@ -238,21 +238,72 @@ bool GLFlat::SetupSubsectorLights(bool lightsapplied, subsector_t * sub)
void GLFlat::DrawSubsector(subsector_t * sub)
{
if (!gl_usevbo)
{
glBegin(GL_TRIANGLE_FAN);
for(unsigned int k=0; k<sub->numlines; k++)
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);
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);
}
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; i<sector->subsectorcount; i++)
{

View file

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

View file

@ -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 (i<vi->numheights && vi->heightlist[i] <= zbottom[0]) i++;
while (i<vi->numheights && 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;
}
}

View file

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

View file

@ -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,17 +250,20 @@ void GLWall::RenderWall(int textured, float * color2, ADynamicLight * light)
// the rest of the code is identical for textured rendering and lights
if (!gl_usevbo)
{
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 (textured & 1) glTexCoord2f(tcs[0].u, tcs[0].v);
glVertex3f(glseg.x1, zbottom[0], glseg.y1);
if (split && glseg.fracleft==0) SplitLeftEdge(tcs);
if (split && glseg.fracleft == 0) SplitLeftEdge(tcs);
// upper left corner
if (textured&1) glTexCoord2f(tcs[1].u,tcs[1].v);
glVertex3f(glseg.x1,ztop[0],glseg.y1);
if (textured & 1) glTexCoord2f(tcs[1].u, tcs[1].v);
glVertex3f(glseg.x1, ztop[0], glseg.y1);
if (split && !(flags & GLWF_NOSPLITUPPER)) SplitUpperEdge(tcs);
@ -266,20 +271,59 @@ void GLWall::RenderWall(int textured, float * color2, ADynamicLight * light)
if (color2) glColor4fv(color2);
// upper right corner
if (textured&1) glTexCoord2f(tcs[2].u,tcs[2].v);
glVertex3f(glseg.x2,ztop[1],glseg.y2);
if (textured & 1) glTexCoord2f(tcs[2].u, tcs[2].v);
glVertex3f(glseg.x2, ztop[1], glseg.y2);
if (split && glseg.fracright==1) SplitRightEdge(tcs);
if (split && glseg.fracright == 1) SplitRightEdge(tcs);
// lower right corner
if (textured&1) glTexCoord2f(tcs[3].u,tcs[3].v);
glVertex3f(glseg.x2,zbottom[1],glseg.y2);
if (textured & 1) glTexCoord2f(tcs[3].u, tcs[3].v);
glVertex3f(glseg.x2, zbottom[1], glseg.y2);
if (split && !(flags & GLWF_NOSPLITLOWER)) SplitLowerEdge(tcs);
glEnd();
vertexcount+=4;
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;
}
}