From 9d13e6b7eca7c687af6d8154a711066ed8e395fe Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 27 Apr 2018 00:31:00 +0200 Subject: [PATCH 01/12] - gl_colormap.h is no longer needed. --- src/gl/renderer/gl_colormap.h | 30 ------------------------------ 1 file changed, 30 deletions(-) delete mode 100644 src/gl/renderer/gl_colormap.h diff --git a/src/gl/renderer/gl_colormap.h b/src/gl/renderer/gl_colormap.h deleted file mode 100644 index 46e36431e..000000000 --- a/src/gl/renderer/gl_colormap.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef __GL_COLORMAP -#define __GL_COLORMAP - -#include "doomtype.h" -#include "v_palette.h" -#include "r_data/colormaps.h" - -struct lightlist_t; - -enum EColorManipulation -{ - CM_SPECIAL2D = -3, // the special colormaps get passed as color pair from the 2D drawer so they need a different value here. - CM_PLAIN2D = -2, // regular 2D drawing. - CM_INVALID=-1, - CM_DEFAULT=0, // untranslated - CM_FIRSTSPECIALCOLORMAP, // first special fixed colormap - CM_FIRSTSPECIALCOLORMAPFORCED= 0x08000000, // first special fixed colormap, application forced (for 2D overlays) - - CM_FOGLAYER = 0x10000000, // Sprite shaped fog layer - - // These are not to be passed to the texture manager - CM_LITE = 0x20000000, // special values to handle these items without excessive hacking - CM_TORCH= 0x20000010, // These are not real color manipulations -}; - -#define CM_MAXCOLORMAP int(CM_FIRSTSPECIALCOLORMAP + SpecialColormaps.Size()) -#define CM_MAXCOLORMAPFORCED int(CM_FIRSTSPECIALCOLORMAPFORCED + SpecialColormaps.Size()) - - -#endif From 0dc82fe75556ddfb5cd4a4d1eadcdde523660cb7 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 27 Apr 2018 00:53:58 +0200 Subject: [PATCH 02/12] - header cleanup for gl_swscene. --- src/gl/scene/gl_swscene.cpp | 8 ++++---- src/gl/scene/gl_swscene.h | 9 --------- 2 files changed, 4 insertions(+), 13 deletions(-) diff --git a/src/gl/scene/gl_swscene.cpp b/src/gl/scene/gl_swscene.cpp index 4281a2cc9..965a2f8dd 100644 --- a/src/gl/scene/gl_swscene.cpp +++ b/src/gl/scene/gl_swscene.cpp @@ -25,17 +25,17 @@ ** */ -#include "gl/system/gl_system.h" -#include "gl/system/gl_debug.h" -#include "gl/data/gl_vertexbuffer.h" -#include "gl/shaders/gl_shader.h" #include "hwrenderer/textures/hw_ihwtexture.h" +#include "hwrenderer/textures/hw_material.h" +#include "r_renderer.h" #include "gl_swscene.h" #include "w_wad.h" #include "d_player.h" #include "textures/bitmap.h" #include "swrenderer/scene/r_light.h" +#include "gl/renderer/gl_renderer.h" + // [RH] Base blending values (for e.g. underwater) int BaseBlendR, BaseBlendG, BaseBlendB; float BaseBlendA; diff --git a/src/gl/scene/gl_swscene.h b/src/gl/scene/gl_swscene.h index f4fbb00a3..f54b2f3ed 100644 --- a/src/gl/scene/gl_swscene.h +++ b/src/gl/scene/gl_swscene.h @@ -4,9 +4,6 @@ #include "r_defs.h" #include "m_fixed.h" #include "hwrenderer/scene/hw_clipper.h" -#include "gl_portal.h" -#include "gl/renderer/gl_lightdata.h" -#include "gl/renderer/gl_renderer.h" #include "r_utility.h" #include "c_cvars.h" @@ -18,12 +15,6 @@ class SWSceneDrawer FSWSceneTexture *FBTexture = nullptr; bool FBIsTruecolor = false; - - void BlendView (player_t *CPlayer, float blend[4]); - bool CreateResources(); - void BindFBBuffer(); - - public: SWSceneDrawer(); ~SWSceneDrawer(); From 286846a8ec7ab33e69ea25abc285a8048ac7f5f9 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 27 Apr 2018 08:59:59 +0200 Subject: [PATCH 03/12] 2D must consider brightmaps. --- wadsrc/static/shaders/glsl/main.fp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wadsrc/static/shaders/glsl/main.fp b/wadsrc/static/shaders/glsl/main.fp index a90141d0d..ddd1f1439 100644 --- a/wadsrc/static/shaders/glsl/main.fp +++ b/wadsrc/static/shaders/glsl/main.fp @@ -504,7 +504,7 @@ void main() case 4: // simple 2D (reuses a uniform for the special colormap for the color overlay.) { - frag = frag * vColor; + frag = frag * ProcessLight(vColor); frag.rgb = frag.rgb + uFixedColormapStart.rgb; break; } From fbcf2033c609134b4a445e32a4d233ca7cd8dd84 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 27 Apr 2018 09:34:02 +0200 Subject: [PATCH 04/12] Corrected render style definition --- src/r_data/renderstyle.cpp | 3 ++- src/r_data/renderstyle.h | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/r_data/renderstyle.cpp b/src/r_data/renderstyle.cpp index 9b0569ea4..7c27e822c 100644 --- a/src/r_data/renderstyle.cpp +++ b/src/r_data/renderstyle.cpp @@ -58,7 +58,8 @@ FRenderStyle LegacyRenderStyles[STYLE_Count] = { { STYLEOP_RevSub, STYLEALPHA_Src, STYLEALPHA_One, 0 } }, /* STYLE_Subtract*/ { { STYLEOP_Add, STYLEALPHA_Src, STYLEALPHA_One, STYLEF_ColorIsFixed } }, /* STYLE_AddStencil */ { { STYLEOP_Add, STYLEALPHA_Src, STYLEALPHA_One, STYLEF_RedIsAlpha | STYLEF_ColorIsFixed } }, /* STYLE_AddShaded */ - { { STYLEOP_Add, STYLEALPHA_InvDstCol, STYLEALPHA_Zero, 0 } }, /* STYLE_Multiply */ + { { STYLEOP_Add, STYLEALPHA_DstCol, STYLEALPHA_Zero, 0 } }, /* STYLE_Multiply */ + { { STYLEOP_Add, STYLEALPHA_InvDstCol, STYLEALPHA_Zero, 0 } }, /* STYLE_InverseMultiply */ }; double GetAlpha(int type, double alpha) diff --git a/src/r_data/renderstyle.h b/src/r_data/renderstyle.h index d5393f487..04970f962 100644 --- a/src/r_data/renderstyle.h +++ b/src/r_data/renderstyle.h @@ -62,6 +62,7 @@ enum ERenderStyle STYLE_AddStencil, // Fill image interior with alphacolor STYLE_AddShaded, // Treat patch data as alpha values for alphacolor STYLE_Multiply, // Multiply source with destination (HW renderer only.) + STYLE_InverseMultiply, // Multiply source with inverse of destination (HW renderer only.) STYLE_Count }; From 90a1614ac8e7e3f19c865f4eb2b9676d79acb502 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 27 Apr 2018 09:34:43 +0200 Subject: [PATCH 05/12] The intermission drawer doesn't need to check the return of Begin2D anymore --- src/intermission/intermission.cpp | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/src/intermission/intermission.cpp b/src/intermission/intermission.cpp index 615f79fae..115084637 100644 --- a/src/intermission/intermission.cpp +++ b/src/intermission/intermission.cpp @@ -229,21 +229,14 @@ void DIntermissionScreenFader::Drawer () if (mType == FADE_In) factor = 1.0 - factor; int color = MAKEARGB(int(factor*255), 0,0,0); - if (screen->Begin2D(false)) + screen->Begin2D(false); + screen->DrawTexture (TexMan[mBackground], 0, 0, DTA_Fullscreen, true, DTA_ColorOverlay, color, TAG_DONE); + for (unsigned i=0; i < mOverlays.Size(); i++) { - screen->DrawTexture (TexMan[mBackground], 0, 0, DTA_Fullscreen, true, DTA_ColorOverlay, color, TAG_DONE); - for (unsigned i=0; i < mOverlays.Size(); i++) - { - if (CheckOverlay(i)) - screen->DrawTexture (TexMan[mOverlays[i].mPic], mOverlays[i].x, mOverlays[i].y, DTA_320x200, true, DTA_ColorOverlay, color, TAG_DONE); - } - screen->FillBorder (NULL); - } - else - { - V_SetBlend (0,0,0,int(256*factor)); - Super::Drawer(); + if (CheckOverlay(i)) + screen->DrawTexture (TexMan[mOverlays[i].mPic], mOverlays[i].x, mOverlays[i].y, DTA_320x200, true, DTA_ColorOverlay, color, TAG_DONE); } + screen->FillBorder (NULL); } } From bbea6e7e3ca2aab2cfbd6a4f0fa7309845ecfdf8 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 27 Apr 2018 09:58:19 +0200 Subject: [PATCH 06/12] Begin2D doesn't need a return type anymore This was to tell the caller that software 2D was in use, but that doesn't exist anymore --- src/gl/scene/gl_wall.h | 2 ++ src/gl/scene/gl_walls_draw.cpp | 2 +- src/gl/system/gl_framebuffer.cpp | 4 +--- src/gl/system/gl_framebuffer.h | 2 +- src/hwrenderer/scene/hw_drawstructs.h | 2 ++ src/v_video.cpp | 3 +-- src/v_video.h | 2 +- 7 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/gl/scene/gl_wall.h b/src/gl/scene/gl_wall.h index 38ff975ab..504c6f21c 100644 --- a/src/gl/scene/gl_wall.h +++ b/src/gl/scene/gl_wall.h @@ -11,7 +11,9 @@ #include "r_data/colormaps.h" #include "hwrenderer/scene/hw_drawstructs.h" +#ifdef _MSC_VER #pragma warning(disable:4244) +#endif struct GLHorizonInfo; struct F3DFloor; diff --git a/src/gl/scene/gl_walls_draw.cpp b/src/gl/scene/gl_walls_draw.cpp index 33d050805..de2e9a657 100644 --- a/src/gl/scene/gl_walls_draw.cpp +++ b/src/gl/scene/gl_walls_draw.cpp @@ -153,7 +153,7 @@ bool GLWall::SetupLights(FDynLightData &lightdata) void FDrawInfo::RenderWall(GLWall *wall, int textured) { - assert(vertcount > 0); + assert(wall->vertcount > 0); gl_RenderState.Apply(); gl_RenderState.ApplyLightIndex(wall->dynlightindex); GLRenderer->mVBO->RenderArray(GL_TRIANGLE_FAN, wall->vertindex, wall->vertcount); diff --git a/src/gl/system/gl_framebuffer.cpp b/src/gl/system/gl_framebuffer.cpp index a66f10291..e7844a219 100644 --- a/src/gl/system/gl_framebuffer.cpp +++ b/src/gl/system/gl_framebuffer.cpp @@ -481,10 +481,9 @@ void OpenGLFrameBuffer::SetClearColor(int color) // // //========================================================================== -bool OpenGLFrameBuffer::Begin2D(bool copy3d) +void OpenGLFrameBuffer::Begin2D(bool copy3d) { Super::Begin2D(copy3d); - ClearClipRect(); gl_RenderState.mViewMatrix.loadIdentity(); gl_RenderState.mProjectionMatrix.ortho(0, GetWidth(), GetHeight(), 0, -1.0f, 1.0f); gl_RenderState.ApplyMatrices(); @@ -503,7 +502,6 @@ bool OpenGLFrameBuffer::Begin2D(bool copy3d) if (GLRenderer != NULL) GLRenderer->Begin2D(); - return true; } //=========================================================================== diff --git a/src/gl/system/gl_framebuffer.h b/src/gl/system/gl_framebuffer.h index 6410a3443..0be4428f2 100644 --- a/src/gl/system/gl_framebuffer.h +++ b/src/gl/system/gl_framebuffer.h @@ -34,7 +34,7 @@ public: PalEntry *GetPalette () override; bool SetFlash(PalEntry rgb, int amount) override; void GetFlash(PalEntry &rgb, int &amount) override; - bool Begin2D(bool copy3d) override; + void Begin2D(bool copy3d) override; void GameRestart() override; void InitForLevel() override; void SetClearColor(int color) override; diff --git a/src/hwrenderer/scene/hw_drawstructs.h b/src/hwrenderer/scene/hw_drawstructs.h index 56f9d9389..262e5ed05 100644 --- a/src/hwrenderer/scene/hw_drawstructs.h +++ b/src/hwrenderer/scene/hw_drawstructs.h @@ -9,7 +9,9 @@ #include "textures/textures.h" #include "r_data/colormaps.h" +#ifdef _MSC_VER #pragma warning(disable:4244) +#endif struct GLHorizonInfo; struct GLSkyInfo; diff --git a/src/v_video.cpp b/src/v_video.cpp index b6d8a1213..5c0395331 100644 --- a/src/v_video.cpp +++ b/src/v_video.cpp @@ -859,11 +859,10 @@ void DFrameBuffer::SetBlendingRect (int x1, int y1, int x2, int y2) // //========================================================================== -bool DFrameBuffer::Begin2D (bool copy3d) +void DFrameBuffer::Begin2D (bool copy3d) { isIn2D = true; ClearClipRect(); - return false; } //========================================================================== diff --git a/src/v_video.h b/src/v_video.h index f2c8a711b..b976e5415 100644 --- a/src/v_video.h +++ b/src/v_video.h @@ -385,7 +385,7 @@ public: // Begin 2D drawing operations. // Returns true if hardware-accelerated 2D has been entered, false if not. - virtual bool Begin2D(bool copy3d); + virtual void Begin2D(bool copy3d); void End2D() { isIn2D = false; } // Returns true if Begin2D has been called and 2D drawing is now active From 200848a4873702f2b9ec83ac18b7cf5feda39004 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 27 Apr 2018 11:40:23 +0200 Subject: [PATCH 07/12] Decal work. Not finished yet. --- src/gl/compatibility/gl_20.cpp | 1 + src/gl/scene/gl_decal.cpp | 297 ++++++++++++++------------ src/gl/scene/gl_wall.h | 2 +- src/gl/scene/gl_walls_draw.cpp | 2 + src/hwrenderer/scene/hw_drawinfo.h | 2 + src/hwrenderer/scene/hw_drawstructs.h | 2 + 6 files changed, 173 insertions(+), 133 deletions(-) diff --git a/src/gl/compatibility/gl_20.cpp b/src/gl/compatibility/gl_20.cpp index 57405e4ab..1c99b1825 100644 --- a/src/gl/compatibility/gl_20.cpp +++ b/src/gl/compatibility/gl_20.cpp @@ -555,6 +555,7 @@ bool FDrawInfo::PutWallCompat(GLWall *wall, int passflag) int list = list_indices[masked][foggy]; auto newwall = dldrawlists[list].NewWall(); *newwall = *wall; + if (!masked) newwall->ProcessDecals(this); return true; } diff --git a/src/gl/scene/gl_decal.cpp b/src/gl/scene/gl_decal.cpp index 0dd0b91f3..fa6f3dbba 100644 --- a/src/gl/scene/gl_decal.cpp +++ b/src/gl/scene/gl_decal.cpp @@ -46,143 +46,141 @@ struct DecalVertex float u,v; }; -//========================================================================== -// -// -// -//========================================================================== -void FDrawInfo::DrawDecal(GLWall *wall, DBaseDecal *decal) +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) { - auto seg = wall->seg; line_t * line = seg->linedef; side_t * side = seg->sidedef; int i; float zpos; - int light; - int rel; - float a; bool flipx, flipy; - DecalVertex dv[4]; FTextureID decalTile; - - + GLDecal gldecal; + + if (decal->RenderFlags & RF_INVISIBLE) return; - if (wall->type == RENDERWALL_FFBLOCK && wall->gltexture->isMasked()) return; // No decals on 3D floors with transparent textures. - - //if (decal->sprite != 0xffff) - { - decalTile = decal->PicNum; - flipx = !!(decal->RenderFlags & RF_XFLIP); - flipy = !!(decal->RenderFlags & RF_YFLIP); - } - /* - else - { - decalTile = SpriteFrames[sprites[decal->sprite].spriteframes + decal->frame].lump[0]; - flipx = SpriteFrames[sprites[decal->sprite].spriteframes + decal->frame].flip & 1; - } - */ + if (type == RENDERWALL_FFBLOCK && gltexture->isMasked()) return; // No decals on 3D floors with transparent textures. + + + decalTile = decal->PicNum; + flipx = !!(decal->RenderFlags & RF_XFLIP); + flipy = !!(decal->RenderFlags & RF_YFLIP); + FTexture *texture = TexMan[decalTile]; if (texture == NULL) return; - FMaterial *tex; - - - tex = FMaterial::ValidateTexture(texture, true); - - + // the sectors are only used for their texture origin coordinates // so we don't need the fake sectors for deep water etc. // As this is a completely split wall fragment no further splits are // necessary for the decal. sector_t *frontsector; - + // for 3d-floor segments use the model sector as reference if ((decal->RenderFlags&RF_CLIPMASK) == RF_CLIPMID) frontsector = decal->Sector; else frontsector = seg->frontsector; - + switch (decal->RenderFlags & RF_RELMASK) { - default: - // No valid decal can have this type. If one is encountered anyway - // it is in some way invalid so skip it. - return; - //zpos = decal->z; - //break; - - case RF_RELUPPER: - if (wall->type != RENDERWALL_TOP) return; - if (line->flags & ML_DONTPEGTOP) - { - zpos = decal->Z + frontsector->GetPlaneTexZ(sector_t::ceiling); - } - else - { - zpos = decal->Z + seg->backsector->GetPlaneTexZ(sector_t::ceiling); - } - break; - case RF_RELLOWER: - if (wall->type != RENDERWALL_BOTTOM) return; - if (line->flags & ML_DONTPEGBOTTOM) - { - zpos = decal->Z + frontsector->GetPlaneTexZ(sector_t::ceiling); - } - else - { - zpos = decal->Z + seg->backsector->GetPlaneTexZ(sector_t::floor); - } - break; - case RF_RELMID: - if (wall->type == RENDERWALL_TOP || wall->type == RENDERWALL_BOTTOM) return; - if (line->flags & ML_DONTPEGBOTTOM) - { - zpos = decal->Z + frontsector->GetPlaneTexZ(sector_t::floor); - } - else - { - zpos = decal->Z + frontsector->GetPlaneTexZ(sector_t::ceiling); - } + default: + // No valid decal can have this type. If one is encountered anyway + // it is in some way invalid so skip it. + return; + //zpos = decal->z; + //break; + + case RF_RELUPPER: + if (type != RENDERWALL_TOP) return; + if (line->flags & ML_DONTPEGTOP) + { + zpos = decal->Z + frontsector->GetPlaneTexZ(sector_t::ceiling); + } + else + { + zpos = decal->Z + seg->backsector->GetPlaneTexZ(sector_t::ceiling); + } + break; + case RF_RELLOWER: + if (type != RENDERWALL_BOTTOM) return; + if (line->flags & ML_DONTPEGBOTTOM) + { + zpos = decal->Z + frontsector->GetPlaneTexZ(sector_t::ceiling); + } + else + { + zpos = decal->Z + seg->backsector->GetPlaneTexZ(sector_t::floor); + } + break; + case RF_RELMID: + if (type == RENDERWALL_TOP || type == RENDERWALL_BOTTOM) return; + if (line->flags & ML_DONTPEGBOTTOM) + { + zpos = decal->Z + frontsector->GetPlaneTexZ(sector_t::floor); + } + else + { + zpos = decal->Z + frontsector->GetPlaneTexZ(sector_t::ceiling); + } } - + + memset(&gldecal, 0, sizeof(gldecal)); + gldecal.gltexture = FMaterial::ValidateTexture(texture, true); + gldecal.wall = this; + gldecal.decal = decal; + if (decal->RenderFlags & RF_FULLBRIGHT) { - light = 255; - rel = 0; + gldecal.light = 255; + gldecal.rel = 0; } else { - light = wall->lightlevel; - rel = wall->rellight + getExtraLight(); + gldecal.light = lightlevel; + gldecal.rel = rellight + getExtraLight(); } - - FColormap p = wall->Colormap; - + + gldecal.colormap = Colormap; + if (level.flags3 & LEVEL3_NOCOLOREDSPRITELIGHTING) { - p.Decolorize(); + gldecal.colormap.Decolorize(); } - - - - a = decal->Alpha; - + + gldecal.a = decal->Alpha; + // now clip the decal to the actual polygon + FMaterial *tex = gldecal.gltexture; + float decalwidth = tex->TextureWidth() * decal->ScaleX; float decalheight = tex->TextureHeight() * decal->ScaleY; float decallefto = tex->GetLeftOffset() * decal->ScaleX; float decaltopo = tex->GetTopOffset() * decal->ScaleY; - - auto &glseg = wall->glseg; + float leftedge = glseg.fracleft * side->TexelLength; float linelength = glseg.fracright * side->TexelLength - leftedge; - + // texel index of the decal's left edge float decalpixpos = (float)side->TexelLength * decal->LeftDistance - (flipx ? decalwidth - decallefto : decallefto) - leftedge; - + float left, right; float lefttex, righttex; - + // decal is off the left edge if (decalpixpos < 0) { @@ -194,7 +192,7 @@ void FDrawInfo::DrawDecal(GLWall *wall, DBaseDecal *decal) left = decalpixpos; lefttex = 0; } - + // decal is off the right edge if (decalpixpos + decalwidth > linelength) { @@ -207,36 +205,37 @@ void FDrawInfo::DrawDecal(GLWall *wall, DBaseDecal *decal) righttex = decalwidth; } if (right <= left) return; // nothing to draw - + // one texture unit on the wall as vector float vx = (glseg.x2 - glseg.x1) / linelength; float vy = (glseg.y2 - glseg.y1) / linelength; - + + DecalVertex *dv = gldecal.dv; dv[1].x = dv[0].x = glseg.x1 + vx * left; dv[1].y = dv[0].y = glseg.y1 + vy * left; - + dv[3].x = dv[2].x = glseg.x1 + vx * right; dv[3].y = dv[2].y = glseg.y1 + vy * right; - + zpos += (flipy ? decalheight - decaltopo : decaltopo); - + dv[1].z = dv[2].z = zpos; dv[0].z = dv[3].z = dv[1].z - decalheight; dv[1].v = dv[2].v = tex->GetVT(); - + dv[1].u = dv[0].u = tex->GetU(lefttex / decal->ScaleX); dv[3].u = dv[2].u = tex->GetU(righttex / decal->ScaleX); dv[0].v = dv[3].v = tex->GetVB(); - + // now clip to the top plane - float vzt = (wall->ztop[1] - wall->ztop[0]) / linelength; - float topleft = wall->ztop[0] + vzt * left; - float topright = wall->ztop[0] + vzt * right; - + float vzt = (ztop[1] - ztop[0]) / linelength; + float topleft = ztop[0] + vzt * left; + float topright = ztop[0] + vzt * right; + // completely below the wall if (topleft < dv[0].z && topright < dv[3].z) return; - + if (topleft < dv[1].z || topright < dv[2].z) { // decal has to be clipped at the top @@ -246,16 +245,16 @@ void FDrawInfo::DrawDecal(GLWall *wall, DBaseDecal *decal) dv[1].z = topleft; dv[2].z = topright; } - + // now clip to the bottom plane - float vzb = (wall->zbottom[1] - wall->zbottom[0]) / linelength; - float bottomleft = wall->zbottom[0] + vzb * left; - float bottomright = wall->zbottom[0] + vzb * right; - + float vzb = (zbottom[1] - zbottom[0]) / linelength; + float bottomleft = zbottom[0] + vzb * left; + float bottomright = zbottom[0] + vzb * right; + // completely above the wall if (bottomleft > dv[1].z && bottomright > dv[2].z) return; - + if (bottomleft > dv[0].z || bottomright > dv[3].z) { // decal has to be clipped at the bottom @@ -265,8 +264,8 @@ void FDrawInfo::DrawDecal(GLWall *wall, DBaseDecal *decal) dv[0].z = bottomleft; dv[3].z = bottomright; } - - + + if (flipx) { float ur = tex->GetUR(); @@ -278,13 +277,56 @@ void FDrawInfo::DrawDecal(GLWall *wall, DBaseDecal *decal) for (i = 0; i < 4; i++) dv[i].v = vb - dv[i].v; } + gldecal.zcenter = zpos - decalheight * 0.5f; + + auto verts = gl_drawinfo->AllocVertices(4); + gldecal.vertindex = verts.second; + + for (i = 0; i < 4; i++) + { + verts.first[i].Set(dv[i].x, dv[i].z, dv[i].y, dv[i].u, dv[i].v); + } + di->AddDecal(&gldecal); +} + +//========================================================================== +// +// +// +//========================================================================== +void GLWall::ProcessDecals(HWDrawInfo *di) +{ + if (seg->sidedef != nullptr) + { + DBaseDecal *decal = seg->sidedef->AttachedDecals; + while (decal) + { + ProcessDecal(di, decal); + decal = decal->WallNext; + } + } +} + +//========================================================================== +// +// +// +//========================================================================== +void FDrawInfo::DrawDecal(GLWall *__wall, DBaseDecal *__decal) +{ + GLDecal *gldecal; + auto wall = gldecal->wall; + auto decal = gldecal->decal; + auto tex = gldecal->gltexture; + auto &seg = wall->seg; + // calculate dynamic light effect. if (gl_lights && GLRenderer->mLightCount && !mDrawer->FixedColormap && gl_light_sprites) { // Note: This should be replaced with proper shader based lighting. double x, y; decal->GetXY(seg->sidedef, x, y); - gl_SetDynSpriteLight(nullptr, x, y, zpos - decalheight * 0.5f, wall->sub); + gl_SetDynSpriteLight(nullptr, x, y, gldecal->zcenter, wall->sub); } // alpha color only has an effect when using an alpha texture. @@ -293,9 +335,6 @@ void FDrawInfo::DrawDecal(GLWall *wall, DBaseDecal *decal) gl_RenderState.SetObjectColor(decal->AlphaColor | 0xff000000); } - - - gl_SetRenderStyle(decal->RenderStyle, false, false); gl_RenderState.SetMaterial(tex, CLAMP_XY, decal->Translation, 0, !!(decal->RenderStyle.Flags & STYLEF_RedIsAlpha)); @@ -305,7 +344,7 @@ void FDrawInfo::DrawDecal(GLWall *wall, DBaseDecal *decal) else gl_RenderState.AlphaFunc(GL_GREATER, 0.f); - mDrawer->SetColor(light, rel, p, a); + mDrawer->SetColor(gldecal->light, gldecal->rel, gldecal->colormap, gldecal->a); // for additively drawn decals we must temporarily set the fog color to black. PalEntry fc = gl_RenderState.GetFogColor(); if (decal->RenderStyle.BlendOp == STYLEOP_Add && decal->RenderStyle.DestAlpha == STYLEALPHA_One) @@ -313,18 +352,12 @@ void FDrawInfo::DrawDecal(GLWall *wall, DBaseDecal *decal) gl_RenderState.SetFog(0, -1); } - gl_RenderState.SetNormal(glseg.Normal()); - - FQuadDrawer qd; - for (i = 0; i < 4; i++) - { - qd.Set(i, dv[i].x, dv[i].z, dv[i].y, dv[i].u, dv[i].v); - } + gl_RenderState.SetNormal(wall->glseg.Normal()); if (wall->lightlist == nullptr) { gl_RenderState.Apply(); - qd.Render(GL_TRIANGLE_FAN); + GLRenderer->mVBO->RenderArray(GL_TRIANGLE_FAN, gldecal->vertindex, 4); } else { @@ -334,6 +367,7 @@ void FDrawInfo::DrawDecal(GLWall *wall, DBaseDecal *decal) { secplane_t &lowplane = k == lightlist.Size() - 1 ? wall->bottomplane : lightlist[k + 1].plane; + DecalVertex *dv = gldecal->dv; float low1 = lowplane.ZatPoint(dv[1].x, dv[1].y); float low2 = lowplane.ZatPoint(dv[2].x, dv[2].y); @@ -343,13 +377,13 @@ void FDrawInfo::DrawDecal(GLWall *wall, DBaseDecal *decal) FColormap thiscm; thiscm.FadeColor = wall->Colormap.FadeColor; thiscm.CopyFrom3DLight(&lightlist[k]); - mDrawer->SetColor(thisll, rel, thiscm, a); + mDrawer->SetColor(thisll, gldecal->rel, thiscm, gldecal->a); if (level.flags3 & LEVEL3_NOCOLOREDSPRITELIGHTING) thiscm.Decolorize(); - mDrawer->SetFog(thisll, rel, &thiscm, wall->RenderStyle == STYLE_Add); + mDrawer->SetFog(thisll, gldecal->rel, &thiscm, wall->RenderStyle == STYLE_Add); gl_RenderState.SetSplitPlanes(lightlist[k].plane, lowplane); gl_RenderState.Apply(); - qd.Render(GL_TRIANGLE_FAN); + GLRenderer->mVBO->RenderArray(GL_TRIANGLE_FAN, gldecal->vertindex, 4); } if (low1 <= dv[0].z && low2 <= dv[3].z) break; } @@ -391,7 +425,6 @@ void FDrawInfo::DoDrawDecals(GLWall *wall) { gl_RenderState.EnableSplit(false); } - } } diff --git a/src/gl/scene/gl_wall.h b/src/gl/scene/gl_wall.h index 504c6f21c..03cc9dadd 100644 --- a/src/gl/scene/gl_wall.h +++ b/src/gl/scene/gl_wall.h @@ -86,7 +86,7 @@ public: void SetFrom3DFloor(F3DFloor *rover, bool top, bool underside); void ProcessSector(sector_t * frontsector); void Draw(int pass, bool trans); - + GLFlat(const GLFlat &other) { memcpy(this, &other, sizeof(GLFlat)); diff --git a/src/gl/scene/gl_walls_draw.cpp b/src/gl/scene/gl_walls_draw.cpp index de2e9a657..4a68d4ac6 100644 --- a/src/gl/scene/gl_walls_draw.cpp +++ b/src/gl/scene/gl_walls_draw.cpp @@ -461,6 +461,7 @@ void FDrawInfo::AddWall(GLWall *wall) wall->MakeVertices(this, false); auto newwall = drawlists[list].NewWall(); *newwall = *wall; + if (!masked) newwall->ProcessDecals(this); } wall->dynlightindex = -1; } @@ -482,6 +483,7 @@ void FDrawInfo::AddMirrorSurface(GLWall *w) tcs[GLWall::LOLFT].u = tcs[GLWall::LORGT].u = tcs[GLWall::UPLFT].u = tcs[GLWall::UPRGT].u = v.X; tcs[GLWall::LOLFT].v = tcs[GLWall::LORGT].v = tcs[GLWall::UPLFT].v = tcs[GLWall::UPRGT].v = v.Z; newwall->MakeVertices(this, false); + newwall->ProcessDecals(this); } //========================================================================== diff --git a/src/hwrenderer/scene/hw_drawinfo.h b/src/hwrenderer/scene/hw_drawinfo.h index 13533cbfc..e2db5f132 100644 --- a/src/hwrenderer/scene/hw_drawinfo.h +++ b/src/hwrenderer/scene/hw_drawinfo.h @@ -6,6 +6,7 @@ struct FSectorPortalGroup; struct FLinePortalSpan; struct FFlatVertex; class GLWall; +struct GLDecal; //========================================================================== // @@ -127,6 +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 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 262e5ed05..a508b2a81 100644 --- a/src/hwrenderer/scene/hw_drawstructs.h +++ b/src/hwrenderer/scene/hw_drawstructs.h @@ -236,6 +236,8 @@ public: float fch1, float fch2, float ffh1, float ffh2, float bch1, float bch2, float bfh1, float bfh2); + void ProcessDecal(HWDrawInfo *di, DBaseDecal *decal); + void ProcessDecals(HWDrawInfo *di); void CreateVertices(FFlatVertex *&ptr, bool nosplit); void SplitLeftEdge (FFlatVertex *&ptr); From 58c0431396078d01ece5066d3b2cfbf1ae27e527 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 27 Apr 2018 18:53:01 +0200 Subject: [PATCH 08/12] - copied gl_SetupLights to hw_walls.cpp. --- src/gl/scene/gl_walls_draw.cpp | 99 ------------------------------- src/hwrenderer/scene/hw_walls.cpp | 99 +++++++++++++++++++++++++++++++ 2 files changed, 99 insertions(+), 99 deletions(-) diff --git a/src/gl/scene/gl_walls_draw.cpp b/src/gl/scene/gl_walls_draw.cpp index 33d050805..8c954acf6 100644 --- a/src/gl/scene/gl_walls_draw.cpp +++ b/src/gl/scene/gl_walls_draw.cpp @@ -44,105 +44,6 @@ EXTERN_CVAR(Bool, gl_seamless) FDynLightData lightdata; -//========================================================================== -// -// Collect lights for shader -// -//========================================================================== - -bool GLWall::SetupLights(FDynLightData &lightdata) -{ - if (RenderStyle == STYLE_Add && !level.lightadditivesurfaces) return false; // no lights on additively blended surfaces. - - // check for wall types which cannot have dynamic lights on them (portal types never get here so they don't need to be checked.) - switch (type) - { - case RENDERWALL_FOGBOUNDARY: - case RENDERWALL_MIRRORSURFACE: - case RENDERWALL_COLOR: - return false; - } - - float vtx[]={glseg.x1,zbottom[0],glseg.y1, glseg.x1,ztop[0],glseg.y1, glseg.x2,ztop[1],glseg.y2, glseg.x2,zbottom[1],glseg.y2}; - Plane p; - - lightdata.Clear(); - - auto normal = glseg.Normal(); - p.Set(normal, -normal.X * glseg.x1 - normal.Z * glseg.y1); - - FLightNode *node; - if (seg->sidedef == NULL) - { - node = NULL; - } - else if (!(seg->sidedef->Flags & WALLF_POLYOBJ)) - { - node = seg->sidedef->lighthead; - } - else if (sub) - { - // Polobject segs cannot be checked per sidedef so use the subsector instead. - node = sub->lighthead; - } - else node = NULL; - - // Iterate through all dynamic lights which touch this wall and render them - while (node) - { - if (!(node->lightsource->flags2&MF2_DORMANT)) - { - iter_dlight++; - - DVector3 posrel = node->lightsource->PosRelative(seg->frontsector); - float x = posrel.X; - float y = posrel.Y; - float z = posrel.Z; - float dist = fabsf(p.DistToPoint(x, z, y)); - float radius = node->lightsource->GetRadius(); - float scale = 1.0f / ((2.f * radius) - dist); - FVector3 fn, pos; - - if (radius > 0.f && dist < radius) - { - FVector3 nearPt, up, right; - - pos = { x, z, y }; - fn = p.Normal(); - - fn.GetRightUp(right, up); - - FVector3 tmpVec = fn * dist; - nearPt = pos + tmpVec; - - FVector3 t1; - int outcnt[4]={0,0,0,0}; - texcoord tcs[4]; - - // do a quick check whether the light touches this polygon - for(int i=0;i<4;i++) - { - t1 = FVector3(&vtx[i*3]); - FVector3 nearToVert = t1 - nearPt; - tcs[i].u = ((nearToVert | right) * scale) + 0.5f; - tcs[i].v = ((nearToVert | up) * scale) + 0.5f; - - if (tcs[i].u<0) outcnt[0]++; - if (tcs[i].u>1) outcnt[1]++; - if (tcs[i].v<0) outcnt[2]++; - if (tcs[i].v>1) outcnt[3]++; - - } - if (outcnt[0]!=4 && outcnt[1]!=4 && outcnt[2]!=4 && outcnt[3]!=4) - { - lightdata.GetLight(seg->frontsector->PortalGroup, p, node->lightsource, true); - } - } - } - node = node->nextLight; - } - return true; -} //========================================================================== // diff --git a/src/hwrenderer/scene/hw_walls.cpp b/src/hwrenderer/scene/hw_walls.cpp index 1df0a0efc..a9c0c0639 100644 --- a/src/hwrenderer/scene/hw_walls.cpp +++ b/src/hwrenderer/scene/hw_walls.cpp @@ -39,6 +39,105 @@ #include "hwrenderer/scene/hw_portal.h" +//========================================================================== +// +// Collect lights for shader +// +//========================================================================== + +bool GLWall::SetupLights(FDynLightData &lightdata) +{ + if (RenderStyle == STYLE_Add && !level.lightadditivesurfaces) return false; // no lights on additively blended surfaces. + + // check for wall types which cannot have dynamic lights on them (portal types never get here so they don't need to be checked.) + switch (type) + { + case RENDERWALL_FOGBOUNDARY: + case RENDERWALL_MIRRORSURFACE: + case RENDERWALL_COLOR: + return false; + } + + float vtx[]={glseg.x1,zbottom[0],glseg.y1, glseg.x1,ztop[0],glseg.y1, glseg.x2,ztop[1],glseg.y2, glseg.x2,zbottom[1],glseg.y2}; + Plane p; + + lightdata.Clear(); + + auto normal = glseg.Normal(); + p.Set(normal, -normal.X * glseg.x1 - normal.Z * glseg.y1); + + FLightNode *node; + if (seg->sidedef == NULL) + { + node = NULL; + } + else if (!(seg->sidedef->Flags & WALLF_POLYOBJ)) + { + node = seg->sidedef->lighthead; + } + else if (sub) + { + // Polobject segs cannot be checked per sidedef so use the subsector instead. + node = sub->lighthead; + } + else node = NULL; + + // Iterate through all dynamic lights which touch this wall and render them + while (node) + { + if (!(node->lightsource->flags2&MF2_DORMANT)) + { + iter_dlight++; + + DVector3 posrel = node->lightsource->PosRelative(seg->frontsector); + float x = posrel.X; + float y = posrel.Y; + float z = posrel.Z; + float dist = fabsf(p.DistToPoint(x, z, y)); + float radius = node->lightsource->GetRadius(); + float scale = 1.0f / ((2.f * radius) - dist); + FVector3 fn, pos; + + if (radius > 0.f && dist < radius) + { + FVector3 nearPt, up, right; + + pos = { x, z, y }; + fn = p.Normal(); + + fn.GetRightUp(right, up); + + FVector3 tmpVec = fn * dist; + nearPt = pos + tmpVec; + + FVector3 t1; + int outcnt[4]={0,0,0,0}; + texcoord tcs[4]; + + // do a quick check whether the light touches this polygon + for(int i=0;i<4;i++) + { + t1 = FVector3(&vtx[i*3]); + FVector3 nearToVert = t1 - nearPt; + tcs[i].u = ((nearToVert | right) * scale) + 0.5f; + tcs[i].v = ((nearToVert | up) * scale) + 0.5f; + + if (tcs[i].u<0) outcnt[0]++; + if (tcs[i].u>1) outcnt[1]++; + if (tcs[i].v<0) outcnt[2]++; + if (tcs[i].v>1) outcnt[3]++; + + } + if (outcnt[0]!=4 && outcnt[1]!=4 && outcnt[2]!=4 && outcnt[3]!=4) + { + lightdata.GetLight(seg->frontsector->PortalGroup, p, node->lightsource, true); + } + } + } + node = node->nextLight; + } + return true; +} const char GLWall::passflag[] = { From 0d7c2527f2f2c6486e36507f65ffd55bc7a52e08 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 27 Apr 2018 20:18:52 +0200 Subject: [PATCH 09/12] - 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 { From 383ff0d8b8acf59c071776c1f818db01020cb337 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 27 Apr 2018 20:21:22 +0200 Subject: [PATCH 10/12] - moved code around. --- src/gl/scene/gl_decal.cpp | 133 -------------------------------- src/gl/scene/gl_walls_draw.cpp | 134 +++++++++++++++++++++++++++++++++ 2 files changed, 134 insertions(+), 133 deletions(-) diff --git a/src/gl/scene/gl_decal.cpp b/src/gl/scene/gl_decal.cpp index cf5aa1f5f..fc0b9f5e6 100644 --- a/src/gl/scene/gl_decal.cpp +++ b/src/gl/scene/gl_decal.cpp @@ -284,136 +284,3 @@ void GLWall::ProcessDecals(HWDrawInfo *di) } } -//========================================================================== -// -// -// -//========================================================================== -void FDrawInfo::DrawDecal(GLDecal *gldecal) -{ - auto wall = gldecal->wall; - auto decal = gldecal->decal; - auto tex = gldecal->gltexture; - auto &seg = wall->seg; - - // calculate dynamic light effect. - if (gl_lights && GLRenderer->mLightCount && !mDrawer->FixedColormap && gl_light_sprites) - { - // Note: This should be replaced with proper shader based lighting. - double x, y; - decal->GetXY(seg->sidedef, x, y); - gl_SetDynSpriteLight(nullptr, x, y, gldecal->zcenter, wall->sub); - } - - // alpha color only has an effect when using an alpha texture. - if (decal->RenderStyle.Flags & STYLEF_RedIsAlpha) - { - gl_RenderState.SetObjectColor(decal->AlphaColor | 0xff000000); - } - - gl_SetRenderStyle(decal->RenderStyle, false, false); - gl_RenderState.SetMaterial(tex, CLAMP_XY, decal->Translation, 0, !!(decal->RenderStyle.Flags & STYLEF_RedIsAlpha)); - - - // If srcalpha is one it looks better with a higher alpha threshold - if (decal->RenderStyle.SrcAlpha == STYLEALPHA_One) gl_RenderState.AlphaFunc(GL_GEQUAL, gl_mask_sprite_threshold); - else gl_RenderState.AlphaFunc(GL_GREATER, 0.f); - - - mDrawer->SetColor(gldecal->light, gldecal->rel, gldecal->colormap, gldecal->a); - // for additively drawn decals we must temporarily set the fog color to black. - PalEntry fc = gl_RenderState.GetFogColor(); - if (decal->RenderStyle.BlendOp == STYLEOP_Add && decal->RenderStyle.DestAlpha == STYLEALPHA_One) - { - gl_RenderState.SetFog(0, -1); - } - - gl_RenderState.SetNormal(wall->glseg.Normal()); - - if (wall->lightlist == nullptr) - { - gl_RenderState.Apply(); - GLRenderer->mVBO->RenderArray(GL_TRIANGLE_FAN, gldecal->vertindex, 4); - } - else - { - auto &lightlist = *wall->lightlist; - - for (unsigned k = 0; k < lightlist.Size(); k++) - { - secplane_t &lowplane = k == lightlist.Size() - 1 ? wall->bottomplane : lightlist[k + 1].plane; - - DecalVertex *dv = gldecal->dv; - float low1 = lowplane.ZatPoint(dv[1].x, dv[1].y); - float low2 = lowplane.ZatPoint(dv[2].x, dv[2].y); - - if (low1 < dv[1].z || low2 < dv[2].z) - { - int thisll = lightlist[k].caster != NULL ? hw_ClampLight(*lightlist[k].p_lightlevel) : wall->lightlevel; - FColormap thiscm; - thiscm.FadeColor = wall->Colormap.FadeColor; - thiscm.CopyFrom3DLight(&lightlist[k]); - mDrawer->SetColor(thisll, gldecal->rel, thiscm, gldecal->a); - if (level.flags3 & LEVEL3_NOCOLOREDSPRITELIGHTING) thiscm.Decolorize(); - mDrawer->SetFog(thisll, gldecal->rel, &thiscm, wall->RenderStyle == STYLE_Add); - gl_RenderState.SetSplitPlanes(lightlist[k].plane, lowplane); - - gl_RenderState.Apply(); - GLRenderer->mVBO->RenderArray(GL_TRIANGLE_FAN, gldecal->vertindex, 4); - } - if (low1 <= dv[0].z && low2 <= dv[3].z) break; - } - } - - rendered_decals++; - gl_RenderState.SetTextureMode(TM_MODULATE); - gl_RenderState.SetObjectColor(0xffffffff); - gl_RenderState.SetFog(fc, -1); - gl_RenderState.SetDynLight(0, 0, 0); -} - -//========================================================================== -// -// -// -//========================================================================== -void FDrawInfo::DrawDecals() -{ - GLWall *wall = nullptr; - for (auto gldecal : decals[0]) - { - if (gldecal->wall != wall) - { - 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); -} - -//========================================================================== -// -// 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(gldecal); - } - } -} - diff --git a/src/gl/scene/gl_walls_draw.cpp b/src/gl/scene/gl_walls_draw.cpp index 5e17fffe0..93cf8ceef 100644 --- a/src/gl/scene/gl_walls_draw.cpp +++ b/src/gl/scene/gl_walls_draw.cpp @@ -470,3 +470,137 @@ void FDrawInfo::AddPortal(GLWall *wall, int ptype) } wall->vertcount = 0; } + +//========================================================================== +// +// +// +//========================================================================== +void FDrawInfo::DrawDecal(GLDecal *gldecal) +{ + auto wall = gldecal->wall; + auto decal = gldecal->decal; + auto tex = gldecal->gltexture; + auto &seg = wall->seg; + + // calculate dynamic light effect. + if (gl_lights && GLRenderer->mLightCount && !mDrawer->FixedColormap && gl_light_sprites) + { + // Note: This should be replaced with proper shader based lighting. + double x, y; + decal->GetXY(seg->sidedef, x, y); + gl_SetDynSpriteLight(nullptr, x, y, gldecal->zcenter, wall->sub); + } + + // alpha color only has an effect when using an alpha texture. + if (decal->RenderStyle.Flags & STYLEF_RedIsAlpha) + { + gl_RenderState.SetObjectColor(decal->AlphaColor | 0xff000000); + } + + gl_SetRenderStyle(decal->RenderStyle, false, false); + gl_RenderState.SetMaterial(tex, CLAMP_XY, decal->Translation, 0, !!(decal->RenderStyle.Flags & STYLEF_RedIsAlpha)); + + + // If srcalpha is one it looks better with a higher alpha threshold + if (decal->RenderStyle.SrcAlpha == STYLEALPHA_One) gl_RenderState.AlphaFunc(GL_GEQUAL, gl_mask_sprite_threshold); + else gl_RenderState.AlphaFunc(GL_GREATER, 0.f); + + + mDrawer->SetColor(gldecal->light, gldecal->rel, gldecal->colormap, gldecal->a); + // for additively drawn decals we must temporarily set the fog color to black. + PalEntry fc = gl_RenderState.GetFogColor(); + if (decal->RenderStyle.BlendOp == STYLEOP_Add && decal->RenderStyle.DestAlpha == STYLEALPHA_One) + { + gl_RenderState.SetFog(0, -1); + } + + gl_RenderState.SetNormal(wall->glseg.Normal()); + + if (wall->lightlist == nullptr) + { + gl_RenderState.Apply(); + GLRenderer->mVBO->RenderArray(GL_TRIANGLE_FAN, gldecal->vertindex, 4); + } + else + { + auto &lightlist = *wall->lightlist; + + for (unsigned k = 0; k < lightlist.Size(); k++) + { + secplane_t &lowplane = k == lightlist.Size() - 1 ? wall->bottomplane : lightlist[k + 1].plane; + + DecalVertex *dv = gldecal->dv; + float low1 = lowplane.ZatPoint(dv[1].x, dv[1].y); + float low2 = lowplane.ZatPoint(dv[2].x, dv[2].y); + + if (low1 < dv[1].z || low2 < dv[2].z) + { + int thisll = lightlist[k].caster != NULL ? hw_ClampLight(*lightlist[k].p_lightlevel) : wall->lightlevel; + FColormap thiscm; + thiscm.FadeColor = wall->Colormap.FadeColor; + thiscm.CopyFrom3DLight(&lightlist[k]); + mDrawer->SetColor(thisll, gldecal->rel, thiscm, gldecal->a); + if (level.flags3 & LEVEL3_NOCOLOREDSPRITELIGHTING) thiscm.Decolorize(); + mDrawer->SetFog(thisll, gldecal->rel, &thiscm, wall->RenderStyle == STYLE_Add); + gl_RenderState.SetSplitPlanes(lightlist[k].plane, lowplane); + + gl_RenderState.Apply(); + GLRenderer->mVBO->RenderArray(GL_TRIANGLE_FAN, gldecal->vertindex, 4); + } + if (low1 <= dv[0].z && low2 <= dv[3].z) break; + } + } + + rendered_decals++; + gl_RenderState.SetTextureMode(TM_MODULATE); + gl_RenderState.SetObjectColor(0xffffffff); + gl_RenderState.SetFog(fc, -1); + gl_RenderState.SetDynLight(0, 0, 0); +} + +//========================================================================== +// +// +// +//========================================================================== +void FDrawInfo::DrawDecals() +{ + GLWall *wall = nullptr; + for (auto gldecal : decals[0]) + { + if (gldecal->wall != wall) + { + 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); +} + +//========================================================================== +// +// 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(gldecal); + } + } +} + From 678ac40b72a4a69a7418cef4498cc8457e8cfbbe Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 27 Apr 2018 20:28:59 +0200 Subject: [PATCH 11/12] - cleaned up includes for gl_decal.cpp --- src/gl/scene/gl_decal.cpp | 20 ++++++++------------ src/gl/scene/gl_scenedrawer.h | 8 -------- src/hwrenderer/utility/hw_lighting.h | 9 +++++++++ 3 files changed, 17 insertions(+), 20 deletions(-) diff --git a/src/gl/scene/gl_decal.cpp b/src/gl/scene/gl_decal.cpp index fc0b9f5e6..3dd2972c8 100644 --- a/src/gl/scene/gl_decal.cpp +++ b/src/gl/scene/gl_decal.cpp @@ -1,7 +1,7 @@ // //--------------------------------------------------------------------------- // -// Copyright(C) 2003-2016 Christoph Oelckers +// Copyright(C) 2003-2018 Christoph Oelckers // All rights reserved. // // This program is free software: you can redistribute it and/or modify @@ -21,24 +21,20 @@ // /* ** gl_decal.cpp -** OpenGL decal rendering code +** OpenGL decal processing code ** */ #include "doomdata.h" -#include "gl/system/gl_system.h" #include "a_sharedglobal.h" #include "r_utility.h" #include "g_levellocals.h" - +#include "hwrenderer/textures/hw_material.h" #include "hwrenderer/utility/hw_cvars.h" -#include "gl/data/gl_vertexbuffer.h" -#include "gl/renderer/gl_renderer.h" -#include "gl/renderer/gl_lightdata.h" -#include "gl/renderer/gl_renderstate.h" -#include "gl/scene/gl_drawinfo.h" -#include "gl/scene/gl_scenedrawer.h" -#include "gl/renderer/gl_quaddrawer.h" +#include "hwrenderer/scene/hw_drawstructs.h" +#include "hwrenderer/scene/hw_drawinfo.h" +#include "hwrenderer/utility/hw_lighting.h" +#include "hwrenderer/data/flatvertices.h" void GLWall::ProcessDecal(HWDrawInfo *di, DBaseDecal *decal) { @@ -257,7 +253,7 @@ void GLWall::ProcessDecal(HWDrawInfo *di, DBaseDecal *decal) gldecal.zcenter = zpos - decalheight * 0.5f; - auto verts = gl_drawinfo->AllocVertices(4); + auto verts = di->AllocVertices(4); gldecal.vertindex = verts.second; for (i = 0; i < 4; i++) diff --git a/src/gl/scene/gl_scenedrawer.h b/src/gl/scene/gl_scenedrawer.h index 0d1759ff7..5520225f6 100644 --- a/src/gl/scene/gl_scenedrawer.h +++ b/src/gl/scene/gl_scenedrawer.h @@ -9,14 +9,6 @@ #include "r_utility.h" #include "c_cvars.h" -EXTERN_CVAR(Int, gl_weaponlight); - -inline int getExtraLight() -{ - return r_viewpoint.extralight * gl_weaponlight; -} - - class GLSceneDrawer { fixed_t viewx, viewy; // since the nodes are still fixed point, keeping the view position also fixed point for node traversal is faster. diff --git a/src/hwrenderer/utility/hw_lighting.h b/src/hwrenderer/utility/hw_lighting.h index 43bceaf98..9acb1578d 100644 --- a/src/hwrenderer/utility/hw_lighting.h +++ b/src/hwrenderer/utility/hw_lighting.h @@ -1,7 +1,9 @@ #pragma once +#include "c_cvars.h" #include "v_palette.h" #include "templates.h" +#include "r_utility.h" struct Colormap; @@ -15,3 +17,10 @@ inline int hw_ClampLight(int lightlevel) return clamp(lightlevel, 0, 255); } +EXTERN_CVAR(Int, gl_weaponlight); + +inline int getExtraLight() +{ + return r_viewpoint.extralight * gl_weaponlight; +} + From fe2bfc6f11f37672ebe9de62a2babe45c0b8a88d Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 27 Apr 2018 20:34:20 +0200 Subject: [PATCH 12/12] - moved the API-independent parts of the decal code to hwrenderer/. --- src/CMakeLists.txt | 2 +- src/{gl/scene/gl_decal.cpp => hwrenderer/scene/hw_decal.cpp} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename src/{gl/scene/gl_decal.cpp => hwrenderer/scene/hw_decal.cpp} (100%) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index a7bedf0a6..7dc4606c2 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -813,7 +813,6 @@ set( FASTMATH_SOURCES textures/hires/xbr/xbrz.cpp textures/hires/xbr/xbrz_old.cpp gl/scene/gl_bsp.cpp - gl/scene/gl_decal.cpp gl/scene/gl_drawinfo.cpp gl/scene/gl_flats.cpp gl/scene/gl_sprite.cpp @@ -828,6 +827,7 @@ set( FASTMATH_SOURCES gl_load/gl_load.c hwrenderer/dynlights/hw_dynlightdata.cpp hwrenderer/scene/hw_fakeflat.cpp + hwrenderer/scene/hw_decal.cpp hwrenderer/scene/hw_clipper.cpp hwrenderer/scene/hw_renderhacks.cpp hwrenderer/scene/hw_walls.cpp diff --git a/src/gl/scene/gl_decal.cpp b/src/hwrenderer/scene/hw_decal.cpp similarity index 100% rename from src/gl/scene/gl_decal.cpp rename to src/hwrenderer/scene/hw_decal.cpp