From 0d7c2527f2f2c6486e36507f65ffd55bc7a52e08 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 27 Apr 2018 20:18:52 +0200 Subject: [PATCH] - 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. --- src/gl/scene/gl_decal.cpp | 79 +++++++++++-------------- src/gl/scene/gl_drawinfo.cpp | 24 ++++---- src/gl/scene/gl_drawinfo.h | 9 +-- src/gl/scene/gl_scene.cpp | 13 +--- src/gl/scene/gl_walls_draw.cpp | 5 +- src/hwrenderer/scene/hw_drawinfo.h | 2 +- src/hwrenderer/scene/hw_drawstructs.h | 26 ++++++++ src/hwrenderer/scene/hw_walls.cpp | 1 + src/hwrenderer/textures/hw_ihwtexture.h | 2 + 9 files changed, 85 insertions(+), 76 deletions(-) diff --git a/src/gl/scene/gl_decal.cpp b/src/gl/scene/gl_decal.cpp index fa6f3dbba..cf5aa1f5f 100644 --- a/src/gl/scene/gl_decal.cpp +++ b/src/gl/scene/gl_decal.cpp @@ -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); } } } diff --git a/src/gl/scene/gl_drawinfo.cpp b/src/gl/scene/gl_drawinfo.cpp index 91c364544..8e04f7d8f 100644 --- a/src/gl/scene/gl_drawinfo.cpp +++ b/src/gl/scene/gl_drawinfo.cpp @@ -867,19 +867,6 @@ void GLDrawList::DrawFlats(int pass) RenderFlat.Unclock(); } -//========================================================================== -// -// -// -//========================================================================== -void GLDrawList::DrawDecals() -{ - for(unsigned i=0;iDoDrawDecals(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 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; +} + diff --git a/src/gl/scene/gl_drawinfo.h b/src/gl/scene/gl_drawinfo.h index ebedb94a2..32003d973 100644 --- a/src/gl/scene/gl_drawinfo.h +++ b/src/gl/scene/gl_drawinfo.h @@ -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 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); diff --git a/src/gl/scene/gl_scene.cpp b/src/gl/scene/gl_scene.cpp index 9e897c122..11d53cd5d 100644 --- a/src/gl/scene/gl_scene.cpp +++ b/src/gl/scene/gl_scene.cpp @@ -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(); } diff --git a/src/gl/scene/gl_walls_draw.cpp b/src/gl/scene/gl_walls_draw.cpp index 10318c425..5e17fffe0 100644 --- a/src/gl/scene/gl_walls_draw.cpp +++ b/src/gl/scene/gl_walls_draw.cpp @@ -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); diff --git a/src/hwrenderer/scene/hw_drawinfo.h b/src/hwrenderer/scene/hw_drawinfo.h index e2db5f132..ec4aaa31f 100644 --- a/src/hwrenderer/scene/hw_drawinfo.h +++ b/src/hwrenderer/scene/hw_drawinfo.h @@ -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 AllocVertices(unsigned int count) = 0; diff --git a/src/hwrenderer/scene/hw_drawstructs.h b/src/hwrenderer/scene/hw_drawstructs.h index a508b2a81..e4e9a2507 100644 --- a/src/hwrenderer/scene/hw_drawstructs.h +++ b/src/hwrenderer/scene/hw_drawstructs.h @@ -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)); diff --git a/src/hwrenderer/scene/hw_walls.cpp b/src/hwrenderer/scene/hw_walls.cpp index a9c0c0639..0ee2af2ee 100644 --- a/src/hwrenderer/scene/hw_walls.cpp +++ b/src/hwrenderer/scene/hw_walls.cpp @@ -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" diff --git a/src/hwrenderer/textures/hw_ihwtexture.h b/src/hwrenderer/textures/hw_ihwtexture.h index 681d6cca6..ca9d5bfad 100644 --- a/src/hwrenderer/textures/hw_ihwtexture.h +++ b/src/hwrenderer/textures/hw_ihwtexture.h @@ -1,8 +1,10 @@ #pragma once #include +#include "tarray.h" typedef TMap SpriteHits; +class FTexture; class IHardwareTexture {