Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Better flat visibility checks for Ortho projection. #2905

Merged
merged 7 commits into from
Mar 5, 2025
5 changes: 5 additions & 0 deletions src/gamedata/r_defs.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand Down
1 change: 1 addition & 0 deletions src/rendering/hwrenderer/hw_entrypoint.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,7 @@ sector_t* RenderViewpoint(FRenderViewpoint& mainvp, AActor* camera, IntRect* bou
bool iso_ortho = (camera->ViewPos != NULL) && (camera->ViewPos->Flags & VPSF_ORTHOGRAPHIC);
if (iso_ortho && (camera->ViewPos->Offset.Length() > 0)) inv_iso_dist = 1.0/camera->ViewPos->Offset.Length();
di->VPUniforms.mProjectionMatrix = eye.GetProjection(fov, ratio, fovratio * inv_iso_dist, iso_ortho);
di->ProjectionMatrix2 = eye.GetProjection(fov, ratio, fovratio, false); // Regular ol' perspective projection matrix

// Stereo mode specific viewpoint adjustment
vp.Pos += eye.GetViewShift(vp.HWAngles.Yaw.Degrees());
Expand Down
105 changes: 48 additions & 57 deletions src/rendering/hwrenderer/scene/hw_bsp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -287,15 +287,17 @@ void HWDrawInfo::AddLine (seg_t *seg, bool portalclip)
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(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;
}
}

Expand All @@ -313,7 +315,7 @@ void HWDrawInfo::AddLine (seg_t *seg, bool portalclip)
{
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;
}
Expand All @@ -326,39 +328,15 @@ void HWDrawInfo::AddLine (seg_t *seg, bool portalclip)
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);

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
{
Expand All @@ -385,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);
}
}
Expand Down Expand Up @@ -729,8 +707,8 @@ void HWDrawInfo::DoSubsector(subsector_t * sub)

if(Viewpoint.IsAllowedOoB() && sector->isSecret() && sector->wasSecret() && !r_radarclipper) return;

// cull everything if subsector outside vertical clipper
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;
Expand All @@ -739,7 +717,10 @@ void HWDrawInfo::DoSubsector(subsector_t * sub)
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;
Expand All @@ -748,25 +729,43 @@ void HWDrawInfo::DoSubsector(subsector_t * sub)
{
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);
}
Expand Down Expand Up @@ -835,7 +834,7 @@ void HWDrawInfo::DoSubsector(subsector_t * sub)
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)
Expand Down Expand Up @@ -988,8 +987,8 @@ void HWDrawInfo::RenderOrthoNoFog()
{
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);
Expand All @@ -1014,16 +1013,8 @@ void HWDrawInfo::RenderBSP(void *node, bool drawpsprites)
viewy = FLOAT2FIXED(Viewpoint.Pos.Y);
if (r_radarclipper && !(Level->flags3 & LEVEL3_NOFOGOFWAR) && Viewpoint.IsAllowedOoB())
{
if (Viewpoint.camera->tracer != NULL)
{
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.
Expand Down
18 changes: 5 additions & 13 deletions src/rendering/hwrenderer/scene/hw_clipper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -394,18 +394,10 @@ angle_t Clipper::PointToPseudoAngle(double x, double y)
{
double vecx = x - viewpoint->Pos.X;
double vecy = y - viewpoint->Pos.Y;
if ((viewpoint->camera != NULL) && amRadar)
if (amRadar)
{
if (viewpoint->camera->tracer != NULL)
{
vecx = x - viewpoint->camera->tracer->X();
vecy = y - viewpoint->camera->tracer->Y();
}
else
{
vecx = x - viewpoint->camera->X();
vecy = y - viewpoint->camera->Y();
}
vecx = x - viewpoint->OffPos.X;
vecy = y - viewpoint->OffPos.Y;
}

if (vecx == 0 && vecy == 0)
Expand Down Expand Up @@ -467,7 +459,7 @@ angle_t Clipper::PointToPseudoPitch(double x, double y, double z)

angle_t Clipper::PointToPseudoOrthoAngle(double x, double y)
{
DVector3 disp = DVector3( x, y, 0 ) - viewpoint->camera->Pos();
DVector3 disp = DVector3(x, y, 0) - viewpoint->OffPos;
if (viewpoint->camera->ViewPos->Offset.XY().Length() == 0)
{
return AngleToPseudo( viewpoint->Angles.Yaw.BAMs() );
Expand All @@ -491,7 +483,7 @@ angle_t Clipper::PointToPseudoOrthoAngle(double x, double y)

angle_t Clipper::PointToPseudoOrthoPitch(double x, double y, double z)
{
DVector3 disp = DVector3( x, y, z ) - viewpoint->camera->Pos();
DVector3 disp = DVector3(x, y, z) - viewpoint->OffPos;
if (viewpoint->camera->ViewPos->Offset.XY().Length() > 0)
{
double yproj = viewpoint->PitchSin * disp.XY().Length() * deltaangle(disp.Angle(), viewpoint->Angles.Yaw).Cos();
Expand Down
Loading