diff --git a/src/rendering/hwrenderer/hw_entrypoint.cpp b/src/rendering/hwrenderer/hw_entrypoint.cpp index e55c041a6..0252fbc40 100644 --- a/src/rendering/hwrenderer/hw_entrypoint.cpp +++ b/src/rendering/hwrenderer/hw_entrypoint.cpp @@ -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()); diff --git a/src/rendering/hwrenderer/scene/hw_bsp.cpp b/src/rendering/hwrenderer/scene/hw_bsp.cpp index 2c1abdf7c..ced71a6fa 100644 --- a/src/rendering/hwrenderer/scene/hw_bsp.cpp +++ b/src/rendering/hwrenderer/scene/hw_bsp.cpp @@ -287,15 +287,16 @@ 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); } } @@ -313,7 +314,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; } @@ -326,31 +327,7 @@ 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); @@ -729,8 +706,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; @@ -739,7 +716,7 @@ 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); angle_t pitchtemp; angle_t pitchmin = ANGLE_90; angle_t pitchmax = 0; @@ -748,13 +725,19 @@ 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)); @@ -988,8 +971,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); @@ -1014,16 +997,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. diff --git a/src/rendering/hwrenderer/scene/hw_clipper.cpp b/src/rendering/hwrenderer/scene/hw_clipper.cpp index 059a39981..7444af309 100644 --- a/src/rendering/hwrenderer/scene/hw_clipper.cpp +++ b/src/rendering/hwrenderer/scene/hw_clipper.cpp @@ -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) @@ -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() ); @@ -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(); diff --git a/src/rendering/hwrenderer/scene/hw_drawinfo.cpp b/src/rendering/hwrenderer/scene/hw_drawinfo.cpp index 4068fbbb8..10ee57b88 100644 --- a/src/rendering/hwrenderer/scene/hw_drawinfo.cpp +++ b/src/rendering/hwrenderer/scene/hw_drawinfo.cpp @@ -160,6 +160,7 @@ void HWDrawInfo::StartScene(FRenderViewpoint &parentvp, HWViewpointUniforms *uni VPUniforms.mProjectionMatrix.loadIdentity(); VPUniforms.mViewMatrix.loadIdentity(); VPUniforms.mNormalViewMatrix.loadIdentity(); + ProjectionMatrix2.loadIdentity(); VPUniforms.mViewHeight = viewheight; if (lightmode == ELightMode::Build) { @@ -684,60 +685,70 @@ void HWDrawInfo::DrawCorona(FRenderState& state, ACorona* corona, double dist) static ETraceStatus TraceCallbackForDitherTransparency(FTraceResults& res, void* userdata) { - int* count = (int*)userdata; + BitArray* CurMapSections = (BitArray*)userdata; double bf, bc; - (*count)++; + switch(res.HitType) { case TRACE_HitWall: if (!(res.Line->sidedef[res.Side]->Flags & WALLF_DITHERTRANS)) { - 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; + 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; + } } break; case TRACE_HitFloor: - if (res.HitPos.Z == res.Sector->floorplane.ZatPoint(res.HitPos)) + if (res.Sector->subsectorcount > 0 && (*CurMapSections)[res.Sector->subsectors[0]->mapsection]) { - res.Sector->floorplane.dithertransflag = true; - } - else if (res.Sector->e->XFloor.ffloors.Size()) // Maybe it was 3D floors - { - F3DFloor *rover; - int kk; - for (kk = 0; kk < (int)res.Sector->e->XFloor.ffloors.Size(); kk++) + if (res.HitPos.Z == res.Sector->floorplane.ZatPoint(res.HitPos)) { - rover = res.Sector->e->XFloor.ffloors[kk]; - if ((rover->flags&(FF_EXISTS | FF_RENDERPLANES | FF_THISINSIDE)) == (FF_EXISTS | FF_RENDERPLANES)) + res.Sector->floorplane.dithertransflag = true; + } + else if (res.Sector->e->XFloor.ffloors.Size()) // Maybe it was 3D floors + { + F3DFloor *rover; + int kk; + for (kk = 0; kk < (int)res.Sector->e->XFloor.ffloors.Size(); kk++) { - if (res.HitPos.Z == rover->top.plane->ZatPoint(res.HitPos)) + rover = res.Sector->e->XFloor.ffloors[kk]; + if ((rover->flags&(FF_EXISTS | FF_RENDERPLANES | FF_THISINSIDE)) == (FF_EXISTS | FF_RENDERPLANES)) { - rover->top.plane->dithertransflag = true; - break; // Out of for loop + if (res.HitPos.Z == rover->top.plane->ZatPoint(res.HitPos)) + { + rover->top.plane->dithertransflag = true; + break; // Out of for loop + } } } } } break; case TRACE_HitCeiling: - if (res.HitPos.Z == res.Sector->ceilingplane.ZatPoint(res.HitPos)) + if (res.Sector->subsectorcount > 0 && (*CurMapSections)[res.Sector->subsectors[0]->mapsection]) { - res.Sector->ceilingplane.dithertransflag = true; - } - else if (res.Sector->e->XFloor.ffloors.Size()) // Maybe it was 3D floors - { - F3DFloor *rover; - int kk; - for (kk = 0; kk < (int)res.Sector->e->XFloor.ffloors.Size(); kk++) + if (res.HitPos.Z == res.Sector->ceilingplane.ZatPoint(res.HitPos)) { - rover = res.Sector->e->XFloor.ffloors[kk]; - if ((rover->flags&(FF_EXISTS | FF_RENDERPLANES | FF_THISINSIDE)) == (FF_EXISTS | FF_RENDERPLANES)) + res.Sector->ceilingplane.dithertransflag = true; + } + else if (res.Sector->e->XFloor.ffloors.Size()) // Maybe it was 3D floors + { + F3DFloor *rover; + int kk; + for (kk = 0; kk < (int)res.Sector->e->XFloor.ffloors.Size(); kk++) { - if (res.HitPos.Z == rover->bottom.plane->ZatPoint(res.HitPos)) + rover = res.Sector->e->XFloor.ffloors[kk]; + if ((rover->flags&(FF_EXISTS | FF_RENDERPLANES | FF_THISINSIDE)) == (FF_EXISTS | FF_RENDERPLANES)) { - rover->bottom.plane->dithertransflag = true; - break; // Out of for loop + if (res.HitPos.Z == rover->bottom.plane->ZatPoint(res.HitPos)) + { + rover->bottom.plane->dithertransflag = true; + break; // Out of for loop + } } } } @@ -763,13 +774,11 @@ void HWDrawInfo::SetDitherTransFlags(AActor* actor) DVector3 vvec = actorpos - Viewpoint.Pos; if (Viewpoint.IsOrtho()) { - vvec += Viewpoint.camera->Pos() - actorpos; - vvec *= 5.0; // Should be 4.0? (since zNear is behind screen by 3*dist in VREyeInfo::GetProjection()) + vvec = 5.0 * Viewpoint.camera->ViewPos->Offset.Length() * Viewpoint.ViewVector3D; // Should be 4.0? (since zNear is behind screen by 3*dist in VREyeInfo::GetProjection()) } double distance = vvec.Length() - actor->radius; DVector3 campos = actorpos - vvec; sector_t* startsec; - int count = 0; vvec = vvec.Unit(); campos.X -= horix; campos.Y += horiy; campos.Z += actor->Height * 0.25; @@ -777,10 +786,10 @@ void HWDrawInfo::SetDitherTransFlags(AActor* actor) { startsec = Level->PointInRenderSubsector(campos)->sector; Trace(campos, startsec, vvec, distance, - 0, 0, actor, results, 0, TraceCallbackForDitherTransparency, &count); + 0, 0, actor, results, TRACE_PortalRestrict, TraceCallbackForDitherTransparency, &CurrentMapSections); campos.Z += actor->Height * 0.5; Trace(campos, startsec, vvec, distance, - 0, 0, actor, results, 0, TraceCallbackForDitherTransparency, &count); + 0, 0, actor, results, TRACE_PortalRestrict, TraceCallbackForDitherTransparency, &CurrentMapSections); campos.Z -= actor->Height * 0.5; campos.X += horix; campos.Y -= horiy; } diff --git a/src/rendering/hwrenderer/scene/hw_drawinfo.h b/src/rendering/hwrenderer/scene/hw_drawinfo.h index ce848e297..e4cbeb98e 100644 --- a/src/rendering/hwrenderer/scene/hw_drawinfo.h +++ b/src/rendering/hwrenderer/scene/hw_drawinfo.h @@ -150,6 +150,7 @@ struct HWDrawInfo Clipper *rClipper; // Radar clipper FRenderViewpoint Viewpoint; HWViewpointUniforms VPUniforms; // per-viewpoint uniform state + VSMatrix ProjectionMatrix2; TArray Portals; TArray Decals[2]; // the second slot is for mirrors which get rendered in a separate pass. TArray hudsprites; // These may just be stored by value. diff --git a/src/rendering/hwrenderer/scene/hw_portal.cpp b/src/rendering/hwrenderer/scene/hw_portal.cpp index b0ea3a8c9..b103f0f81 100644 --- a/src/rendering/hwrenderer/scene/hw_portal.cpp +++ b/src/rendering/hwrenderer/scene/hw_portal.cpp @@ -125,6 +125,7 @@ bool FPortalSceneState::RenderFirstSkyPortal(int recursion, HWDrawInfo *outer_di { HWPortal * best = nullptr; unsigned bestindex = 0; + bool usestencil = outer_di->Viewpoint.IsAllowedOoB(); // Find the one with the highest amount of lines. // Normally this is also the one that saves the largest amount @@ -145,7 +146,7 @@ bool FPortalSceneState::RenderFirstSkyPortal(int recursion, HWDrawInfo *outer_di } // If the portal area contains the current camera viewpoint, let's always use it because it's likely to give the largest area. - if (p->boundingBox.contains(outer_di->Viewpoint.Pos)) + if (p->boundingBox.contains(usestencil ? outer_di->Viewpoint.OffPos : outer_di->Viewpoint.Pos)) { best = p; bestindex = i; @@ -157,7 +158,13 @@ bool FPortalSceneState::RenderFirstSkyPortal(int recursion, HWDrawInfo *outer_di if (best) { portals.Delete(bestindex); - RenderPortal(best, state, false, outer_di); + if (usestencil) + { + tempmatrix = outer_di->VPUniforms.mProjectionMatrix; // ensure perspective projection matrix for skies + outer_di->VPUniforms.mProjectionMatrix = outer_di->ProjectionMatrix2; + } + RenderPortal(best, state, usestencil, outer_di); + if (usestencil) outer_di->VPUniforms.mProjectionMatrix = tempmatrix; delete best; return true; } @@ -410,20 +417,23 @@ void HWScenePortalBase::ClearClipper(HWDrawInfo *di, Clipper *clipper) // Set the clipper to the minimal visible area clipper->SafeAddClipRange(0, 0xffffffff); + auto outvp = outer_di->Viewpoint; + DVector3 outPos = clipper->amRadar ? outvp.OffPos : outvp.Pos; + angle_t padding = clipper->amRadar ? 0x00200000 : 0x00000000; // Make radar clipping more aggressive (reveal less) for (unsigned int i = 0; i < lines.Size(); i++) { - DAngle startAngle = (DVector2(lines[i].glseg.x2, lines[i].glseg.y2) - outer_di->Viewpoint.Pos).Angle() + angleOffset; - DAngle endAngle = (DVector2(lines[i].glseg.x1, lines[i].glseg.y1) - outer_di->Viewpoint.Pos).Angle() + angleOffset; + DAngle startAngle = (DVector2(lines[i].glseg.x2, lines[i].glseg.y2) - outPos).Angle() + angleOffset; + DAngle endAngle = (DVector2(lines[i].glseg.x1, lines[i].glseg.y1) - outPos).Angle() + angleOffset; if (deltaangle(endAngle, startAngle) < nullAngle) { - clipper->SafeRemoveClipRangeRealAngles(startAngle.BAMs(), endAngle.BAMs()); + clipper->SafeRemoveClipRangeRealAngles(startAngle.BAMs() + padding, endAngle.BAMs() - padding); } } // and finally clip it to the visible area angle_t a1 = di->FrustumAngle(); - if (a1 < ANGLE_180) clipper->SafeAddClipRangeRealAngles(di->Viewpoint.Angles.Yaw.BAMs() + a1, di->Viewpoint.Angles.Yaw.BAMs() - a1); + if (!clipper->amRadar && a1 < ANGLE_180) clipper->SafeAddClipRangeRealAngles(di->Viewpoint.Angles.Yaw.BAMs() + a1, di->Viewpoint.Angles.Yaw.BAMs() - a1); // lock the parts that have just been clipped out. clipper->SetSilhouette(); @@ -608,6 +618,8 @@ bool HWLineToLinePortal::Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *cl P_TranslatePortalZ(origin, vp.Pos.Z); P_TranslatePortalXY(origin, vp.Path[0].X, vp.Path[0].Y); P_TranslatePortalXY(origin, vp.Path[1].X, vp.Path[1].Y); + P_TranslatePortalXY(origin, vp.OffPos.X, vp.OffPos.Y); + P_TranslatePortalZ(origin, vp.OffPos.Z); if (!vp.showviewer && vp.camera != nullptr && P_PointOnLineSidePrecise(vp.Path[0], glport->lines[0]->mDestination) != P_PointOnLineSidePrecise(vp.Path[1], glport->lines[0]->mDestination)) { double distp = (vp.Path[0] - vp.Path[1]).Length(); diff --git a/src/rendering/hwrenderer/scene/hw_portal.h b/src/rendering/hwrenderer/scene/hw_portal.h index 29481f9e3..760b8c435 100644 --- a/src/rendering/hwrenderer/scene/hw_portal.h +++ b/src/rendering/hwrenderer/scene/hw_portal.h @@ -112,6 +112,8 @@ struct FPortalSceneState int skyboxrecursion = 0; + VSMatrix tempmatrix; + void BeginScene() { UniqueSkies.Clear(); @@ -145,7 +147,7 @@ public: virtual bool NeedDepthBuffer() { return true; } virtual void DrawContents(HWDrawInfo *di, FRenderState &state) { - if (Setup(di, state, di->mClipper)) + if (Setup(di, state, (di->Viewpoint.IsAllowedOoB() ? di->rClipper : di->mClipper))) { di->DrawScene(DM_PORTAL); Shutdown(di, state); diff --git a/src/rendering/hwrenderer/scene/hw_sky.cpp b/src/rendering/hwrenderer/scene/hw_sky.cpp index 6d77a275d..93fc827cc 100644 --- a/src/rendering/hwrenderer/scene/hw_sky.cpp +++ b/src/rendering/hwrenderer/scene/hw_sky.cpp @@ -130,7 +130,6 @@ void HWSkyInfo::init(HWDrawInfo *di, sector_t* sec, int skypos, int sky1, PalEnt void HWWall::SkyPlane(HWWallDispatcher *di, sector_t *sector, int plane, bool allowreflect) { int ptype = -1; - if (di->di && di->di->Viewpoint.IsAllowedOoB()) return; // Couldn't prevent sky portal occlusion. Skybox is bad in ortho too. FSectorPortal *sportal = sector->ValidatePortal(plane); if (sportal != nullptr && sportal->mFlags & PORTSF_INSKYBOX) sportal = nullptr; // no recursions, delete it here to simplify the following code @@ -155,6 +154,7 @@ void HWWall::SkyPlane(HWWallDispatcher *di, sector_t *sector, int plane, bool al case PORTS_PORTAL: case PORTS_LINKEDPORTAL: { + if (di->di && di->di->Viewpoint.IsAllowedOoB()) return; auto glport = sector->GetPortalGroup(plane); if (glport != NULL) { diff --git a/src/rendering/hwrenderer/scene/hw_walls.cpp b/src/rendering/hwrenderer/scene/hw_walls.cpp index 5c5e357d5..97b0c91a6 100644 --- a/src/rendering/hwrenderer/scene/hw_walls.cpp +++ b/src/rendering/hwrenderer/scene/hw_walls.cpp @@ -2181,8 +2181,6 @@ void HWWall::Process(HWWallDispatcher *di, seg_t *seg, sector_t * frontsector, s } bool isportal = seg->linedef->isVisualPortal() && seg->sidedef == seg->linedef->sidedef[0]; - // Don't render portal insides if in orthographic mode - if (di->di) isportal &= !(di->di->Viewpoint.IsOrtho()); //return; // [GZ] 3D middle textures are necessarily two-sided, even if they lack the explicit two-sided flag diff --git a/src/rendering/r_utility.cpp b/src/rendering/r_utility.cpp index cd0c3d0c2..035ac6de7 100644 --- a/src/rendering/r_utility.cpp +++ b/src/rendering/r_utility.cpp @@ -550,8 +550,12 @@ void R_InterpolateView(FRenderViewpoint& viewPoint, const player_t* const player const int prevPortalGroup = viewLvl->PointInRenderSubsector(iView->Old.Pos)->sector->PortalGroup; const int curPortalGroup = viewLvl->PointInRenderSubsector(iView->New.Pos)->sector->PortalGroup; - const DVector2 portalOffset = viewLvl->Displacements.getOffset(prevPortalGroup, curPortalGroup); - viewPoint.Pos = iView->Old.Pos * inverseTicFrac + (iView->New.Pos - portalOffset) * ticFrac; + if (viewPoint.IsAllowedOoB() && prevPortalGroup != curPortalGroup) viewPoint.Pos = iView->New.Pos; + else + { + const DVector2 portalOffset = viewLvl->Displacements.getOffset(prevPortalGroup, curPortalGroup); + viewPoint.Pos = iView->Old.Pos * inverseTicFrac + (iView->New.Pos - portalOffset) * ticFrac; + } viewPoint.Path[0] = viewPoint.Path[1] = iView->New.Pos; } } @@ -708,6 +712,18 @@ void FRenderViewpoint::SetViewAngle(const FViewWindow& viewWindow) ViewVector3D.Y = v.Y * PitchCos; ViewVector3D.Z = -PitchSin; + if (IsOrtho() || IsAllowedOoB()) // These auto-ensure that camera and camera->ViewPos exist + { + if (camera->tracer != NULL) + { + OffPos = camera->tracer->Pos(); + } + else + { + OffPos = Pos + ViewVector3D * camera->ViewPos->Offset.Length(); + } + } + if (IsOrtho() && (camera->ViewPos->Offset.XY().Length() > 0.0)) { ScreenProj = 1.34396 / camera->ViewPos->Offset.Length() / tan (FieldOfView.Radians()*0.5); // [DVR] Estimated. +/-1 should be top/bottom of screen. diff --git a/src/rendering/r_utility.h b/src/rendering/r_utility.h index d82b03e68..0c2f47833 100644 --- a/src/rendering/r_utility.h +++ b/src/rendering/r_utility.h @@ -26,6 +26,7 @@ struct FRenderViewpoint FRotator HWAngles; // Actual rotation angles for the hardware renderer DVector2 ViewVector; // HWR only: direction the camera is facing. DVector3 ViewVector3D; // 3D direction the camera is facing. + DVector3 OffPos; // Viewpoint position to use for Ortho and OoB calculations AActor *ViewActor; // either the same as camera or nullptr FLevelLocals *ViewLevel; // The level this viewpoint is on.