Allow portal rendering and sky rendering (with stencils) and reflective flats with OoB and Ortho viewpoints. Works with r_radarclipper too.

This commit is contained in:
Dileep V. Reddy 2025-03-09 21:14:54 -06:00 committed by Nash Muhandes
commit 6c93c3d564
13 changed files with 300 additions and 137 deletions

View file

@ -290,15 +290,17 @@ void HWDrawInfo::AddLine (seg_t *seg, bool portalclip, FRenderState& state)
auto &clipperr = *rClipper;
angle_t startAngleR = clipperr.PointToPseudoAngle(seg->v2->fX(), seg->v2->fY());
angle_t endAngleR = clipperr.PointToPseudoAngle(seg->v1->fX(), seg->v1->fY());
angle_t paddingR = 0x00200000; // Make radar clipping more aggressive (reveal less)
if(Viewpoint.IsAllowedOoB() && r_radarclipper && !(Level->flags3 & LEVEL3_NOFOGOFWAR) && (startAngleR - endAngleR >= ANGLE_180))
{
if (!seg->backsector) clipperr.SafeAddClipRange(startAngleR, endAngleR);
if (!seg->backsector) clipperr.SafeAddClipRange(startAngleR - paddingR, endAngleR + paddingR);
else if((seg->sidedef != nullptr) && !uint8_t(seg->sidedef->Flags & WALLF_POLYOBJ) && (currentsector->sectornum != seg->backsector->sectornum))
{
if (in_area == area_default) in_area = hw_CheckViewArea(seg->v1, seg->v2, seg->frontsector, seg->backsector);
backsector = hw_FakeFlat(drawctx, seg->backsector, in_area, true);
if (hw_CheckClip(seg->sidedef, currentsector, backsector)) clipperr.SafeAddClipRange(startAngleR, endAngleR);
if (hw_CheckClip(seg->sidedef, currentsector, backsector)) clipperr.SafeAddClipRange(startAngleR - paddingR, endAngleR + paddingR);
backsector = nullptr;
}
}
@ -316,7 +318,7 @@ void HWDrawInfo::AddLine (seg_t *seg, bool portalclip, FRenderState& state)
{
currentsubsector->flags |= SSECMF_DRAWN;
}
if ((r_radarclipper || !(Level->flags3 & LEVEL3_NOFOGOFWAR)) && clipperr.SafeCheckRange(startAngleR, endAngleR))
if (Viewpoint.IsAllowedOoB() && (r_radarclipper && !(Level->flags3 & LEVEL3_NOFOGOFWAR)) && clipperr.SafeCheckRange(startAngleR, endAngleR))
{
currentsubsector->flags |= SSECMF_DRAWN;
}
@ -329,31 +331,7 @@ void HWDrawInfo::AddLine (seg_t *seg, bool portalclip, FRenderState& state)
return;
}
if (Viewpoint.IsAllowedOoB()) // No need for vertical clipping if viewpoint not allowed out of bounds
{
auto &clipperv = *vClipper;
angle_t startPitch = clipperv.PointToPseudoPitch(seg->v1->fX(), seg->v1->fY(), currentsector->floorplane.ZatPoint(seg->v1));
angle_t endPitch = clipperv.PointToPseudoPitch(seg->v1->fX(), seg->v1->fY(), currentsector->ceilingplane.ZatPoint(seg->v1));
angle_t startPitch2 = clipperv.PointToPseudoPitch(seg->v2->fX(), seg->v2->fY(), currentsector->floorplane.ZatPoint(seg->v2));
angle_t endPitch2 = clipperv.PointToPseudoPitch(seg->v2->fX(), seg->v2->fY(), currentsector->ceilingplane.ZatPoint(seg->v2));
angle_t temp;
// Wall can be tilted from viewpoint perspective. Find vertical extent on screen in psuedopitch units (0 to 2, bottom to top)
if(int(startPitch) > int(startPitch2)) // Handle zero crossing
{
temp = startPitch; startPitch = startPitch2; startPitch2 = temp; // exchange
}
if(int(endPitch) > int(endPitch2)) // Handle zero crossing
{
temp = endPitch; endPitch = endPitch2; endPitch2 = temp; // exchange
}
if (!clipperv.SafeCheckRange(startPitch, endPitch2))
{
return;
}
}
if (!r_radarclipper || (Level->flags3 & LEVEL3_NOFOGOFWAR) || clipperr.SafeCheckRange(startAngleR, endAngleR))
if (Viewpoint.IsAllowedOoB() && (!r_radarclipper || (Level->flags3 & LEVEL3_NOFOGOFWAR) || clipperr.SafeCheckRange(startAngleR, endAngleR)))
currentsubsector->flags |= SSECMF_DRAWN;
uint8_t ispoly = uint8_t(seg->sidedef->Flags & WALLF_POLYOBJ);
@ -361,7 +339,7 @@ void HWDrawInfo::AddLine (seg_t *seg, bool portalclip, FRenderState& state)
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
{
@ -388,7 +366,7 @@ void HWDrawInfo::AddLine (seg_t *seg, bool portalclip, FRenderState& state)
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);
}
}
@ -732,8 +710,8 @@ void HWDrawInfo::DoSubsector(subsector_t * sub, FRenderState& state)
if(Viewpoint.IsAllowedOoB() && sector->isSecret() && sector->wasSecret() && !r_radarclipper) return;
// cull everything if subsector outside all clippers
if ((sub->polys == nullptr) && (!Viewpoint.IsOrtho() || !((Level->flags3 & LEVEL3_NOFOGOFWAR) || !r_radarclipper)))
// cull everything if subsector outside all relevant clippers
if ((sub->polys == nullptr))
{
auto &clipper = *mClipper;
auto &clipperv = *vClipper;
@ -742,7 +720,10 @@ void HWDrawInfo::DoSubsector(subsector_t * sub, FRenderState& state)
seg_t * seg = sub->firstline;
bool anglevisible = false;
bool pitchvisible = !(Viewpoint.IsAllowedOoB()); // No vertical clipping if viewpoint is not allowed out of bounds
bool radarvisible = false;
bool radarvisible = !(Viewpoint.IsAllowedOoB()) || !r_radarclipper || (Level->flags3 & LEVEL3_NOFOGOFWAR) || ((sub->flags & SSECMF_DRAWN) && !deathmatch);
bool ceilreflect = (mCurrentPortal && strcmp(mCurrentPortal->GetName(), "Planemirror ceiling"));
bool floorreflect = (mCurrentPortal && strcmp(mCurrentPortal->GetName(), "Planemirror floor"));
double planez = (ceilreflect ? sector->ceilingplane.ZatPoint(Viewpoint.Pos) : sector->floorplane.ZatPoint(Viewpoint.Pos));
angle_t pitchtemp;
angle_t pitchmin = ANGLE_90;
angle_t pitchmax = 0;
@ -751,25 +732,43 @@ void HWDrawInfo::DoSubsector(subsector_t * sub, FRenderState& state)
{
if((seg->v1 != nullptr) && (seg->v2 != nullptr))
{
angle_t startAngle = clipper.GetClipAngle(seg->v2);
angle_t endAngle = clipper.GetClipAngle(seg->v1);
if (startAngle-endAngle >= ANGLE_180) anglevisible |= clipper.SafeCheckRange(startAngle, endAngle);
angle_t startAngleR = clipperr.PointToPseudoAngle(seg->v2->fX(), seg->v2->fY());
angle_t endAngleR = clipperr.PointToPseudoAngle(seg->v1->fX(), seg->v1->fY());
if (startAngleR-endAngleR >= ANGLE_180)
radarvisible |= (clipperr.SafeCheckRange(startAngleR, endAngleR) || (Level->flags3 & LEVEL3_NOFOGOFWAR) || ((sub->flags & SSECMF_DRAWN) && !deathmatch));
if (!anglevisible)
{
angle_t startAngle = clipper.GetClipAngle(seg->v2);
angle_t endAngle = clipper.GetClipAngle(seg->v1);
if (startAngle-endAngle >= ANGLE_180) anglevisible |= clipper.SafeCheckRange(startAngle, endAngle);
}
if (!radarvisible)
{
angle_t startAngleR = clipperr.PointToPseudoAngle(seg->v2->fX(), seg->v2->fY());
angle_t endAngleR = clipperr.PointToPseudoAngle(seg->v1->fX(), seg->v1->fY());
if (startAngleR-endAngleR >= ANGLE_180) radarvisible |= clipperr.SafeCheckRange(startAngleR, endAngleR);
}
if (!pitchvisible)
{
pitchmin = clipperv.PointToPseudoPitch(seg->v1->fX(), seg->v1->fY(), sector->floorplane.ZatPoint(seg->v1));
pitchmax = clipperv.PointToPseudoPitch(seg->v1->fX(), seg->v1->fY(), sector->ceilingplane.ZatPoint(seg->v1));
pitchmin = clipperv.PointToPseudoPitch(seg->v1->fX(), seg->v1->fY(),
(ceilreflect || floorreflect) ?
2 * planez - sector->floorplane.ZatPoint(seg->v1) :
sector->floorplane.ZatPoint(seg->v1));
pitchmax = clipperv.PointToPseudoPitch(seg->v1->fX(), seg->v1->fY(),
(ceilreflect || floorreflect) ?
2 * planez - sector->ceilingplane.ZatPoint(seg->v1) :
sector->ceilingplane.ZatPoint(seg->v1));
pitchvisible |= clipperv.SafeCheckRange(pitchmin, pitchmax);
}
if (pitchvisible && anglevisible && radarvisible) break;
if (!pitchvisible)
{
pitchtemp = clipperv.PointToPseudoPitch(seg->v2->fX(), seg->v2->fY(), sector->floorplane.ZatPoint(seg->v2));
pitchtemp = clipperv.PointToPseudoPitch(seg->v2->fX(), seg->v2->fY(),
(ceilreflect || floorreflect) ?
2 * planez - sector->floorplane.ZatPoint(seg->v2) :
sector->floorplane.ZatPoint(seg->v2));
if (int(pitchmin) > int(pitchtemp)) pitchmin = pitchtemp;
pitchtemp = clipperv.PointToPseudoPitch(seg->v2->fX(), seg->v2->fY(), sector->ceilingplane.ZatPoint(seg->v2));
pitchtemp = clipperv.PointToPseudoPitch(seg->v2->fX(), seg->v2->fY(),
(ceilreflect || floorreflect) ?
2 * planez - sector->ceilingplane.ZatPoint(seg->v2) :
sector->ceilingplane.ZatPoint(seg->v2));
if (int(pitchmax) < int(pitchtemp)) pitchmax = pitchtemp;
pitchvisible |= clipperv.SafeCheckRange(pitchmin, pitchmax);
}
@ -838,7 +837,7 @@ void HWDrawInfo::DoSubsector(subsector_t * sub, FRenderState& state)
SetupSprite.Unclock();
}
}
if (r_dithertransparency && Viewpoint.IsAllowedOoB() && (RTnum < MAXDITHERACTORS))
if (r_dithertransparency && Viewpoint.IsAllowedOoB() && (RTnum < MAXDITHERACTORS) && mCurrentPortal == nullptr)
{
// [DVR] Not parallelizable due to variables RTnum and RenderedTargets[]
for (auto p = sector->touching_renderthings; p != nullptr; p = p->m_snext)
@ -992,8 +991,8 @@ void HWDrawInfo::RenderOrthoNoFog(FRenderState& state)
{
if (Viewpoint.IsOrtho() && ((Level->flags3 & LEVEL3_NOFOGOFWAR) || !r_radarclipper))
{
double vxdbl = Viewpoint.camera->X();
double vydbl = Viewpoint.camera->Y();
double vxdbl = Viewpoint.OffPos.X;
double vydbl = Viewpoint.OffPos.Y;
double ext = Viewpoint.camera->ViewPos->Offset.Length() ?
3.0 * Viewpoint.camera->ViewPos->Offset.Length() * tan (Viewpoint.FieldOfView.Radians()*0.5) : 100.0;
FBoundingBox viewbox(vxdbl, vydbl, ext);
@ -1018,16 +1017,8 @@ void HWDrawInfo::RenderBSP(void *node, bool drawpsprites, FRenderState& state)
viewy = FLOAT2FIXED(Viewpoint.Pos.Y);
if (r_radarclipper && !(Level->flags3 & LEVEL3_NOFOGOFWAR) && Viewpoint.IsAllowedOoB())
{
if (Viewpoint.camera->tracer != nullptr)
{
viewx = FLOAT2FIXED(Viewpoint.camera->tracer->X());
viewy = FLOAT2FIXED(Viewpoint.camera->tracer->Y());
}
else
{
viewx = FLOAT2FIXED(Viewpoint.camera->X());
viewy = FLOAT2FIXED(Viewpoint.camera->Y());
}
viewx = FLOAT2FIXED(Viewpoint.OffPos.X);
viewy = FLOAT2FIXED(Viewpoint.OffPos.Y);
}
validcount++; // used for processing sidedefs only once by the renderer.