From fc57180d7e8737ab869517b34fafa9406bc7b27c Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 30 Jan 2016 23:01:11 +0100 Subject: [PATCH 1/9] - added necessary state to implement 3D light splitting using hardware clipping planes. --- src/gl/renderer/gl_renderstate.cpp | 16 ++++++++++++++-- src/gl/renderer/gl_renderstate.h | 13 +++++++++++++ src/gl/scene/gl_wall.h | 2 ++ src/gl/shaders/gl_shader.cpp | 2 ++ src/gl/shaders/gl_shader.h | 4 ++++ src/gl/system/gl_interface.cpp | 2 +- wadsrc/static/shaders/glsl/main.vp | 7 +++++++ 7 files changed, 43 insertions(+), 3 deletions(-) diff --git a/src/gl/renderer/gl_renderstate.cpp b/src/gl/renderer/gl_renderstate.cpp index 15aa56da9..d7f46e07e 100644 --- a/src/gl/renderer/gl_renderstate.cpp +++ b/src/gl/renderer/gl_renderstate.cpp @@ -69,7 +69,7 @@ TArray gl_MatrixStack; void FRenderState::Reset() { mTextureEnabled = true; - mBrightmapEnabled = mFogEnabled = mGlowEnabled = false; + mSplitEnabled = mBrightmapEnabled = mFogEnabled = mGlowEnabled = false; mColorMask[0] = mColorMask[1] = mColorMask[2] = mColorMask[3] = true; currentColorMask[0] = currentColorMask[1] = currentColorMask[2] = currentColorMask[3] = true; mFogColor.d = -1; @@ -104,6 +104,7 @@ void FRenderState::Reset() bool FRenderState::ApplyShader() { + static const float nulvec[] = { 0.f, 0.f, 0.f, 0.f }; if (mSpecialEffect > EFF_NONE) { activeShader = GLRenderer->mShaderManager->BindEffect(mSpecialEffect); @@ -157,7 +158,6 @@ bool FRenderState::ApplyShader() else if (activeShader->currentglowstate) { // if glowing is on, disable it. - static const float nulvec[] = { 0.f, 0.f, 0.f, 0.f }; activeShader->muGlowTopColor.Set(nulvec); activeShader->muGlowBottomColor.Set(nulvec); activeShader->muGlowTopPlane.Set(nulvec); @@ -165,6 +165,18 @@ bool FRenderState::ApplyShader() activeShader->currentglowstate = 0; } + if (mSplitEnabled) + { + activeShader->muSplitTopPlane.Set(mSplitTopPlane.vec); + activeShader->muSplitBottomPlane.Set(mSplitBottomPlane.vec); + activeShader->currentsplitstate = 1; + } + else + { + activeShader->muSplitTopPlane.Set(nulvec); + activeShader->muSplitBottomPlane.Set(nulvec); + } + if (mColormapState != activeShader->currentfixedcolormap) { float r, g, b; diff --git a/src/gl/renderer/gl_renderstate.h b/src/gl/renderer/gl_renderstate.h index aa24072c2..d46bb4996 100644 --- a/src/gl/renderer/gl_renderstate.h +++ b/src/gl/renderer/gl_renderstate.h @@ -46,6 +46,7 @@ class FRenderState bool mTextureEnabled; bool mFogEnabled; bool mGlowEnabled; + bool mSplitEnabled; bool mBrightmapEnabled; bool mColorMask[4]; bool currentColorMask[4]; @@ -72,6 +73,7 @@ class FRenderState FStateVec4 mCameraPos; FStateVec4 mGlowTop, mGlowBottom; FStateVec4 mGlowTopPlane, mGlowBottomPlane; + FStateVec4 mSplitTopPlane, mSplitBottomPlane; PalEntry mFogColor; PalEntry mObjectColor; FStateVec4 mDynColor; @@ -229,6 +231,11 @@ public: mGlowEnabled = on; } + void EnableSplit(bool on) + { + mSplitEnabled = on; + } + void SetLightIndex(int n) { mLightIndex = n; @@ -272,6 +279,12 @@ public: mGlowBottomPlane.Set(FIXED2FLOAT(bottom.a), FIXED2FLOAT(bottom.b), FIXED2FLOAT(bottom.ic), FIXED2FLOAT(bottom.d)); } + void SetSplitPlanes(const secplane_t &top, const secplane_t &bottom) + { + mSplitTopPlane.Set(FIXED2FLOAT(top.a), FIXED2FLOAT(top.b), FIXED2FLOAT(top.ic), FIXED2FLOAT(top.d)); + mSplitBottomPlane.Set(FIXED2FLOAT(bottom.a), FIXED2FLOAT(bottom.b), FIXED2FLOAT(bottom.ic), FIXED2FLOAT(bottom.d)); + } + void SetDynLight(float r, float g, float b) { mDynColor.Set(r, g, b, 0); diff --git a/src/gl/scene/gl_wall.h b/src/gl/scene/gl_wall.h index 5b27d9435..6dc694585 100644 --- a/src/gl/scene/gl_wall.h +++ b/src/gl/scene/gl_wall.h @@ -150,6 +150,8 @@ public: FTextureID topflat,bottomflat; secplane_t topplane, bottomplane; // we need to save these to pass them to the shader for calculating glows. + secplane_t *toplight, *bottomlight; // These refer to the planes within the lightlist_t entries. + // these are not the same as ytop and ybottom!!! float zceil[2]; float zfloor[2]; diff --git a/src/gl/shaders/gl_shader.cpp b/src/gl/shaders/gl_shader.cpp index 2955cf7c8..aa8dfac2b 100644 --- a/src/gl/shaders/gl_shader.cpp +++ b/src/gl/shaders/gl_shader.cpp @@ -216,6 +216,8 @@ bool FShader::Load(const char * name, const char * vert_prog_lump, const char * muGlowTopColor.Init(hShader, "uGlowTopColor"); muGlowBottomPlane.Init(hShader, "uGlowBottomPlane"); muGlowTopPlane.Init(hShader, "uGlowTopPlane"); + muSplitBottomPlane.Init(hShader, "uSplitBottomPlane"); + muSplitTopPlane.Init(hShader, "uSplitTopPlane"); muFixedColormap.Init(hShader, "uFixedColormap"); muInterpolationFactor.Init(hShader, "uInterpolationFactor"); muClipHeightTop.Init(hShader, "uClipHeightTop"); diff --git a/src/gl/shaders/gl_shader.h b/src/gl/shaders/gl_shader.h index c5baceceb..cf6480d9b 100644 --- a/src/gl/shaders/gl_shader.h +++ b/src/gl/shaders/gl_shader.h @@ -218,6 +218,8 @@ class FShader FUniform4f muGlowTopColor; FUniform4f muGlowBottomPlane; FUniform4f muGlowTopPlane; + FUniform4f muSplitBottomPlane; + FUniform4f muSplitTopPlane; FBufferedUniform1f muInterpolationFactor; FBufferedUniform1f muClipHeightTop; FBufferedUniform1f muClipHeightBottom; @@ -233,6 +235,7 @@ public: int fakevb_index; private: int currentglowstate; + int currentsplitstate; int currentfixedcolormap; bool currentTextureMatrixState; bool currentModelMatrixState; @@ -243,6 +246,7 @@ public: { hShader = hVertProg = hFragProg = 0; currentglowstate = 0; + currentsplitstate = 0; currentfixedcolormap = 0; currentTextureMatrixState = true; // by setting the matrix state to 'true' it is guaranteed to be set the first time the render state gets applied. currentModelMatrixState = true; diff --git a/src/gl/system/gl_interface.cpp b/src/gl/system/gl_interface.cpp index 2e7d0f1e0..3fd718ff7 100644 --- a/src/gl/system/gl_interface.cpp +++ b/src/gl/system/gl_interface.cpp @@ -174,7 +174,7 @@ void gl_LoadExtensions() void gl_PrintStartupLog() { int v = 0; - glGetIntegerv(GL_CONTEXT_PROFILE_MASK, &v); + if (gl.version >= 3.2) glGetIntegerv(GL_CONTEXT_PROFILE_MASK, &v); Printf ("GL_VENDOR: %s\n", glGetString(GL_VENDOR)); Printf ("GL_RENDERER: %s\n", glGetString(GL_RENDERER)); diff --git a/wadsrc/static/shaders/glsl/main.vp b/wadsrc/static/shaders/glsl/main.vp index 827644eea..1c6aebe47 100644 --- a/wadsrc/static/shaders/glsl/main.vp +++ b/wadsrc/static/shaders/glsl/main.vp @@ -29,6 +29,12 @@ void main() glowdist.x = -((uGlowTopPlane.w + uGlowTopPlane.x * worldcoord.x + uGlowTopPlane.y * worldcoord.z) * uGlowTopPlane.z) - worldcoord.y; glowdist.y = worldcoord.y + ((uGlowBottomPlane.w + uGlowBottomPlane.x * worldcoord.x + uGlowBottomPlane.y * worldcoord.z) * uGlowBottomPlane.z); + + if (uSplitBottomPlane.z != 0) + { + gl_ClipDistance[3] = -((uSplitTopPlane.w + uSplitTopPlane.x * worldcoord.x + uSplitTopPlane.y * worldcoord.z) * uSplitTopPlane.z) - worldcoord.y; + gl_ClipDistance[4] = worldcoord.y + ((uSplitBottomPlane.w + uSplitBottomPlane.x * worldcoord.x + uSplitBottomPlane.y * worldcoord.z) * uSplitBottomPlane.z); + } #endif #ifdef SPHEREMAP @@ -56,4 +62,5 @@ void main() gl_ClipDistance[1] = worldcoord.y - uClipSplit.x; gl_ClipDistance[2] = uClipSplit.y - worldcoord.y; + } From 1d9ab5c63270a3c3ba0e43b546c7135bcc413d56 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 31 Jan 2016 00:45:29 +0100 Subject: [PATCH 2/9] - clean out GLWall::SplitWall and instead of actually splitting the wall just attach a list of lights to it. Actual handling will be in the rendering function because this doesn't need multiple vertex transfers to the GPU. All slices can be drawn from the same buffer with different uniform info being set. --- src/gl/scene/gl_wall.h | 13 ++- src/gl/scene/gl_walls.cpp | 205 ++------------------------------------ 2 files changed, 21 insertions(+), 197 deletions(-) diff --git a/src/gl/scene/gl_wall.h b/src/gl/scene/gl_wall.h index 6dc694585..1bdc86fe9 100644 --- a/src/gl/scene/gl_wall.h +++ b/src/gl/scene/gl_wall.h @@ -85,6 +85,15 @@ struct GLSectorPlane }; +struct GLWallLightEntry +{ + secplane_t *cliptop; + secplane_t *clipbottom; + int lightlevel; + FColormap colormap; +}; + +extern FMemArena GLWallLightEntryArena; class GLWall { @@ -126,6 +135,7 @@ public: fixed_t viewdistance; + GLWallLightEntry *lights; int lightlevel; BYTE type; BYTE flags; @@ -150,8 +160,6 @@ public: FTextureID topflat,bottomflat; secplane_t topplane, bottomplane; // we need to save these to pass them to the shader for calculating glows. - secplane_t *toplight, *bottomlight; // These refer to the planes within the lightlist_t entries. - // these are not the same as ytop and ybottom!!! float zceil[2]; float zfloor[2]; @@ -177,7 +185,6 @@ private: void SkyTop(seg_t * seg,sector_t * fs,sector_t * bs,vertex_t * v1,vertex_t * v2); void SkyBottom(seg_t * seg,sector_t * fs,sector_t * bs,vertex_t * v1,vertex_t * v2); - void Put3DWall(lightlist_t * lightlist, bool translucent); void SplitWall(sector_t * frontsector, bool translucent); void LightPass(); void SetHorizon(vertex_t * ul, vertex_t * ur, vertex_t * ll, vertex_t * lr); diff --git a/src/gl/scene/gl_walls.cpp b/src/gl/scene/gl_walls.cpp index bbe36b71f..4a7efaf88 100644 --- a/src/gl/scene/gl_walls.cpp +++ b/src/gl/scene/gl_walls.cpp @@ -62,6 +62,8 @@ #include "gl/shaders/gl_shader.h" +FMemArena GLWallLightEntryArena; + //========================================================================== // // Checks whether a wall should glow @@ -217,25 +219,6 @@ void GLWall::PutWall(bool translucent) } } -//========================================================================== -// -// Sets 3D-floor lighting info -// -//========================================================================== - -void GLWall::Put3DWall(lightlist_t * lightlist, bool translucent) -{ - // only modify the light level if it doesn't originate from the seg's frontsector. This is to account for light transferring effects - if (lightlist->p_lightlevel != &seg->sidedef->sector->lightlevel) - { - lightlevel = gl_ClampLight(*lightlist->p_lightlevel); - } - // relative light won't get changed here. It is constant across the entire wall. - - Colormap.CopyFrom3DLight(lightlist); - PutWall(translucent); -} - //========================================================================== // // Splits a wall vertically if a 3D-floor @@ -245,11 +228,6 @@ void GLWall::Put3DWall(lightlist_t * lightlist, bool translucent) void GLWall::SplitWall(sector_t * frontsector, bool translucent) { - GLWall copyWall1,copyWall2; - float maplightbottomleft; - float maplightbottomright; - unsigned int i; - int origlight = lightlevel; TArray & lightlist=frontsector->e->XFloor.lightlist; if (glseg.x1==glseg.x2 && glseg.y1==glseg.y2) @@ -258,178 +236,17 @@ void GLWall::SplitWall(sector_t * frontsector, bool translucent) } ::SplitWall.Clock(); -#ifdef _DEBUG - if (seg->linedef-lines==1) + lights = (GLWallLightEntry*)GLWallLightEntryArena.Alloc(sizeof(GLWallLightEntry)*lightlist.Size()); + secplane_t *upperplane = &topplane; + for (unsigned i = 0; i < lightlist.Size(); i++) { - int a = 0; + lights[i].cliptop = &lightlist[i].plane; + lights[i].clipbottom = i == lightlist.Size() - 1 ? &bottomplane : &lightlist[i + 1].plane; + lights[i].lightlevel = lightlist[i].caster != NULL? gl_ClampLight(*lightlist[i].p_lightlevel) : lightlevel; + lights[i].colormap.FadeColor = Colormap.FadeColor; + lights[i].colormap.CopyFrom3DLight(&lightlist[i]); } -#endif - - if (lightlist.Size()>1) - { - for(i=0;i=ztop[0] && maplightbottomright>=ztop[1]) - { - continue; - } - - // check for an intersection with the upper plane - if ((maplightbottomleftztop[1]) || - (maplightbottomleft>ztop[0] && maplightbottomright(fabsf(glseg.x2-glseg.x1), fabsf(glseg.y2-glseg.y2)); - - float dch=ztop[1]-ztop[0]; - float dfh=maplightbottomright-maplightbottomleft; - float coeff= (ztop[0]-maplightbottomleft)/(dfh-dch); - - // check for inaccuracies - let's be a little generous here! - if (coeff*clen<.1f) - { - maplightbottomleft=ztop[0]; - } - else if (coeff*clen>clen-.1f) - { - maplightbottomright=ztop[1]; - } - else - { - // split the wall in 2 at the intersection and recursively split both halves - copyWall1=copyWall2=*this; - - copyWall1.glseg.x2 = copyWall2.glseg.x1 = glseg.x1 + coeff * (glseg.x2-glseg.x1); - copyWall1.glseg.y2 = copyWall2.glseg.y1 = glseg.y1 + coeff * (glseg.y2-glseg.y1); - copyWall1.ztop[1] = copyWall2.ztop[0] = ztop[0] + coeff * (ztop[1]-ztop[0]); - copyWall1.zbottom[1] = copyWall2.zbottom[0] = zbottom[0] + coeff * (zbottom[1]-zbottom[0]); - copyWall1.glseg.fracright = copyWall2.glseg.fracleft = glseg.fracleft + coeff * (glseg.fracright-glseg.fracleft); - copyWall1.uprgt.u = copyWall2.uplft.u = uplft.u + coeff * (uprgt.u-uplft.u); - copyWall1.uprgt.v = copyWall2.uplft.v = uplft.v + coeff * (uprgt.v-uplft.v); - copyWall1.lorgt.u = copyWall2.lolft.u = lolft.u + coeff * (lorgt.u-lolft.u); - copyWall1.lorgt.v = copyWall2.lolft.v = lolft.v + coeff * (lorgt.v-lolft.v); - - ::SplitWall.Unclock(); - - copyWall1.SplitWall(frontsector, translucent); - copyWall2.SplitWall(frontsector, translucent); - return; - } - } - - // check for an intersection with the lower plane - if ((maplightbottomleftzbottom[1]) || - (maplightbottomleft>zbottom[0] && maplightbottomright(fabsf(glseg.x2-glseg.x1), fabsf(glseg.y2-glseg.y2)); - - float dch=zbottom[1]-zbottom[0]; - float dfh=maplightbottomright-maplightbottomleft; - float coeff= (zbottom[0]-maplightbottomleft)/(dfh-dch); - - // check for inaccuracies - let's be a little generous here because there's - // some conversions between floats and fixed_t's involved - if (coeff*clen<.1f) - { - maplightbottomleft=zbottom[0]; - } - else if (coeff*clen>clen-.1f) - { - maplightbottomright=zbottom[1]; - } - else - { - // split the wall in 2 at the intersection and recursively split both halves - copyWall1=copyWall2=*this; - - copyWall1.glseg.x2 = copyWall2.glseg.x1 = glseg.x1 + coeff * (glseg.x2-glseg.x1); - copyWall1.glseg.y2 = copyWall2.glseg.y1 = glseg.y1 + coeff * (glseg.y2-glseg.y1); - copyWall1.ztop[1] = copyWall2.ztop[0] = ztop[0] + coeff * (ztop[1]-ztop[0]); - copyWall1.zbottom[1] = copyWall2.zbottom[0] = zbottom[0] + coeff * (zbottom[1]-zbottom[0]); - copyWall1.glseg.fracright = copyWall2.glseg.fracleft = glseg.fracleft + coeff * (glseg.fracright-glseg.fracleft); - copyWall1.uprgt.u = copyWall2.uplft.u = uplft.u + coeff * (uprgt.u-uplft.u); - copyWall1.uprgt.v = copyWall2.uplft.v = uplft.v + coeff * (uprgt.v-uplft.v); - copyWall1.lorgt.u = copyWall2.lolft.u = lolft.u + coeff * (lorgt.u-lolft.u); - copyWall1.lorgt.v = copyWall2.lolft.v = lolft.v + coeff * (lorgt.v-lolft.v); - - ::SplitWall.Unclock(); - - copyWall1.SplitWall(frontsector, translucent); - copyWall2.SplitWall(frontsector, translucent); - return; - } - } - - // 3D floor is completely within this light - if (maplightbottomleft<=zbottom[0] && maplightbottomright<=zbottom[1]) - { - // These values must not be destroyed! - int ll=lightlevel; - FColormap lc=Colormap; - - Put3DWall(&lightlist[i], translucent); - - lightlevel=ll; - Colormap=lc; - - ::SplitWall.Unclock(); - - return; - } - - if (maplightbottomleft<=ztop[0] && maplightbottomright<=ztop[1] && - (maplightbottomleft!=ztop[0] || maplightbottomright!=ztop[1])) - { - copyWall1=*this; - - copyWall1.flags |= GLWF_NOSPLITLOWER; - flags |= GLWF_NOSPLITUPPER; - ztop[0]=copyWall1.zbottom[0]=maplightbottomleft; - ztop[1]=copyWall1.zbottom[1]=maplightbottomright; - uplft.v=copyWall1.lolft.v=copyWall1.uplft.v+ - (maplightbottomleft-copyWall1.ztop[0])*(copyWall1.lolft.v-copyWall1.uplft.v)/(zbottom[0]-copyWall1.ztop[0]); - uprgt.v=copyWall1.lorgt.v=copyWall1.uprgt.v+ - (maplightbottomright-copyWall1.ztop[1])*(copyWall1.lorgt.v-copyWall1.uprgt.v)/(zbottom[1]-copyWall1.ztop[1]); - copyWall1.Put3DWall(&lightlist[i], translucent); - } - if (ztop[0]==zbottom[0] && ztop[1]==zbottom[1]) - { - ::SplitWall.Unclock(); - return; - } - } - } - - // These values must not be destroyed! - int ll=lightlevel; - FColormap lc=Colormap; - - Put3DWall(&lightlist[lightlist.Size()-1], translucent); - - lightlevel=ll; - Colormap=lc; - flags &= ~GLWF_NOSPLITUPPER; - ::SplitWall.Unclock(); + PutWall(translucent); } From f86535407d8a7626e877939b5daa3ca44201aad9 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 31 Jan 2016 00:52:50 +0100 Subject: [PATCH 3/9] - forgot this. --- src/gl/scene/gl_scene.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/gl/scene/gl_scene.cpp b/src/gl/scene/gl_scene.cpp index 7a961d2cd..99776afbe 100644 --- a/src/gl/scene/gl_scene.cpp +++ b/src/gl/scene/gl_scene.cpp @@ -838,6 +838,7 @@ sector_t * FGLRenderer::RenderViewpoint (AActor * camera, GL_IRECT * bounds, flo angle_t a1 = FrustumAngle(); clipper.SafeAddClipRangeRealAngles(viewangle + a1, viewangle - a1); + GLWallLightEntryArena.FreeAll(); ProcessScene(toscreen); if (mainview) EndDrawScene(retval); // do not call this for camera textures. eye->TearDown(); From 5448b335c6f534dbf91b6a26e32e649905b95795 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 31 Jan 2016 21:10:59 +0100 Subject: [PATCH 4/9] - rewrote render loop for walls. Not working yet. --- src/gl/scene/gl_wall.h | 3 +- src/gl/scene/gl_walls.cpp | 4 +- src/gl/scene/gl_walls_draw.cpp | 139 +++++++++++++++------------------ 3 files changed, 69 insertions(+), 77 deletions(-) diff --git a/src/gl/scene/gl_wall.h b/src/gl/scene/gl_wall.h index 1bdc86fe9..c9b2e12bd 100644 --- a/src/gl/scene/gl_wall.h +++ b/src/gl/scene/gl_wall.h @@ -114,7 +114,6 @@ public: { RWF_BLANK = 0, RWF_TEXTURED = 1, // actually not being used anymore because with buffers it's even less efficient not writing the texture coordinates - but leave it here - RWF_GLOW = 2, RWF_NOSPLIT = 4, RWF_NORENDER = 8, }; @@ -136,6 +135,7 @@ public: fixed_t viewdistance; GLWallLightEntry *lights; + unsigned int lightsize; int lightlevel; BYTE type; BYTE flags; @@ -176,6 +176,7 @@ private: void SetupLights(); bool PrepareLight(texcoord * tcs, ADynamicLight * light); void RenderWall(int textured, unsigned int *store = NULL); + void RenderTextured(int rflags); void FloodPlane(int pass); diff --git a/src/gl/scene/gl_walls.cpp b/src/gl/scene/gl_walls.cpp index 4a7efaf88..d9eb74354 100644 --- a/src/gl/scene/gl_walls.cpp +++ b/src/gl/scene/gl_walls.cpp @@ -236,7 +236,8 @@ void GLWall::SplitWall(sector_t * frontsector, bool translucent) } ::SplitWall.Clock(); - lights = (GLWallLightEntry*)GLWallLightEntryArena.Alloc(sizeof(GLWallLightEntry)*lightlist.Size()); + lightsize = lightlist.Size(); + lights = (GLWallLightEntry*)GLWallLightEntryArena.Alloc(sizeof(GLWallLightEntry)*lightsize); secplane_t *upperplane = &topplane; for (unsigned i = 0; i < lightlist.Size(); i++) { @@ -1293,6 +1294,7 @@ void GLWall::Process(seg_t *seg, sector_t * frontsector, sector_t * backsector) Colormap = frontsector->ColorMap; flags = 0; dynlightindex = UINT_MAX; + lights = NULL; int rel = 0; int orglightlevel = gl_ClampLight(frontsector->lightlevel); diff --git a/src/gl/scene/gl_walls_draw.cpp b/src/gl/scene/gl_walls_draw.cpp index ce14e16d3..90eddd2e9 100644 --- a/src/gl/scene/gl_walls_draw.cpp +++ b/src/gl/scene/gl_walls_draw.cpp @@ -182,11 +182,6 @@ void GLWall::RenderWall(int textured, unsigned int *store) tcs[1]=uplft; tcs[2]=uprgt; tcs[3]=lorgt; - if ((flags&GLWF_GLOW) && (textured & RWF_GLOW)) - { - gl_RenderState.SetGlowPlanes(topplane, bottomplane); - gl_RenderState.SetGlowParams(topglowcolor, bottomglowcolor); - } if (!(textured & RWF_NORENDER)) { @@ -306,6 +301,59 @@ void GLWall::RenderMirrorSurface() } } +//========================================================================== +// +// +// +//========================================================================== + +void GLWall::RenderTextured(int rflags) +{ + int tmode = gl_RenderState.GetTextureMode(); + int rel = getExtraLight(); + + if (flags & GLWF_GLOW) + { + gl_RenderState.EnableGlow(true); + gl_RenderState.SetGlowPlanes(topplane, bottomplane); + gl_RenderState.SetGlowParams(topglowcolor, bottomglowcolor); + } + gl_RenderState.SetMaterial(gltexture, flags & 3, 0, -1, false); + + if (type == RENDERWALL_M2SNF) + { + if (flags & GLT_CLAMPY) + { + if (tmode == TM_MODULATE) gl_RenderState.SetTextureMode(TM_CLAMPY); + } + gl_SetFog(255, 0, NULL, false); + } + + float absalpha = fabsf(alpha); + if (lights == NULL) + { + gl_SetColor(lightlevel, rel, Colormap, absalpha); + if (type != RENDERWALL_M2SNF) gl_SetFog(lightlevel, rel, &Colormap, RenderStyle == STYLE_Add); + RenderWall(rflags); + } + else + { + unsigned int store[2]; + //RenderWall(rflags, store); + gl_RenderState.EnableSplit(true); + for (unsigned i = 0; i < lightsize; i++) + { + gl_SetColor(lights[i].lightlevel, rel, lights[i].colormap, absalpha); + if (type != RENDERWALL_M2SNF) gl_SetFog(lights[i].lightlevel, rel, &lights[i].colormap, RenderStyle == STYLE_Add); + gl_RenderState.SetSplitPlanes(*lights[i].cliptop, *lights[i].clipbottom); + //GLRenderer->mVBO->RenderArray(GL_TRIANGLE_FAN, store[0], store[1]); + RenderWall(rflags); + } + gl_RenderState.EnableSplit(false); + } + gl_RenderState.SetTextureMode(tmode); + gl_RenderState.EnableGlow(false); +} //========================================================================== // @@ -315,57 +363,26 @@ void GLWall::RenderMirrorSurface() void GLWall::RenderTranslucentWall() { - bool transparent = gltexture? gltexture->GetTransparent() : false; - - // currently the only modes possible are solid, additive or translucent - // and until that changes I won't fix this code for the new blending modes! - bool isadditive = RenderStyle == STYLE_Add; - if (gl_fixedcolormap == CM_DEFAULT && gl_lights && (gl.flags & RFL_BUFFER_STORAGE)) { SetupLights(); } - - if (!transparent) gl_RenderState.AlphaFunc(GL_GEQUAL, gl_mask_threshold); - else gl_RenderState.AlphaFunc(GL_GEQUAL, 0.f); - if (isadditive) gl_RenderState.BlendFunc(GL_SRC_ALPHA,GL_ONE); - - int extra; - if (gltexture) + if (gltexture) { - gl_RenderState.EnableGlow(!!(flags & GLWF_GLOW)); - gl_RenderState.SetMaterial(gltexture, flags & 3, 0, -1, false); - extra = getExtraLight(); + if (!gltexture->GetTransparent()) gl_RenderState.AlphaFunc(GL_GEQUAL, gl_mask_threshold); + else gl_RenderState.AlphaFunc(GL_GEQUAL, 0.f); + if (RenderStyle == STYLE_Add) gl_RenderState.BlendFunc(GL_SRC_ALPHA,GL_ONE); + RenderTextured(RWF_TEXTURED | RWF_NOSPLIT); + if (RenderStyle == STYLE_Add) gl_RenderState.BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); } - else - { - gl_RenderState.EnableTexture(false); - extra = 0; - } - int tmode = gl_RenderState.GetTextureMode(); - - gl_SetColor(lightlevel, extra, Colormap, fabsf(alpha)); - if (type!=RENDERWALL_M2SNF) gl_SetFog(lightlevel, extra, &Colormap, isadditive); else { - if (flags & GLT_CLAMPY) - { - if (tmode == TM_MODULATE) gl_RenderState.SetTextureMode(TM_CLAMPY); - } - gl_SetFog(255, 0, NULL, false); - } - - RenderWall(RWF_TEXTURED|RWF_NOSPLIT); - - // restore default settings - if (isadditive) gl_RenderState.BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - - if (!gltexture) - { + gl_RenderState.AlphaFunc(GL_GEQUAL, 0.f); + gl_SetColor(lightlevel, 0, Colormap, fabsf(alpha)); + gl_SetFog(lightlevel, 0, &Colormap, RenderStyle == STYLE_Add); + RenderWall(RWF_NOSPLIT); gl_RenderState.EnableTexture(true); } - gl_RenderState.EnableGlow(false); - gl_RenderState.SetTextureMode(tmode); } //========================================================================== @@ -375,17 +392,6 @@ void GLWall::RenderTranslucentWall() //========================================================================== void GLWall::Draw(int pass) { - int rel; - int tmode; - -#ifdef _DEBUG - if (seg->linedef-lines==879) - { - int a = 0; - } -#endif - - switch (pass) { case GLPASS_LIGHTSONLY: @@ -396,28 +402,11 @@ void GLWall::Draw(int pass) SetupLights(); // fall through case GLPASS_PLAIN: - rel = rellight + getExtraLight(); - gl_SetColor(lightlevel, rel, Colormap,1.0f); - tmode = gl_RenderState.GetTextureMode(); - if (type!=RENDERWALL_M2SNF) gl_SetFog(lightlevel, rel, &Colormap, false); - else - { - if (flags & GLT_CLAMPY) - { - if (tmode == TM_MODULATE) gl_RenderState.SetTextureMode(TM_CLAMPY); - } - gl_SetFog(255, 0, NULL, false); - } - gl_RenderState.EnableGlow(!!(flags & GLWF_GLOW)); - gl_RenderState.SetMaterial(gltexture, flags & 3, false, -1, false); - RenderWall(RWF_TEXTURED|RWF_GLOW); - gl_RenderState.EnableGlow(false); - gl_RenderState.SetTextureMode(tmode); + RenderTextured(RWF_TEXTURED); break; case GLPASS_TRANSLUCENT: - switch (type) { case RENDERWALL_MIRRORSURFACE: From 9ce6a7932c669293c612bea9b65c3edcd2f0bb88 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 31 Jan 2016 22:04:20 +0100 Subject: [PATCH 5/9] - implemented rendering of 3D lights with clip planes. --- src/gl/scene/gl_walls.cpp | 2 +- src/gl/scene/gl_walls_draw.cpp | 11 ++++++----- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/gl/scene/gl_walls.cpp b/src/gl/scene/gl_walls.cpp index d9eb74354..2e4e21e5c 100644 --- a/src/gl/scene/gl_walls.cpp +++ b/src/gl/scene/gl_walls.cpp @@ -242,7 +242,7 @@ void GLWall::SplitWall(sector_t * frontsector, bool translucent) for (unsigned i = 0; i < lightlist.Size(); i++) { lights[i].cliptop = &lightlist[i].plane; - lights[i].clipbottom = i == lightlist.Size() - 1 ? &bottomplane : &lightlist[i + 1].plane; + lights[i].clipbottom = i == lightlist.Size() - 1 ? (secplane_t*)NULL : &lightlist[i + 1].plane; lights[i].lightlevel = lightlist[i].caster != NULL? gl_ClampLight(*lightlist[i].p_lightlevel) : lightlevel; lights[i].colormap.FadeColor = Colormap.FadeColor; lights[i].colormap.CopyFrom3DLight(&lightlist[i]); diff --git a/src/gl/scene/gl_walls_draw.cpp b/src/gl/scene/gl_walls_draw.cpp index 90eddd2e9..4bff69238 100644 --- a/src/gl/scene/gl_walls_draw.cpp +++ b/src/gl/scene/gl_walls_draw.cpp @@ -338,17 +338,18 @@ void GLWall::RenderTextured(int rflags) } else { - unsigned int store[2]; - //RenderWall(rflags, store); gl_RenderState.EnableSplit(true); - for (unsigned i = 0; i < lightsize; i++) + glEnable(GL_CLIP_DISTANCE3); + glEnable(GL_CLIP_DISTANCE4); + for (unsigned i = 0; i mVBO->RenderArray(GL_TRIANGLE_FAN, store[0], store[1]); + gl_RenderState.SetSplitPlanes(*lights[i].cliptop, lights[i].clipbottom? *lights[i].clipbottom : bottomplane); RenderWall(rflags); } + glDisable(GL_CLIP_DISTANCE3); + glDisable(GL_CLIP_DISTANCE4); gl_RenderState.EnableSplit(false); } gl_RenderState.SetTextureMode(tmode); From 53a389aafc2d5827bcf120b8412386498bf7df89 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 31 Jan 2016 22:24:48 +0100 Subject: [PATCH 6/9] - fixed: for untextured walls, the texture must be disabled before rendering. - fixed: untextured walls should never be passed to SplitWall. - fixed: untextured walls should not be affected by dynamic lights (it's either fog boundaries or outsides of 3D fog volumes.) --- src/gl/scene/gl_walls.cpp | 10 ++++++---- src/gl/scene/gl_walls_draw.cpp | 9 +++++---- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/src/gl/scene/gl_walls.cpp b/src/gl/scene/gl_walls.cpp index 2e4e21e5c..6e51c2702 100644 --- a/src/gl/scene/gl_walls.cpp +++ b/src/gl/scene/gl_walls.cpp @@ -248,6 +248,8 @@ void GLWall::SplitWall(sector_t * frontsector, bool translucent) lights[i].colormap.CopyFrom3DLight(&lightlist[i]); } PutWall(translucent); + lights = NULL; + lightsize = 0; } @@ -543,7 +545,7 @@ void GLWall::DoTexture(int _type,seg_t * seg, int peg, // Add this wall to the render list sector_t * sec = sub? sub->sector : seg->frontsector; - if (sec->e->XFloor.lightlist.Size()==0 || gl_fixedcolormap) PutWall(false); + if (sec->e->XFloor.lightlist.Size()==0 || gl_fixedcolormap || !gltexture) PutWall(false); else SplitWall(sec, false); glseg=glsave; @@ -832,7 +834,7 @@ void GLWall::DoMidTexture(seg_t * seg, bool drawfogboundary, // Draw the stuff // // - if (realfront->e->XFloor.lightlist.Size()==0 || gl_fixedcolormap) split.PutWall(translucent); + if (realfront->e->XFloor.lightlist.Size()==0 || gl_fixedcolormap || !gltexture) split.PutWall(translucent); else split.SplitWall(realfront, translucent); t=1; @@ -846,7 +848,7 @@ void GLWall::DoMidTexture(seg_t * seg, bool drawfogboundary, // Draw the stuff without splitting // // - if (realfront->e->XFloor.lightlist.Size()==0 || gl_fixedcolormap) PutWall(translucent); + if (realfront->e->XFloor.lightlist.Size()==0 || gl_fixedcolormap || !gltexture) PutWall(translucent); else SplitWall(realfront, translucent); } alpha=1.0f; @@ -958,7 +960,7 @@ void GLWall::BuildFFBlock(seg_t * seg, F3DFloor * rover, sector_t * sec = sub? sub->sector : seg->frontsector; - if (sec->e->XFloor.lightlist.Size()==0 || gl_fixedcolormap) PutWall(translucent); + if (sec->e->XFloor.lightlist.Size()==0 || gl_fixedcolormap || !gltexture) PutWall(translucent); else SplitWall(sec, translucent); alpha=1.0f; diff --git a/src/gl/scene/gl_walls_draw.cpp b/src/gl/scene/gl_walls_draw.cpp index 4bff69238..814bc3545 100644 --- a/src/gl/scene/gl_walls_draw.cpp +++ b/src/gl/scene/gl_walls_draw.cpp @@ -364,12 +364,12 @@ void GLWall::RenderTextured(int rflags) void GLWall::RenderTranslucentWall() { - if (gl_fixedcolormap == CM_DEFAULT && gl_lights && (gl.flags & RFL_BUFFER_STORAGE)) - { - SetupLights(); - } if (gltexture) { + if (gl_fixedcolormap == CM_DEFAULT && gl_lights && (gl.flags & RFL_BUFFER_STORAGE)) + { + SetupLights(); + } if (!gltexture->GetTransparent()) gl_RenderState.AlphaFunc(GL_GEQUAL, gl_mask_threshold); else gl_RenderState.AlphaFunc(GL_GEQUAL, 0.f); if (RenderStyle == STYLE_Add) gl_RenderState.BlendFunc(GL_SRC_ALPHA,GL_ONE); @@ -381,6 +381,7 @@ void GLWall::RenderTranslucentWall() gl_RenderState.AlphaFunc(GL_GEQUAL, 0.f); gl_SetColor(lightlevel, 0, Colormap, fabsf(alpha)); gl_SetFog(lightlevel, 0, &Colormap, RenderStyle == STYLE_Add); + gl_RenderState.EnableTexture(false); RenderWall(RWF_NOSPLIT); gl_RenderState.EnableTexture(true); } From 71da7406bd8961c197e42c57f8275e904c115f4e Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 1 Feb 2016 00:42:37 +0100 Subject: [PATCH 7/9] - since we no longer split walls at 3D floor boundaries, those planes no longer need to be added to the vertex height lists. --- src/gl/data/gl_setup.cpp | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/gl/data/gl_setup.cpp b/src/gl/data/gl_setup.cpp index 5e6e0767b..07e5c8347 100644 --- a/src/gl/data/gl_setup.cpp +++ b/src/gl/data/gl_setup.cpp @@ -436,15 +436,6 @@ static void InitVertexData() AddToVertex(sec, vt_sectorlists[v-vertexes]); if (sec->heightsec) AddToVertex(sec->heightsec, vt_sectorlists[v-vertexes]); - - for(l=0;lflags & FF_EXISTS)) continue; - if (rover->flags&FF_NOSHADE) continue; // FF_NOSHADE doesn't create any wall splits - - AddToVertex(rover->model, vt_sectorlists[v-vertexes]); - } } } } From 9305cd86a09579a2b38fea5d29561e21d3d97e9d Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 1 Feb 2016 01:03:34 +0100 Subject: [PATCH 8/9] - remove the GLWallLightEntry type. Everything it contains can be retrieved from the existing lightlist just as easily, and this approach avoids a lot of memory allocations. - removed the SplitWall profiling timer because all it measures now is an almost empty function. --- src/gl/data/gl_setup.cpp | 1 - src/gl/scene/gl_scene.cpp | 1 - src/gl/scene/gl_wall.h | 13 +------------ src/gl/scene/gl_walls.cpp | 22 +++------------------- src/gl/scene/gl_walls_draw.cpp | 16 +++++++++++----- src/gl/utility/gl_clock.cpp | 9 ++++----- src/gl/utility/gl_clock.h | 2 +- 7 files changed, 20 insertions(+), 44 deletions(-) diff --git a/src/gl/data/gl_setup.cpp b/src/gl/data/gl_setup.cpp index 07e5c8347..c42a2c19c 100644 --- a/src/gl/data/gl_setup.cpp +++ b/src/gl/data/gl_setup.cpp @@ -413,7 +413,6 @@ static void InitVertexData() TArray * vt_sectorlists; int i,j,k; - unsigned int l; vt_sectorlists = new TArray[numvertexes]; diff --git a/src/gl/scene/gl_scene.cpp b/src/gl/scene/gl_scene.cpp index 99776afbe..7a961d2cd 100644 --- a/src/gl/scene/gl_scene.cpp +++ b/src/gl/scene/gl_scene.cpp @@ -838,7 +838,6 @@ sector_t * FGLRenderer::RenderViewpoint (AActor * camera, GL_IRECT * bounds, flo angle_t a1 = FrustumAngle(); clipper.SafeAddClipRangeRealAngles(viewangle + a1, viewangle - a1); - GLWallLightEntryArena.FreeAll(); ProcessScene(toscreen); if (mainview) EndDrawScene(retval); // do not call this for camera textures. eye->TearDown(); diff --git a/src/gl/scene/gl_wall.h b/src/gl/scene/gl_wall.h index c9b2e12bd..4d83e726b 100644 --- a/src/gl/scene/gl_wall.h +++ b/src/gl/scene/gl_wall.h @@ -85,16 +85,6 @@ struct GLSectorPlane }; -struct GLWallLightEntry -{ - secplane_t *cliptop; - secplane_t *clipbottom; - int lightlevel; - FColormap colormap; -}; - -extern FMemArena GLWallLightEntryArena; - class GLWall { public: @@ -134,8 +124,7 @@ public: fixed_t viewdistance; - GLWallLightEntry *lights; - unsigned int lightsize; + TArray *lightlist; int lightlevel; BYTE type; BYTE flags; diff --git a/src/gl/scene/gl_walls.cpp b/src/gl/scene/gl_walls.cpp index 6e51c2702..ac90e6123 100644 --- a/src/gl/scene/gl_walls.cpp +++ b/src/gl/scene/gl_walls.cpp @@ -62,8 +62,6 @@ #include "gl/shaders/gl_shader.h" -FMemArena GLWallLightEntryArena; - //========================================================================== // // Checks whether a wall should glow @@ -228,28 +226,14 @@ void GLWall::PutWall(bool translucent) void GLWall::SplitWall(sector_t * frontsector, bool translucent) { - TArray & lightlist=frontsector->e->XFloor.lightlist; if (glseg.x1==glseg.x2 && glseg.y1==glseg.y2) { return; } - ::SplitWall.Clock(); - - lightsize = lightlist.Size(); - lights = (GLWallLightEntry*)GLWallLightEntryArena.Alloc(sizeof(GLWallLightEntry)*lightsize); - secplane_t *upperplane = &topplane; - for (unsigned i = 0; i < lightlist.Size(); i++) - { - lights[i].cliptop = &lightlist[i].plane; - lights[i].clipbottom = i == lightlist.Size() - 1 ? (secplane_t*)NULL : &lightlist[i + 1].plane; - lights[i].lightlevel = lightlist[i].caster != NULL? gl_ClampLight(*lightlist[i].p_lightlevel) : lightlevel; - lights[i].colormap.FadeColor = Colormap.FadeColor; - lights[i].colormap.CopyFrom3DLight(&lightlist[i]); - } + lightlist=&frontsector->e->XFloor.lightlist; PutWall(translucent); - lights = NULL; - lightsize = 0; + lightlist = NULL; } @@ -1296,7 +1280,7 @@ void GLWall::Process(seg_t *seg, sector_t * frontsector, sector_t * backsector) Colormap = frontsector->ColorMap; flags = 0; dynlightindex = UINT_MAX; - lights = NULL; + lightlist = NULL; int rel = 0; int orglightlevel = gl_ClampLight(frontsector->lightlevel); diff --git a/src/gl/scene/gl_walls_draw.cpp b/src/gl/scene/gl_walls_draw.cpp index 814bc3545..cd404f4c9 100644 --- a/src/gl/scene/gl_walls_draw.cpp +++ b/src/gl/scene/gl_walls_draw.cpp @@ -330,7 +330,7 @@ void GLWall::RenderTextured(int rflags) } float absalpha = fabsf(alpha); - if (lights == NULL) + if (lightlist == NULL) { gl_SetColor(lightlevel, rel, Colormap, absalpha); if (type != RENDERWALL_M2SNF) gl_SetFog(lightlevel, rel, &Colormap, RenderStyle == STYLE_Add); @@ -341,13 +341,19 @@ void GLWall::RenderTextured(int rflags) gl_RenderState.EnableSplit(true); glEnable(GL_CLIP_DISTANCE3); glEnable(GL_CLIP_DISTANCE4); - for (unsigned i = 0; i Size(); i++) { - gl_SetColor(lights[i].lightlevel, rel, lights[i].colormap, absalpha); - if (type != RENDERWALL_M2SNF) gl_SetFog(lights[i].lightlevel, rel, &lights[i].colormap, RenderStyle == STYLE_Add); - gl_RenderState.SetSplitPlanes(*lights[i].cliptop, lights[i].clipbottom? *lights[i].clipbottom : bottomplane); + int thisll = (*lightlist)[i].caster != NULL? gl_ClampLight(*(*lightlist)[i].p_lightlevel) : lightlevel; + FColormap thiscm; + thiscm.FadeColor = Colormap.FadeColor; + thiscm.CopyFrom3DLight(&(*lightlist)[i]); + gl_SetColor(thisll, rel, thiscm, absalpha); + if (type != RENDERWALL_M2SNF) gl_SetFog(thisll, rel, &thiscm, RenderStyle == STYLE_Add); + gl_RenderState.SetSplitPlanes((*lightlist)[i].plane, i == (*lightlist).Size() - 1 ? bottomplane : (*lightlist)[i + 1].plane); RenderWall(rflags); } + glDisable(GL_CLIP_DISTANCE3); glDisable(GL_CLIP_DISTANCE4); gl_RenderState.EnableSplit(false); diff --git a/src/gl/utility/gl_clock.cpp b/src/gl/utility/gl_clock.cpp index 48c21dde2..545607ea1 100644 --- a/src/gl/utility/gl_clock.cpp +++ b/src/gl/utility/gl_clock.cpp @@ -16,7 +16,7 @@ #include "gl/utility/gl_convert.h" -glcycle_t RenderWall,SetupWall,ClipWall,SplitWall; +glcycle_t RenderWall,SetupWall,ClipWall; glcycle_t RenderFlat,SetupFlat; glcycle_t RenderSprite,SetupSprite; glcycle_t All, Finish, PortalAll, Bsp; @@ -91,7 +91,6 @@ void ResetProfilingData() ProcessAll.Reset(); RenderWall.Reset(); SetupWall.Reset(); - SplitWall.Reset(); ClipWall.Reset(); RenderFlat.Reset(); SetupFlat.Reset(); @@ -111,15 +110,15 @@ void ResetProfilingData() static void AppendRenderTimes(FString &str) { - double setupwall = SetupWall.TimeMS() - SplitWall.TimeMS(); + double setupwall = SetupWall.TimeMS(); double clipwall = ClipWall.TimeMS() - SetupWall.TimeMS(); double bsp = Bsp.TimeMS() - ClipWall.TimeMS() - SetupFlat.TimeMS() - SetupSprite.TimeMS(); - str.AppendFormat("W: Render=%2.3f, Split = %2.3f, Setup=%2.3f, Clip=%2.3f\n" + str.AppendFormat("W: Render=%2.3f, Setup=%2.3f, Clip=%2.3f\n" "F: Render=%2.3f, Setup=%2.3f\n" "S: Render=%2.3f, Setup=%2.3f\n" "All=%2.3f, Render=%2.3f, Setup=%2.3f, BSP = %2.3f, Portal=%2.3f, Drawcalls=%2.3f, Finish=%2.3f\n", - RenderWall.TimeMS(), SplitWall.TimeMS(), setupwall, clipwall, RenderFlat.TimeMS(), SetupFlat.TimeMS(), + RenderWall.TimeMS(), setupwall, clipwall, RenderFlat.TimeMS(), SetupFlat.TimeMS(), RenderSprite.TimeMS(), SetupSprite.TimeMS(), All.TimeMS() + Finish.TimeMS(), RenderAll.TimeMS(), ProcessAll.TimeMS(), bsp, PortalAll.TimeMS(), drawcalls.TimeMS(), Finish.TimeMS()); } diff --git a/src/gl/utility/gl_clock.h b/src/gl/utility/gl_clock.h index 46a01d1e4..4d5163d86 100644 --- a/src/gl/utility/gl_clock.h +++ b/src/gl/utility/gl_clock.h @@ -102,7 +102,7 @@ private: #endif // __APPLE__ -extern glcycle_t RenderWall,SetupWall,ClipWall,SplitWall; +extern glcycle_t RenderWall,SetupWall,ClipWall; extern glcycle_t RenderFlat,SetupFlat; extern glcycle_t RenderSprite,SetupSprite; extern glcycle_t All, Finish, PortalAll, Bsp; From 67fc35e7382c0b6a68b58a5e21a3077b6a63199d Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 1 Feb 2016 01:49:49 +0100 Subject: [PATCH 9/9] - some cleanup of wall processing code. * removed SplitWall function * split PutWall into PutWall and PutPortal because none of the portal cases needs the overhead for normal walls. --- src/gl/scene/gl_sky.cpp | 22 ++++--- src/gl/scene/gl_wall.h | 20 +++--- src/gl/scene/gl_walls.cpp | 124 ++++++++++++++++---------------------- 3 files changed, 76 insertions(+), 90 deletions(-) diff --git a/src/gl/scene/gl_sky.cpp b/src/gl/scene/gl_sky.cpp index 7eeda5f3d..c020ab276 100644 --- a/src/gl/scene/gl_sky.cpp +++ b/src/gl/scene/gl_sky.cpp @@ -137,11 +137,12 @@ void GLSkyInfo::init(int sky1, PalEntry FadeColor) void GLWall::SkyPlane(sector_t *sector, int plane, bool allowreflect) { + int ptype = -1; FPortal *portal = sector->portals[plane]; if (portal != NULL) { if (GLPortal::instack[1 - plane]) return; - type = RENDERWALL_SECTORSTACK; + ptype = PORTALTYPE_SECTORSTACK; this->portal = portal; } else @@ -156,13 +157,13 @@ void GLWall::SkyPlane(sector_t *sector, int plane, bool allowreflect) if (!gl_noskyboxes && skyboxx && GLRenderer->mViewActor != skyboxx && !(skyboxx->flags&MF_JUSTHIT)) { - type = RENDERWALL_SKYBOX; + ptype = PORTALTYPE_SKYBOX; skybox = skyboxx; } else { skyinfo.init(sector->sky, Colormap.FadeColor); - type = RENDERWALL_SKY; + ptype = PORTALTYPE_SKY; sky = UniqueSkies.Get(&skyinfo); } } @@ -170,12 +171,14 @@ void GLWall::SkyPlane(sector_t *sector, int plane, bool allowreflect) { if ((plane == sector_t::ceiling && viewz > sector->ceilingplane.d) || (plane == sector_t::floor && viewz < -sector->floorplane.d)) return; - type = RENDERWALL_PLANEMIRROR; + ptype = PORTALTYPE_PLANEMIRROR; planemirror = plane == sector_t::ceiling ? §or->ceilingplane : §or->floorplane; } - else return; } - PutWall(0); + if (ptype != -1) + { + PutPortal(ptype); + } } @@ -189,22 +192,23 @@ void GLWall::SkyLine(line_t *line) { ASkyViewpoint * skyboxx = line->skybox; GLSkyInfo skyinfo; + int ptype; // JUSTHIT is used as an indicator that a skybox is in use. // This is to avoid recursion if (!gl_noskyboxes && skyboxx && GLRenderer->mViewActor != skyboxx && !(skyboxx->flags&MF_JUSTHIT)) { - type = RENDERWALL_SKYBOX; + ptype = PORTALTYPE_SKYBOX; skybox = skyboxx; } else { skyinfo.init(line->frontsector->sky, Colormap.FadeColor); - type = RENDERWALL_SKY; + ptype = PORTALTYPE_SKY; sky = UniqueSkies.Get(&skyinfo); } - PutWall(0); + PutPortal(ptype); } diff --git a/src/gl/scene/gl_wall.h b/src/gl/scene/gl_wall.h index 4d83e726b..d9ef91232 100644 --- a/src/gl/scene/gl_wall.h +++ b/src/gl/scene/gl_wall.h @@ -30,13 +30,7 @@ enum WallTypes RENDERWALL_M1S, RENDERWALL_M2S, RENDERWALL_BOTTOM, - RENDERWALL_SKY, RENDERWALL_FOGBOUNDARY, - RENDERWALL_HORIZON, - RENDERWALL_SKYBOX, - RENDERWALL_SECTORSTACK, - RENDERWALL_PLANEMIRROR, - RENDERWALL_MIRROR, RENDERWALL_MIRRORSURFACE, RENDERWALL_M2SNF, RENDERWALL_COLOR, @@ -44,6 +38,16 @@ enum WallTypes // Insert new types at the end! }; +enum PortalTypes +{ + PORTALTYPE_SKY, + PORTALTYPE_HORIZON, + PORTALTYPE_SKYBOX, + PORTALTYPE_SECTORSTACK, + PORTALTYPE_PLANEMIRROR, + PORTALTYPE_MIRROR, +}; + struct GLSeg { float x1,x2; @@ -159,7 +163,8 @@ public: private: void CheckGlowing(); - void PutWall(bool translucent); + void PutWall(sector_t *sec, bool translucent); + void PutPortal(int ptype); void CheckTexturePosition(); void SetupLights(); @@ -175,7 +180,6 @@ private: void SkyTop(seg_t * seg,sector_t * fs,sector_t * bs,vertex_t * v1,vertex_t * v2); void SkyBottom(seg_t * seg,sector_t * fs,sector_t * bs,vertex_t * v1,vertex_t * v2); - void SplitWall(sector_t * frontsector, bool translucent); void LightPass(); void SetHorizon(vertex_t * ul, vertex_t * ur, vertex_t * ll, vertex_t * lr); bool DoHorizon(seg_t * seg,sector_t * fs, vertex_t * v1,vertex_t * v2); diff --git a/src/gl/scene/gl_walls.cpp b/src/gl/scene/gl_walls.cpp index ac90e6123..c8808e79b 100644 --- a/src/gl/scene/gl_walls.cpp +++ b/src/gl/scene/gl_walls.cpp @@ -96,57 +96,54 @@ void GLWall::CheckGlowing() // // //========================================================================== -void GLWall::PutWall(bool translucent) +void GLWall::PutWall(sector_t *sec, bool translucent) { - GLPortal * portal; int list; - static char passflag[]={ + static char passflag[] = { 0, //RENDERWALL_NONE, 1, //RENDERWALL_TOP, // unmasked 1, //RENDERWALL_M1S, // unmasked 2, //RENDERWALL_M2S, // depends on render and texture settings 1, //RENDERWALL_BOTTOM, // unmasked - 4, //RENDERWALL_SKYDOME, // special 3, //RENDERWALL_FOGBOUNDARY, // translucent - 4, //RENDERWALL_HORIZON, // special - 4, //RENDERWALL_SKYBOX, // special - 4, //RENDERWALL_SECTORSTACK, // special - 4, //RENDERWALL_PLANEMIRROR, // special - 4, //RENDERWALL_MIRROR, // special - 1, //RENDERWALL_MIRRORSURFACE, // only created here from RENDERWALL_MIRROR + 1, //RENDERWALL_MIRRORSURFACE, // only created from PORTALTYPE_MIRROR 2, //RENDERWALL_M2SNF, // depends on render and texture settings, no fog, used on mid texture lines with a fog boundary. 3, //RENDERWALL_COLOR, // translucent 2, //RENDERWALL_FFBLOCK // depends on render and texture settings }; - + + if (gltexture && gltexture->GetTransparent() && passflag[type] == 2) { translucent = true; } - if (gl_fixedcolormap) + if (gl_fixedcolormap) { // light planes don't get drawn with fullbright rendering - if (!gltexture && passflag[type]!=4) return; - + if (gltexture == NULL) return; Colormap.Clear(); } + else if (sec->e->XFloor.lightlist.Size() > 0 && gltexture != NULL) + { + lightlist = &sec->e->XFloor.lightlist; + } CheckGlowing(); if (translucent) // translucent walls { - viewdistance = P_AproxDistance( ((seg->linedef->v1->x+seg->linedef->v2->x)>>1) - viewx, - ((seg->linedef->v1->y+seg->linedef->v2->y)>>1) - viewy); + viewdistance = P_AproxDistance(((seg->linedef->v1->x + seg->linedef->v2->x) >> 1) - viewx, + ((seg->linedef->v1->y + seg->linedef->v2->y) >> 1) - viewy); gl_drawinfo->drawlists[GLDL_TRANSLUCENT].AddWall(this); } - else if (passflag[type]!=4) // non-translucent walls + else { bool masked; - masked = passflag[type]==1? false : (gltexture && gltexture->isMasked()); + masked = passflag[type] == 1 ? false : (gltexture && gltexture->isMasked()); if ((flags&GLWF_SKYHACK && type == RENDERWALL_M2S)) { @@ -159,18 +156,25 @@ void GLWall::PutWall(bool translucent) gl_drawinfo->drawlists[list].AddWall(this); } - else switch (type) + lightlist = NULL; +} + +void GLWall::PutPortal(int ptype) +{ + GLPortal * portal; + + switch (ptype) { // portals don't go into the draw list. // Instead they are added to the portal manager - case RENDERWALL_HORIZON: + case PORTALTYPE_HORIZON: horizon=UniqueHorizons.Get(horizon); portal=GLPortal::FindPortal(horizon); if (!portal) portal=new GLHorizonPortal(horizon); portal->AddLine(this); break; - case RENDERWALL_SKYBOX: + case PORTALTYPE_SKYBOX: portal = GLPortal::FindPortal(skybox); if (!portal) { @@ -181,12 +185,12 @@ void GLWall::PutWall(bool translucent) portal->AddLine(this); break; - case RENDERWALL_SECTORSTACK: + case PORTALTYPE_SECTORSTACK: portal = this->portal->GetGLPortal(); portal->AddLine(this); break; - case RENDERWALL_PLANEMIRROR: + case PORTALTYPE_PLANEMIRROR: if (GLPortal::PlaneMirrorMode * planemirror->c <=0) { //@sync-portal @@ -197,7 +201,7 @@ void GLWall::PutWall(bool translucent) } break; - case RENDERWALL_MIRROR: + case PORTALTYPE_MIRROR: portal=GLPortal::FindPortal(seg->linedef); if (!portal) portal=new GLMirrorPortal(seg->linedef); portal->AddLine(this); @@ -209,7 +213,7 @@ void GLWall::PutWall(bool translucent) } break; - case RENDERWALL_SKY: + case PORTALTYPE_SKY: portal=GLPortal::FindPortal(sky); if (!portal) portal=new GLSkyPortal(sky); portal->AddLine(this); @@ -217,26 +221,6 @@ void GLWall::PutWall(bool translucent) } } -//========================================================================== -// -// Splits a wall vertically if a 3D-floor -// creates different lighting across the wall -// -//========================================================================== - -void GLWall::SplitWall(sector_t * frontsector, bool translucent) -{ - - if (glseg.x1==glseg.x2 && glseg.y1==glseg.y2) - { - return; - } - lightlist=&frontsector->e->XFloor.lightlist; - PutWall(translucent); - lightlist = NULL; -} - - //========================================================================== // // @@ -262,7 +246,6 @@ bool GLWall::DoHorizon(seg_t * seg,sector_t * fs, vertex_t * v1,vertex_t * v2) } else { - type = RENDERWALL_HORIZON; hi.plane.GetFromSector(fs, true); hi.lightlevel = gl_ClampLight(fs->GetCeilingLight()); hi.colormap = fs->ColorMap; @@ -277,7 +260,7 @@ bool GLWall::DoHorizon(seg_t * seg,sector_t * fs, vertex_t * v1,vertex_t * v2) if (gl_fixedcolormap) hi.colormap.Clear(); horizon = &hi; - PutWall(0); + PutPortal(PORTALTYPE_HORIZON); } ztop[1] = ztop[0] = zbottom[0]; } @@ -291,7 +274,6 @@ bool GLWall::DoHorizon(seg_t * seg,sector_t * fs, vertex_t * v1,vertex_t * v2) } else { - type = RENDERWALL_HORIZON; hi.plane.GetFromSector(fs, false); hi.lightlevel = gl_ClampLight(fs->GetFloorLight()); hi.colormap = fs->ColorMap; @@ -306,7 +288,7 @@ bool GLWall::DoHorizon(seg_t * seg,sector_t * fs, vertex_t * v1,vertex_t * v2) if (gl_fixedcolormap) hi.colormap.Clear(); horizon = &hi; - PutWall(0); + PutPortal(PORTALTYPE_HORIZON); } } return true; @@ -516,7 +498,7 @@ void GLWall::DoTexture(int _type,seg_t * seg, int peg, gltexture->GetTexCoordInfo(&tci, seg->sidedef->GetTextureXScale(texpos), seg->sidedef->GetTextureYScale(texpos)); - type = (seg->linedef->special == Line_Mirror && _type == RENDERWALL_M1S && gl_mirrors) ? RENDERWALL_MIRROR : _type; + type = _type; float floatceilingref = FIXED2FLOAT(ceilingrefheight + tci.RowOffset(seg->sidedef->GetTextureYOffset(texpos))); if (peg) floatceilingref += tci.mRenderHeight - FIXED2FLOAT(lh + v_offset); @@ -524,13 +506,16 @@ void GLWall::DoTexture(int _type,seg_t * seg, int peg, if (!SetWallCoordinates(seg, &tci, floatceilingref, topleft, topright, bottomleft, bottomright, seg->sidedef->GetTextureXOffset(texpos))) return; - CheckTexturePosition(); - - // Add this wall to the render list - sector_t * sec = sub? sub->sector : seg->frontsector; - - if (sec->e->XFloor.lightlist.Size()==0 || gl_fixedcolormap || !gltexture) PutWall(false); - else SplitWall(sec, false); + if (seg->linedef->special == Line_Mirror && _type == RENDERWALL_M1S && gl_mirrors) + { + PutPortal(PORTALTYPE_MIRROR); + } + else + { + CheckTexturePosition(); + // Add this wall to the render list + PutWall(sub ? sub->sector : seg->frontsector, false); + } glseg=glsave; flags&=~GLT_CLAMPY; @@ -728,12 +713,15 @@ void GLWall::DoMidTexture(seg_t * seg, bool drawfogboundary, { flags |= GLWF_NOSPLITUPPER|GLWF_NOSPLITLOWER; type=RENDERWALL_FOGBOUNDARY; - PutWall(true); - if (!gltexture) + FMaterial *savetex = gltexture; + gltexture = NULL; + PutWall(seg->frontsector, true); + if (!savetex) { flags &= ~(GLWF_NOSPLITUPPER|GLWF_NOSPLITLOWER); return; } + gltexture = savetex; type=RENDERWALL_M2SNF; } else type=RENDERWALL_M2S; @@ -818,8 +806,7 @@ void GLWall::DoMidTexture(seg_t * seg, bool drawfogboundary, // Draw the stuff // // - if (realfront->e->XFloor.lightlist.Size()==0 || gl_fixedcolormap || !gltexture) split.PutWall(translucent); - else split.SplitWall(realfront, translucent); + split.PutWall(realfront, translucent); t=1; } @@ -827,13 +814,7 @@ void GLWall::DoMidTexture(seg_t * seg, bool drawfogboundary, } else { - // - // - // Draw the stuff without splitting - // - // - if (realfront->e->XFloor.lightlist.Size()==0 || gl_fixedcolormap || !gltexture) PutWall(translucent); - else SplitWall(realfront, translucent); + PutWall(realfront, translucent); } alpha=1.0f; } @@ -941,11 +922,8 @@ void GLWall::BuildFFBlock(seg_t * seg, F3DFloor * rover, RenderStyle=STYLE_Normal; translucent=false; } - - sector_t * sec = sub? sub->sector : seg->frontsector; - if (sec->e->XFloor.lightlist.Size()==0 || gl_fixedcolormap || !gltexture) PutWall(translucent); - else SplitWall(sec, translucent); + PutWall(sub? sub->sector : seg->frontsector, translucent); alpha=1.0f; lightlevel = savelight; @@ -1573,7 +1551,7 @@ void GLWall::ProcessLowerMiniseg(seg_t *seg, sector_t * frontsector, sector_t * type = RENDERWALL_BOTTOM; gltexture->GetTexCoordInfo(&tci, FRACUNIT, FRACUNIT); SetWallCoordinates(seg, &tci, FIXED2FLOAT(bfh), bfh, bfh, ffh, ffh, 0); - PutWall(false); + PutWall(seg->frontsector, false); } } }