mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-11-27 14:22:13 +00:00
- 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.
This commit is contained in:
parent
0c8a817df4
commit
c129cb3ca4
2 changed files with 153 additions and 8 deletions
|
@ -167,6 +167,9 @@ private:
|
||||||
void PutPortal(int ptype);
|
void PutPortal(int ptype);
|
||||||
void CheckTexturePosition();
|
void CheckTexturePosition();
|
||||||
|
|
||||||
|
void Put3DWall(lightlist_t * lightlist, bool translucent);
|
||||||
|
void SplitWall(sector_t * frontsector, bool translucent);
|
||||||
|
|
||||||
void SetupLights();
|
void SetupLights();
|
||||||
bool PrepareLight(texcoord * tcs, ADynamicLight * light);
|
bool PrepareLight(texcoord * tcs, ADynamicLight * light);
|
||||||
void RenderWall(int textured, unsigned int *store = NULL);
|
void RenderWall(int textured, unsigned int *store = NULL);
|
||||||
|
|
|
@ -125,10 +125,6 @@ void GLWall::PutWall(sector_t *sec, bool translucent)
|
||||||
if (gltexture == NULL) return;
|
if (gltexture == NULL) return;
|
||||||
Colormap.Clear();
|
Colormap.Clear();
|
||||||
}
|
}
|
||||||
else if (sec->e->XFloor.lightlist.Size() > 0 && gltexture != NULL)
|
|
||||||
{
|
|
||||||
lightlist = &sec->e->XFloor.lightlist;
|
|
||||||
}
|
|
||||||
|
|
||||||
CheckGlowing();
|
CheckGlowing();
|
||||||
|
|
||||||
|
@ -220,6 +216,138 @@ void GLWall::PutPortal(int ptype)
|
||||||
break;
|
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_t> & 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<lightlist.Size()-1;i++)
|
||||||
|
{
|
||||||
|
if (i<lightlist.Size()-1)
|
||||||
|
{
|
||||||
|
secplane_t &p = lightlist[i+1].plane;
|
||||||
|
if (p.a | p.b)
|
||||||
|
{
|
||||||
|
maplightbottomleft = p.ZatPoint(glseg.x1,glseg.y1);
|
||||||
|
maplightbottomright= p.ZatPoint(glseg.x2,glseg.y2);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
maplightbottomleft =
|
||||||
|
maplightbottomright= p.ZatPoint(glseg.x2,glseg.y2);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
maplightbottomright = maplightbottomleft = -32000;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The light is completely above the wall!
|
||||||
|
if (maplightbottomleft>=ztop[0] && maplightbottomright>=ztop[1])
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check for an intersection with the upper and lower planes of the wall segment
|
||||||
|
if ((maplightbottomleft<ztop[0] && maplightbottomright>ztop[1]) ||
|
||||||
|
(maplightbottomleft>ztop[0] && maplightbottomright<ztop[1]) ||
|
||||||
|
(maplightbottomleft<zbottom[0] && maplightbottomright>zbottom[1]) ||
|
||||||
|
(maplightbottomleft>zbottom[0] && maplightbottomright<zbottom[1]))
|
||||||
|
{
|
||||||
|
// Use hardware clipping if this cannot be done cleanly.
|
||||||
|
this->lightlist = &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();
|
CheckTexturePosition();
|
||||||
// Add this wall to the render list
|
// 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;
|
glseg=glsave;
|
||||||
|
@ -806,7 +937,8 @@ void GLWall::DoMidTexture(seg_t * seg, bool drawfogboundary,
|
||||||
// Draw the stuff
|
// 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;
|
t=1;
|
||||||
}
|
}
|
||||||
|
@ -814,7 +946,13 @@ void GLWall::DoMidTexture(seg_t * seg, bool drawfogboundary,
|
||||||
}
|
}
|
||||||
else
|
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;
|
alpha=1.0f;
|
||||||
}
|
}
|
||||||
|
@ -922,8 +1060,11 @@ void GLWall::BuildFFBlock(seg_t * seg, F3DFloor * rover,
|
||||||
RenderStyle=STYLE_Normal;
|
RenderStyle=STYLE_Normal;
|
||||||
translucent=false;
|
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;
|
alpha=1.0f;
|
||||||
lightlevel = savelight;
|
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)
|
void GLWall::ProcessLowerMiniseg(seg_t *seg, sector_t * frontsector, sector_t * backsector)
|
||||||
{
|
{
|
||||||
if (frontsector->GetTexture(sector_t::floor) == skyflatnum) return;
|
if (frontsector->GetTexture(sector_t::floor) == skyflatnum) return;
|
||||||
|
lightlist = NULL;
|
||||||
|
|
||||||
fixed_t ffh = frontsector->GetPlaneTexZ(sector_t::floor);
|
fixed_t ffh = frontsector->GetPlaneTexZ(sector_t::floor);
|
||||||
fixed_t bfh = backsector->GetPlaneTexZ(sector_t::floor);
|
fixed_t bfh = backsector->GetPlaneTexZ(sector_t::floor);
|
||||||
|
|
Loading…
Reference in a new issue