- 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/scene/gl_scenedrawer.h"
#include "gl/renderer/gl_quaddrawer.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) void GLWall::ProcessDecal(HWDrawInfo *di, DBaseDecal *decal)
{ {
line_t * line = seg->linedef; line_t * line = seg->linedef;
@ -70,11 +48,11 @@ void GLWall::ProcessDecal(HWDrawInfo *di, DBaseDecal *decal)
float zpos; float zpos;
bool flipx, flipy; bool flipx, flipy;
FTextureID decalTile; FTextureID decalTile;
GLDecal gldecal;
if (decal->RenderFlags & RF_INVISIBLE) return; if (decal->RenderFlags & RF_INVISIBLE) return;
if (type == RENDERWALL_FFBLOCK && gltexture->isMasked()) return; // No decals on 3D floors with transparent textures. if (type == RENDERWALL_FFBLOCK && gltexture->isMasked()) return; // No decals on 3D floors with transparent textures.
if (seg == nullptr) return;
decalTile = decal->PicNum; decalTile = decal->PicNum;
@ -139,7 +117,7 @@ void GLWall::ProcessDecal(HWDrawInfo *di, DBaseDecal *decal)
} }
} }
memset(&gldecal, 0, sizeof(gldecal)); GLDecal &gldecal = *di->AddDecal(type == RENDERWALL_MIRRORSURFACE);
gldecal.gltexture = FMaterial::ValidateTexture(texture, true); gldecal.gltexture = FMaterial::ValidateTexture(texture, true);
gldecal.wall = this; gldecal.wall = this;
gldecal.decal = decal; 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); 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 wall = gldecal->wall;
auto decal = gldecal->decal; auto decal = gldecal->decal;
auto tex = gldecal->gltexture; 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); wall = gldecal->wall;
} if (wall->lightlist != nullptr)
else {
{ gl_RenderState.EnableSplit(true);
mDrawer->SetFog(wall->lightlevel, wall->rellight + getExtraLight(), &wall->Colormap, false); }
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); DrawDecal(gldecal);
decal = decal->WallNext;
}
if (wall->lightlist != nullptr)
{
gl_RenderState.EnableSplit(false);
} }
} }
} }

View file

@ -867,19 +867,6 @@ void GLDrawList::DrawFlats(int pass)
RenderFlat.Unclock(); 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. // Sorting the drawitems first by texture and then by light level.
@ -952,7 +939,6 @@ GLSprite *GLDrawList::NewSprite()
return sprite; return sprite;
} }
//========================================================================== //==========================================================================
// //
// Try to reuse the lists as often as possible as they contain resources that // 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(); 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); auto p = GLRenderer->mVBO->Alloc(count, &index);
return std::make_pair(p, 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 Draw(int pass, bool trans = false);
void DrawWalls(int pass); void DrawWalls(int pass);
void DrawFlats(int pass); void DrawFlats(int pass);
void DrawDecals();
GLDrawList * next; GLDrawList * next;
} ; } ;
@ -172,6 +171,7 @@ struct FDrawInfo : public HWDrawInfo
FDrawInfo * next; FDrawInfo * next;
GLDrawList drawlists[GLDL_TYPES]; 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. GLDrawList *dldrawlists = NULL; // only gets allocated when needed.
FDrawInfo(); FDrawInfo();
@ -179,6 +179,7 @@ struct FDrawInfo : public HWDrawInfo
void AddWall(GLWall *wall) override; void AddWall(GLWall *wall) override;
void AddMirrorSurface(GLWall *w) override; void AddMirrorSurface(GLWall *w) override;
GLDecal *AddDecal(bool onmirror) override;
void AddPortal(GLWall *w, int portaltype) override; void AddPortal(GLWall *w, int portaltype) override;
void ProcessActorsInPortal(FLinePortalSpan *glport) override; void ProcessActorsInPortal(FLinePortalSpan *glport) override;
@ -189,9 +190,9 @@ struct FDrawInfo : public HWDrawInfo
void RenderFogBoundaryCompat(GLWall *wall); void RenderFogBoundaryCompat(GLWall *wall);
void RenderLightsCompat(GLWall *wall, int pass); void RenderLightsCompat(GLWall *wall, int pass);
void DrawDecal(GLWall *wall, DBaseDecal *decal); void DrawDecal(GLDecal *gldecal);
void DoDrawDecals(GLWall *wall); void DrawDecals();
void DrawDecalsForMirror(GLWall *wall);
void StartScene(); void StartScene();
void SetupFloodStencil(wallseg * ws); void SetupFloodStencil(wallseg * ws);

View file

@ -375,15 +375,7 @@ void GLSceneDrawer::RenderScene(int recursion)
glEnable(GL_POLYGON_OFFSET_FILL); glEnable(GL_POLYGON_OFFSET_FILL);
glPolygonOffset(-1.0f, -128.0f); glPolygonOffset(-1.0f, -128.0f);
glDepthMask(false); glDepthMask(false);
gl_drawinfo->DrawDecals();
// 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_RenderState.SetTextureMode(TM_MODULATE); gl_RenderState.SetTextureMode(TM_MODULATE);
@ -434,9 +426,10 @@ void GLSceneDrawer::RenderTranslucent()
gl_drawinfo->drawlists[GLDL_TRANSLUCENT].DrawSorted(); gl_drawinfo->drawlists[GLDL_TRANSLUCENT].DrawSorted();
gl_RenderState.EnableBrightmap(false); gl_RenderState.EnableBrightmap(false);
glDepthMask(true);
gl_RenderState.AlphaFunc(GL_GEQUAL, 0.5f); gl_RenderState.AlphaFunc(GL_GEQUAL, 0.5f);
glDepthMask(true);
RenderAll.Unclock(); RenderAll.Unclock();
} }

View file

@ -139,13 +139,14 @@ void FDrawInfo::RenderMirrorSurface(GLWall *wall)
glDepthFunc(GL_LESS); glDepthFunc(GL_LESS);
// This is drawn in the translucent pass which is done after the decal pass // 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) if (wall->seg->sidedef->AttachedDecals)
{ {
glEnable(GL_POLYGON_OFFSET_FILL); glEnable(GL_POLYGON_OFFSET_FILL);
glPolygonOffset(-1.0f, -128.0f); glPolygonOffset(-1.0f, -128.0f);
glDepthMask(false); glDepthMask(false);
gl_drawinfo->DoDrawDecals(wall); gl_drawinfo->DrawDecalsForMirror(wall);
glDepthMask(true); glDepthMask(true);
glPolygonOffset(0.0f, 0.0f); glPolygonOffset(0.0f, 0.0f);
glDisable(GL_POLYGON_OFFSET_FILL); glDisable(GL_POLYGON_OFFSET_FILL);

View file

@ -128,7 +128,7 @@ public:
virtual void AddWall(GLWall *w) = 0; virtual void AddWall(GLWall *w) = 0;
virtual void AddPortal(GLWall *w, int portaltype) = 0; virtual void AddPortal(GLWall *w, int portaltype) = 0;
virtual void AddMirrorSurface(GLWall *w) = 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 void ProcessActorsInPortal(FLinePortalSpan *glport) = 0;
virtual std::pair<FFlatVertex *, unsigned int> AllocVertices(unsigned int count) = 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) inline float Dist2(float x1,float y1,float x2,float y2)
{ {
return sqrtf((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)); return sqrtf((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));

View file

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

View file

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