From c129cb3ca4b38f6f037521a836c04c2162a5e55f Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 4 Feb 2016 15:34:12 +0100 Subject: [PATCH] - reinstated software clipping by light volumes for walls. It turned out that using hardware clipping planes exclusively to handle this cost more than it gained. Now only the expensive or formerly impossible cases of intersecting light volumes or light volumes intersecting with the top and bottom of the wall polygon will use hardware clipping. The trivial cases will go back to software splitting. --- src/gl/scene/gl_wall.h | 3 + src/gl/scene/gl_walls.cpp | 158 ++++++++++++++++++++++++++++++++++++-- 2 files changed, 153 insertions(+), 8 deletions(-) diff --git a/src/gl/scene/gl_wall.h b/src/gl/scene/gl_wall.h index 67d75dc3d..ef770bfde 100644 --- a/src/gl/scene/gl_wall.h +++ b/src/gl/scene/gl_wall.h @@ -167,6 +167,9 @@ private: void PutPortal(int ptype); void CheckTexturePosition(); + void Put3DWall(lightlist_t * lightlist, bool translucent); + void SplitWall(sector_t * frontsector, bool translucent); + void SetupLights(); bool PrepareLight(texcoord * tcs, ADynamicLight * light); void RenderWall(int textured, unsigned int *store = NULL); diff --git a/src/gl/scene/gl_walls.cpp b/src/gl/scene/gl_walls.cpp index c8808e79b..828092b92 100644 --- a/src/gl/scene/gl_walls.cpp +++ b/src/gl/scene/gl_walls.cpp @@ -125,10 +125,6 @@ void GLWall::PutWall(sector_t *sec, bool translucent) if (gltexture == NULL) return; Colormap.Clear(); } - else if (sec->e->XFloor.lightlist.Size() > 0 && gltexture != NULL) - { - lightlist = &sec->e->XFloor.lightlist; - } CheckGlowing(); @@ -220,6 +216,138 @@ void GLWall::PutPortal(int ptype) break; } } +//========================================================================== +// +// 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(NULL, translucent); +} + +//========================================================================== +// +// Splits a wall vertically if a 3D-floor +// creates different lighting across the wall +// +//========================================================================== + +void GLWall::SplitWall(sector_t * frontsector, bool translucent) +{ + GLWall copyWall1,copyWall2; + float maplightbottomleft; + float maplightbottomright; + unsigned int i; + int origlight = lightlevel; + FColormap origcm=Colormap; + + TArray & lightlist=frontsector->e->XFloor.lightlist; + + if (glseg.x1==glseg.x2 && glseg.y1==glseg.y2) + { + return; + } + //::SplitWall.Clock(); + +#ifdef _DEBUG + if (seg->linedef-lines==1) + { + int a = 0; + } +#endif + + if (lightlist.Size()>1) + { + for(i=0;i=ztop[0] && maplightbottomright>=ztop[1]) + { + continue; + } + + // check for an intersection with the upper and lower planes of the wall segment + if ((maplightbottomleftztop[1]) || + (maplightbottomleft>ztop[0] && maplightbottomrightzbottom[1]) || + (maplightbottomleft>zbottom[0] && maplightbottomrightlightlist = &lightlist; + PutWall(frontsector, translucent); + goto out; + } + + // 3D floor is completely within this light + if (maplightbottomleft<=zbottom[0] && maplightbottomright<=zbottom[1]) + { + Put3DWall(&lightlist[i], translucent); + goto out; + } + + 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(); + goto out; + } + } + } + + Put3DWall(&lightlist[lightlist.Size()-1], translucent); + +out: + lightlevel=origlight; + Colormap=origcm; + flags &= ~GLWF_NOSPLITUPPER; + this->lightlist = NULL; + //::SplitWall.Unclock(); +} + //========================================================================== // @@ -514,7 +642,10 @@ void GLWall::DoTexture(int _type,seg_t * seg, int peg, { CheckTexturePosition(); // Add this wall to the render list - PutWall(sub ? sub->sector : seg->frontsector, false); + sector_t * sec = sub? sub->sector : seg->frontsector; + + if (sec->e->XFloor.lightlist.Size()==0 || gl_fixedcolormap) PutWall(sec, false); + else SplitWall(sec, false); } glseg=glsave; @@ -806,7 +937,8 @@ void GLWall::DoMidTexture(seg_t * seg, bool drawfogboundary, // Draw the stuff // // - split.PutWall(realfront, translucent); + if (realfront->e->XFloor.lightlist.Size()==0 || gl_fixedcolormap) split.PutWall(realfront, translucent); + else split.SplitWall(realfront, translucent); t=1; } @@ -814,7 +946,13 @@ void GLWall::DoMidTexture(seg_t * seg, bool drawfogboundary, } else { - PutWall(realfront, translucent); + // + // + // Draw the stuff without splitting + // + // + if (realfront->e->XFloor.lightlist.Size()==0 || gl_fixedcolormap) PutWall(realfront, translucent); + else SplitWall(realfront, translucent); } alpha=1.0f; } @@ -922,8 +1060,11 @@ void GLWall::BuildFFBlock(seg_t * seg, F3DFloor * rover, RenderStyle=STYLE_Normal; translucent=false; } + + sector_t * sec = sub? sub->sector : seg->frontsector; - PutWall(sub? sub->sector : seg->frontsector, translucent); + if (sec->e->XFloor.lightlist.Size()==0 || gl_fixedcolormap) PutWall(sec, translucent); + else SplitWall(sec, translucent); alpha=1.0f; lightlevel = savelight; @@ -1505,6 +1646,7 @@ void GLWall::Process(seg_t *seg, sector_t * frontsector, sector_t * backsector) void GLWall::ProcessLowerMiniseg(seg_t *seg, sector_t * frontsector, sector_t * backsector) { if (frontsector->GetTexture(sector_t::floor) == skyflatnum) return; + lightlist = NULL; fixed_t ffh = frontsector->GetPlaneTexZ(sector_t::floor); fixed_t bfh = backsector->GetPlaneTexZ(sector_t::floor);