- finished decal render refactoring.

Decals will now be processed into a list in the processing pass, allowing to use the vertex buffer even on GL3 hardware and to offload this part of the work to a multithreaded worker task.
This commit is contained in:
Christoph Oelckers 2018-04-27 20:18:52 +02:00
parent 1ae2f06161
commit 0d7c2527f2
9 changed files with 85 additions and 76 deletions

View File

@ -40,28 +40,6 @@
#include "gl/scene/gl_scenedrawer.h"
#include "gl/renderer/gl_quaddrawer.h"
struct DecalVertex
{
float x,y,z;
float u,v;
};
struct GLDecal
{
unsigned int vertindex;
FMaterial *gltexture;
GLWall *wall;
DBaseDecal *decal;
DecalVertex dv[4];
float zcenter;
int light;
int rel;
float a;
FColormap colormap;
};
void GLWall::ProcessDecal(HWDrawInfo *di, DBaseDecal *decal)
{
line_t * line = seg->linedef;
@ -70,11 +48,11 @@ void GLWall::ProcessDecal(HWDrawInfo *di, DBaseDecal *decal)
float zpos;
bool flipx, flipy;
FTextureID decalTile;
GLDecal gldecal;
if (decal->RenderFlags & RF_INVISIBLE) return;
if (type == RENDERWALL_FFBLOCK && gltexture->isMasked()) return; // No decals on 3D floors with transparent textures.
if (seg == nullptr) return;
decalTile = decal->PicNum;
@ -138,8 +116,8 @@ void GLWall::ProcessDecal(HWDrawInfo *di, DBaseDecal *decal)
zpos = decal->Z + frontsector->GetPlaneTexZ(sector_t::ceiling);
}
}
memset(&gldecal, 0, sizeof(gldecal));
GLDecal &gldecal = *di->AddDecal(type == RENDERWALL_MIRRORSURFACE);
gldecal.gltexture = FMaterial::ValidateTexture(texture, true);
gldecal.wall = this;
gldecal.decal = decal;
@ -286,7 +264,6 @@ void GLWall::ProcessDecal(HWDrawInfo *di, DBaseDecal *decal)
{
verts.first[i].Set(dv[i].x, dv[i].z, dv[i].y, dv[i].u, dv[i].v);
}
di->AddDecal(&gldecal);
}
//==========================================================================
@ -312,9 +289,8 @@ void GLWall::ProcessDecals(HWDrawInfo *di)
//
//
//==========================================================================
void FDrawInfo::DrawDecal(GLWall *__wall, DBaseDecal *__decal)
void FDrawInfo::DrawDecal(GLDecal *gldecal)
{
GLDecal *gldecal;
auto wall = gldecal->wall;
auto decal = gldecal->decal;
auto tex = gldecal->gltexture;
@ -401,29 +377,42 @@ void FDrawInfo::DrawDecal(GLWall *__wall, DBaseDecal *__decal)
//
//
//==========================================================================
void FDrawInfo::DoDrawDecals(GLWall *wall)
void FDrawInfo::DrawDecals()
{
if (wall->seg->sidedef && wall->seg->sidedef->AttachedDecals)
GLWall *wall = nullptr;
for (auto gldecal : decals[0])
{
if (wall->lightlist != nullptr)
if (gldecal->wall != wall)
{
gl_RenderState.EnableSplit(true);
}
else
{
mDrawer->SetFog(wall->lightlevel, wall->rellight + getExtraLight(), &wall->Colormap, false);
wall = gldecal->wall;
if (wall->lightlist != nullptr)
{
gl_RenderState.EnableSplit(true);
}
else
{
gl_RenderState.EnableSplit(false);
mDrawer->SetFog(wall->lightlevel, wall->rellight + getExtraLight(), &wall->Colormap, false);
}
}
DrawDecal(gldecal);
}
if (wall && wall->lightlist != nullptr) gl_RenderState.EnableSplit(false);
}
DBaseDecal *decal = wall->seg->sidedef->AttachedDecals;
while (decal)
//==========================================================================
//
// This list will never get long, so this code should be ok.
//
//==========================================================================
void FDrawInfo::DrawDecalsForMirror(GLWall *wall)
{
mDrawer->SetFog(wall->lightlevel, wall->rellight + getExtraLight(), &wall->Colormap, false);
for (auto gldecal : decals[1])
{
if (gldecal->wall == wall)
{
DrawDecal(wall, decal);
decal = decal->WallNext;
}
if (wall->lightlist != nullptr)
{
gl_RenderState.EnableSplit(false);
DrawDecal(gldecal);
}
}
}

View File

@ -867,19 +867,6 @@ void GLDrawList::DrawFlats(int pass)
RenderFlat.Unclock();
}
//==========================================================================
//
//
//
//==========================================================================
void GLDrawList::DrawDecals()
{
for(unsigned i=0;i<drawitems.Size();i++)
{
gl_drawinfo->DoDrawDecals(walls[drawitems[i].index]);
}
}
//==========================================================================
//
// Sorting the drawitems first by texture and then by light level.
@ -952,7 +939,6 @@ GLSprite *GLDrawList::NewSprite()
return sprite;
}
//==========================================================================
//
// Try to reuse the lists as often as possible as they contain resources that
@ -1033,6 +1019,8 @@ void FDrawInfo::StartScene()
{
for (int i = 0; i < GLLDL_TYPES; i++) dldrawlists[i].Reset();
}
decals[0].Clear();
decals[1].Clear();
}
//==========================================================================
@ -1323,3 +1311,11 @@ std::pair<FFlatVertex *, unsigned int> FDrawInfo::AllocVertices(unsigned int cou
auto p = GLRenderer->mVBO->Alloc(count, &index);
return std::make_pair(p, index);
}
GLDecal *FDrawInfo::AddDecal(bool onmirror)
{
auto decal = (GLDecal*)RenderDataAllocator.Alloc(sizeof(GLDecal));
decals[onmirror ? 1 : 0].Push(decal);
return decal;
}

View File

@ -158,7 +158,6 @@ public:
void Draw(int pass, bool trans = false);
void DrawWalls(int pass);
void DrawFlats(int pass);
void DrawDecals();
GLDrawList * next;
} ;
@ -172,6 +171,7 @@ struct FDrawInfo : public HWDrawInfo
FDrawInfo * next;
GLDrawList drawlists[GLDL_TYPES];
TArray<GLDecal *> decals[2]; // the second slot is for mirrors which get rendered in a separate pass.
GLDrawList *dldrawlists = NULL; // only gets allocated when needed.
FDrawInfo();
@ -179,6 +179,7 @@ struct FDrawInfo : public HWDrawInfo
void AddWall(GLWall *wall) override;
void AddMirrorSurface(GLWall *w) override;
GLDecal *AddDecal(bool onmirror) override;
void AddPortal(GLWall *w, int portaltype) override;
void ProcessActorsInPortal(FLinePortalSpan *glport) override;
@ -189,10 +190,10 @@ struct FDrawInfo : public HWDrawInfo
void RenderFogBoundaryCompat(GLWall *wall);
void RenderLightsCompat(GLWall *wall, int pass);
void DrawDecal(GLWall *wall, DBaseDecal *decal);
void DoDrawDecals(GLWall *wall);
void DrawDecal(GLDecal *gldecal);
void DrawDecals();
void DrawDecalsForMirror(GLWall *wall);
void StartScene();
void SetupFloodStencil(wallseg * ws);
void ClearFloodStencil(wallseg * ws);

View File

@ -375,15 +375,7 @@ void GLSceneDrawer::RenderScene(int recursion)
glEnable(GL_POLYGON_OFFSET_FILL);
glPolygonOffset(-1.0f, -128.0f);
glDepthMask(false);
// this is the only geometry type on which decals can possibly appear
gl_drawinfo->drawlists[GLDL_PLAINWALLS].DrawDecals();
if (gl.legacyMode)
{
// also process the render lists with walls and dynamic lights
gl_drawinfo->dldrawlists[GLLDL_WALLS_PLAIN].DrawDecals();
gl_drawinfo->dldrawlists[GLLDL_WALLS_FOG].DrawDecals();
}
gl_drawinfo->DrawDecals();
gl_RenderState.SetTextureMode(TM_MODULATE);
@ -434,9 +426,10 @@ void GLSceneDrawer::RenderTranslucent()
gl_drawinfo->drawlists[GLDL_TRANSLUCENT].DrawSorted();
gl_RenderState.EnableBrightmap(false);
glDepthMask(true);
gl_RenderState.AlphaFunc(GL_GEQUAL, 0.5f);
glDepthMask(true);
RenderAll.Unclock();
}

View File

@ -139,13 +139,14 @@ void FDrawInfo::RenderMirrorSurface(GLWall *wall)
glDepthFunc(GL_LESS);
// This is drawn in the translucent pass which is done after the decal pass
// As a result the decals have to be drawn here.
// As a result the decals have to be drawn here, right after the wall they are on,
// because the depth buffer won't get set by translucent items.
if (wall->seg->sidedef->AttachedDecals)
{
glEnable(GL_POLYGON_OFFSET_FILL);
glPolygonOffset(-1.0f, -128.0f);
glDepthMask(false);
gl_drawinfo->DoDrawDecals(wall);
gl_drawinfo->DrawDecalsForMirror(wall);
glDepthMask(true);
glPolygonOffset(0.0f, 0.0f);
glDisable(GL_POLYGON_OFFSET_FILL);

View File

@ -128,7 +128,7 @@ public:
virtual void AddWall(GLWall *w) = 0;
virtual void AddPortal(GLWall *w, int portaltype) = 0;
virtual void AddMirrorSurface(GLWall *w) = 0;
virtual void AddDecal(GLDecal *d) = 0;
virtual GLDecal *AddDecal(bool onmirror) = 0;
virtual void ProcessActorsInPortal(FLinePortalSpan *glport) = 0;
virtual std::pair<FFlatVertex *, unsigned int> AllocVertices(unsigned int count) = 0;

View File

@ -281,6 +281,32 @@ public:
};
struct DecalVertex
{
float x, y, z;
float u, v;
};
struct GLDecal
{
FMaterial *gltexture;
GLWall *wall;
DBaseDecal *decal;
DecalVertex dv[4];
float zcenter;
unsigned int vertindex;
int light;
int rel;
float a;
FColormap colormap;
};
inline float Dist2(float x1,float y1,float x2,float y2)
{
return sqrtf((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));

View File

@ -29,6 +29,7 @@
#include "p_maputl.h"
#include "doomdata.h"
#include "g_levellocals.h"
#include "actorinlines.h"
#include "hwrenderer/dynlights/hw_dynlightdata.h"
#include "hwrenderer/textures/hw_material.h"
#include "hwrenderer/utility/hw_cvars.h"

View File

@ -1,8 +1,10 @@
#pragma once
#include <stdint.h>
#include "tarray.h"
typedef TMap<int, bool> SpriteHits;
class FTexture;
class IHardwareTexture
{