Making 3D-floors respond to r_dithertransparency properly.

This commit is contained in:
Dileep V. Reddy 2025-02-13 21:54:36 -07:00 committed by Rachael Alexanderson
parent 42947d04dc
commit 0acfd9661b
4 changed files with 55 additions and 7 deletions

View file

@ -1196,6 +1196,9 @@ enum
WALLF_ABSLIGHTING_BOTTOM = WALLF_ABSLIGHTING_TIER << 2, // Bottom tier light is absolute instead of relative
WALLF_DITHERTRANS = 8192, // Render with dithering transparency shader (gets reset every frame)
WALLF_DITHERTRANS_TOP = WALLF_DITHERTRANS << 0, // Top tier (gets reset every frame)
WALLF_DITHERTRANS_MID = WALLF_DITHERTRANS << 1, // Mid tier (gets reset every frame)
WALLF_DITHERTRANS_BOTTOM = WALLF_DITHERTRANS << 2, // Bottom tier (gets reset every frame)
};
struct side_t
@ -1271,6 +1274,8 @@ struct side_t
int numsegs;
int sidenum;
int dithertranscount;
int GetLightLevel (bool foggy, int baselight, int which, bool is3dlight=false, int *pfakecontrast_usedbygzdoom=NULL) const;
void SetLight(int16_t l)

View file

@ -297,6 +297,7 @@ void HWDrawInfo::AddLine (seg_t *seg, bool portalclip)
if (in_area == area_default) in_area = hw_CheckViewArea(seg->v1, seg->v2, seg->frontsector, seg->backsector);
backsector = hw_FakeFlat(seg->backsector, in_area, true);
if (hw_CheckClip(seg->sidedef, currentsector, backsector)) clipperr.SafeAddClipRange(startAngleR - paddingR, endAngleR + paddingR);
backsector = nullptr;
}
}
@ -335,7 +336,7 @@ void HWDrawInfo::AddLine (seg_t *seg, bool portalclip)
if (!seg->backsector)
{
if(!Viewpoint.IsAllowedOoB())
if (!(seg->sidedef->Flags & WALLF_DITHERTRANS)) clipper.SafeAddClipRange(startAngle, endAngle);
if (!(seg->sidedef->Flags & WALLF_DITHERTRANS_MID)) clipper.SafeAddClipRange(startAngle, endAngle);
}
else if (!ispoly) // Two-sided polyobjects never obstruct the view
{
@ -362,7 +363,7 @@ void HWDrawInfo::AddLine (seg_t *seg, bool portalclip)
if (hw_CheckClip(seg->sidedef, currentsector, backsector))
{
if(!Viewpoint.IsAllowedOoB() && !(seg->sidedef->Flags & WALLF_DITHERTRANS))
if(!Viewpoint.IsAllowedOoB() && !(seg->sidedef->Flags & WALLF_DITHERTRANS_MID))
clipper.SafeAddClipRange(startAngle, endAngle);
}
}

View file

@ -691,14 +691,28 @@ static ETraceStatus TraceCallbackForDitherTransparency(FTraceResults& res, void*
switch(res.HitType)
{
case TRACE_HitWall:
if (!(res.Line->sidedef[res.Side]->Flags & WALLF_DITHERTRANS))
{
sector_t* linesec = res.Line->sidedef[res.Side]->sector;
if (linesec->subsectorcount > 0 && (*CurMapSections)[linesec->subsectors[0]->mapsection])
{
bf = res.Line->sidedef[res.Side]->sector->floorplane.ZatPoint(res.HitPos.XY());
bc = res.Line->sidedef[res.Side]->sector->ceilingplane.ZatPoint(res.HitPos.XY());
if ((res.HitPos.Z <= bc) && (res.HitPos.Z >= bf)) res.Line->sidedef[res.Side]->Flags |= WALLF_DITHERTRANS;
if (res.Line->sidedef[!res.Side])
{
// Two sided line! So let's find out if mid, top, or bottom texture needs dithered transparency
bf = max(bf, res.Line->sidedef[!res.Side]->sector->floorplane.ZatPoint(res.HitPos.XY()));
bc = min(bc, res.Line->sidedef[!res.Side]->sector->ceilingplane.ZatPoint(res.HitPos.XY()));
if (res.HitPos.Z <= bf) res.Line->sidedef[res.Side]->Flags |= WALLF_DITHERTRANS_BOTTOM;
else if (res.HitPos.Z < bc) res.Line->sidedef[res.Side]->Flags |= WALLF_DITHERTRANS_MID;
else res.Line->sidedef[res.Side]->Flags |= WALLF_DITHERTRANS_TOP;
res.Line->sidedef[res.Side]->dithertranscount = max<int>(1, res.Line->sidedef[!res.Side]->sector->e->XFloor.ffloors.Size());
}
else if ((res.HitPos.Z <= bc) && (res.HitPos.Z >= bf))
{
res.Line->sidedef[res.Side]->Flags |= WALLF_DITHERTRANS_MID;
res.Line->sidedef[res.Side]->dithertranscount = 1;
}
}
}
break;
@ -793,6 +807,18 @@ void HWDrawInfo::SetDitherTransFlags(AActor* actor)
campos.Z -= actor->Height * 0.5;
campos.X += horix; campos.Y -= horiy;
}
// Tracers don't work on 3D floors when you are starting in the same sector (standing under them, for example)
if (actor->Sector->e->XFloor.ffloors.Size()) // 3D floor
{
F3DFloor *rover;
for (int kk = 0; kk < (int)actor->Sector->e->XFloor.ffloors.Size(); kk++)
{
rover = actor->Sector->e->XFloor.ffloors[kk];
rover->top.plane->dithertransflag = true;
rover->bottom.plane->dithertransflag = true;
}
}
}
}

View file

@ -83,15 +83,31 @@ void SetSplitPlanes(FRenderState& state, const secplane_t& top, const secplane_t
void HWWall::RenderWall(FRenderState &state, int textured)
{
if (seg->sidedef->Flags & WALLF_DITHERTRANS) state.SetEffect(EFF_DITHERTRANS);
bool ditherT = (type == RENDERWALL_BOTTOM) && (seg->sidedef->Flags & WALLF_DITHERTRANS_BOTTOM);
ditherT |= (type == RENDERWALL_TOP) && (seg->sidedef->Flags & WALLF_DITHERTRANS_TOP);
ditherT |= seg->sidedef->Flags & WALLF_DITHERTRANS_MID;
if (ditherT)
{
state.SetEffect(EFF_DITHERTRANS);
}
assert(vertcount > 0);
state.SetLightIndex(dynlightindex);
state.Draw(DT_TriangleFan, vertindex, vertcount);
vertexcount += vertcount;
if (seg->sidedef->Flags & WALLF_DITHERTRANS)
if (ditherT)
{
state.SetEffect(EFF_NONE);
seg->sidedef->Flags &= ~WALLF_DITHERTRANS; // reset this every frame
switch(type) // reset this every frame
{
case RENDERWALL_TOP:
seg->sidedef->Flags &= ~WALLF_DITHERTRANS_TOP;
break;
case RENDERWALL_BOTTOM:
seg->sidedef->Flags &= ~WALLF_DITHERTRANS_BOTTOM;
break;
default:
if (seg->sidedef->dithertranscount-- <= 0) seg->sidedef->Flags &= ~WALLF_DITHERTRANS_MID;
}
}
}