From 54970b60e80c5ec87bd62cc28497b6bd2f3e1e94 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 19 Jun 2018 23:16:22 +0200 Subject: [PATCH] - use locally stored viewpoint variables in the hardware renderer. - move a few variables from SceneDrawer to FRenderViewpoint. The global r_viewpoint variable is left alone now to always represent the current viewpoint to the play code. The main reason behind this change is to reduce the amount of global variables being used by the hardware renderer's scene processing code. --- src/gl/renderer/gl_renderer.cpp | 6 +- src/gl/renderer/gl_renderer.h | 3 +- src/gl/scene/gl_drawinfo.cpp | 20 +-- src/gl/scene/gl_drawinfo.h | 4 +- src/gl/scene/gl_portal.cpp | 168 ++++++++++++------------ src/gl/scene/gl_portal.h | 9 +- src/gl/scene/gl_scene.cpp | 117 ++++++----------- src/gl/scene/gl_scenedrawer.h | 9 +- src/gl/scene/gl_skydome.cpp | 3 +- src/gl/scene/gl_sprite.cpp | 2 +- src/gl/scene/gl_walls_draw.cpp | 2 +- src/hwrenderer/scene/hw_bsp.cpp | 4 +- src/hwrenderer/scene/hw_drawinfo.h | 5 +- src/hwrenderer/scene/hw_drawlist.cpp | 2 +- src/hwrenderer/scene/hw_fakeflat.cpp | 25 +++- src/hwrenderer/scene/hw_flats.cpp | 2 +- src/hwrenderer/scene/hw_portal.h | 2 +- src/hwrenderer/scene/hw_renderhacks.cpp | 14 +- src/hwrenderer/scene/hw_sky.cpp | 4 +- src/hwrenderer/scene/hw_skydome.cpp | 2 +- src/hwrenderer/scene/hw_sprites.cpp | 15 ++- src/hwrenderer/scene/hw_walls.cpp | 4 +- src/hwrenderer/scene/hw_weapon.cpp | 4 +- src/r_utility.cpp | 9 +- src/r_utility.h | 1 + src/vectors.h | 2 +- 26 files changed, 221 insertions(+), 217 deletions(-) diff --git a/src/gl/renderer/gl_renderer.cpp b/src/gl/renderer/gl_renderer.cpp index 73563d64b..c438f0934 100644 --- a/src/gl/renderer/gl_renderer.cpp +++ b/src/gl/renderer/gl_renderer.cpp @@ -89,7 +89,6 @@ FGLRenderer::FGLRenderer(OpenGLFrameBuffer *fb) mCurrentPortal = nullptr; mMirrorCount = 0; mPlaneMirrorCount = 0; - mAngles = FRotator(0.f, 0.f, 0.f); mVBO = nullptr; mSkyVBO = nullptr; mShaderManager = nullptr; @@ -326,7 +325,7 @@ sector_t *FGLRenderer::RenderView(player_t* player) GLSceneDrawer drawer; mShadowMap.Update(); - retsec = drawer.RenderViewpoint(player->camera, NULL, r_viewpoint.FieldOfView.Degrees, ratio, fovratio, true, true); + retsec = drawer.RenderViewpoint(r_viewpoint, player->camera, NULL, r_viewpoint.FieldOfView.Degrees, ratio, fovratio, true, true); } All.Unclock(); return retsec; @@ -354,7 +353,8 @@ void FGLRenderer::RenderTextureView(FCanvasTexture *tex, AActor *Viewpoint, doub bounds.height = FHardwareTexture::GetTexDimension(gltex->GetHeight()); GLSceneDrawer drawer; - drawer.RenderViewpoint(Viewpoint, &bounds, FOV, (float)width / height, (float)width / height, false, false); + FRenderViewpoint texvp; + drawer.RenderViewpoint(texvp, Viewpoint, &bounds, FOV, (float)width / height, (float)width / height, false, false); EndOffscreen(); diff --git a/src/gl/renderer/gl_renderer.h b/src/gl/renderer/gl_renderer.h index e74ea4d6c..29e4e081d 100644 --- a/src/gl/renderer/gl_renderer.h +++ b/src/gl/renderer/gl_renderer.h @@ -69,7 +69,6 @@ public: GLPortal *mCurrentPortal; int mMirrorCount; int mPlaneMirrorCount; - float mCurrentFoV; FShaderManager *mShaderManager; FSamplerManager *mSamplerManager; unsigned int mFBID; @@ -104,7 +103,7 @@ public: FShadowMap mShadowMap; - FRotator mAngles; + //FRotator mAngles; FFlatVertexBuffer *mVBO; FSkyVertexBuffer *mSkyVBO; diff --git a/src/gl/scene/gl_drawinfo.cpp b/src/gl/scene/gl_drawinfo.cpp index efab1d84f..60991e2fb 100644 --- a/src/gl/scene/gl_drawinfo.cpp +++ b/src/gl/scene/gl_drawinfo.cpp @@ -63,7 +63,7 @@ void FDrawInfo::DoDrawSorted(HWDrawList *dl, SortNode * head) if (dl->drawitems[head->itemindex].rendertype == GLDIT_FLAT) { z = dl->flats[dl->drawitems[head->itemindex].index]->z; - relation = z > r_viewpoint.Pos.Z ? 1 : -1; + relation = z > Viewpoint.Pos.Z ? 1 : -1; } @@ -190,13 +190,14 @@ FDrawInfo::~FDrawInfo() // OpenGL has no use for multiple clippers so use the same one for all DrawInfos. static Clipper staticClipper; -FDrawInfo *FDrawInfo::StartDrawInfo(GLSceneDrawer *drawer) +FDrawInfo *FDrawInfo::StartDrawInfo(GLSceneDrawer *drawer, FRenderViewpoint &parentvp) { FDrawInfo *di=di_list.GetNew(); di->mDrawer = drawer; di->mVBO = GLRenderer->mVBO; di->mClipper = &staticClipper; - di->mClipper->SetViewpoint(r_viewpoint); + di->Viewpoint = parentvp; + di->mClipper->SetViewpoint(di->Viewpoint); staticClipper.Clear(); di->StartScene(); return di; @@ -224,7 +225,7 @@ void FDrawInfo::StartScene() // // //========================================================================== -void FDrawInfo::EndDrawInfo() +FDrawInfo *FDrawInfo::EndDrawInfo() { FDrawInfo * di = gl_drawinfo; @@ -233,6 +234,7 @@ void FDrawInfo::EndDrawInfo() di_list.Release(di); if (gl_drawinfo == nullptr) ResetRenderDataAllocator(); + return gl_drawinfo; } @@ -342,9 +344,9 @@ void FDrawInfo::DrawFloodedPlane(wallseg * ws, float planez, sector_t * sec, boo SetFog(lightlevel, rel, &Colormap, false); gl_RenderState.SetMaterial(gltexture, CLAMP_NONE, 0, -1, false); - float fviewx = r_viewpoint.Pos.X; - float fviewy = r_viewpoint.Pos.Y; - float fviewz = r_viewpoint.Pos.Z; + float fviewx = Viewpoint.Pos.X; + float fviewy = Viewpoint.Pos.Y; + float fviewz = Viewpoint.Pos.Z; gl_RenderState.SetPlaneTextureRotation(&plane, gltexture); gl_RenderState.Apply(); @@ -395,7 +397,7 @@ void FDrawInfo::FloodUpperGap(seg_t * seg) double frontz = fakefsector->ceilingplane.ZatPoint(seg->v1); if (fakebsector->GetTexture(sector_t::ceiling)==skyflatnum) return; - if (backz < r_viewpoint.Pos.Z) return; + if (backz < Viewpoint.Pos.Z) return; if (seg->sidedef == seg->linedef->sidedef[0]) { @@ -448,7 +450,7 @@ void FDrawInfo::FloodLowerGap(seg_t * seg) if (fakebsector->GetTexture(sector_t::floor) == skyflatnum) return; - if (fakebsector->GetPlaneTexZ(sector_t::floor) > r_viewpoint.Pos.Z) return; + if (fakebsector->GetPlaneTexZ(sector_t::floor) > Viewpoint.Pos.Z) return; if (seg->sidedef == seg->linedef->sidedef[0]) { diff --git a/src/gl/scene/gl_drawinfo.h b/src/gl/scene/gl_drawinfo.h index f069f2736..e732c8c8f 100644 --- a/src/gl/scene/gl_drawinfo.h +++ b/src/gl/scene/gl_drawinfo.h @@ -106,8 +106,8 @@ struct FDrawInfo : public HWDrawInfo void ProcessLowerMinisegs(TArray &lowersegs) override; void AddSubsectorToPortal(FSectorPortalGroup *portal, subsector_t *sub) override; - static FDrawInfo *StartDrawInfo(GLSceneDrawer *drawer); - static void EndDrawInfo(); + static FDrawInfo *StartDrawInfo(GLSceneDrawer *drawer, FRenderViewpoint &parentvp); + FDrawInfo *EndDrawInfo(); gl_subsectorrendernode * GetOtherFloorPlanes(unsigned int sector) { diff --git a/src/gl/scene/gl_portal.cpp b/src/gl/scene/gl_portal.cpp index a3e457ceb..afdfc3c14 100644 --- a/src/gl/scene/gl_portal.cpp +++ b/src/gl/scene/gl_portal.cpp @@ -228,7 +228,7 @@ bool GLPortal::Start(bool usestencil, bool doquery, FDrawInfo *outer_di, FDrawIn return false; } } - *pDi = FDrawInfo::StartDrawInfo(drawer); + *pDi = FDrawInfo::StartDrawInfo(drawer, outer_di->Viewpoint); } else { @@ -257,7 +257,7 @@ bool GLPortal::Start(bool usestencil, bool doquery, FDrawInfo *outer_di, FDrawIn { if (NeedDepthBuffer()) { - *pDi = FDrawInfo::StartDrawInfo(drawer); + *pDi = FDrawInfo::StartDrawInfo(drawer, outer_di->Viewpoint); } else { @@ -268,8 +268,7 @@ bool GLPortal::Start(bool usestencil, bool doquery, FDrawInfo *outer_di, FDrawIn } // save viewpoint - savedviewpoint = r_viewpoint; - savedvisibility = r_viewpoint.camera ? r_viewpoint.camera->renderflags & RF_MAYBEINVISIBLE : ActorRenderFlags::FromInt(0); + savedvisibility = outer_di->Viewpoint.camera ? outer_di->Viewpoint.camera->renderflags & RF_MAYBEINVISIBLE : ActorRenderFlags::FromInt(0); PrevPortal = GLRenderer->mCurrentPortal; @@ -282,8 +281,8 @@ bool GLPortal::Start(bool usestencil, bool doquery, FDrawInfo *outer_di, FDrawIn inline void GLPortal::ClearClipper(FDrawInfo *di) { - FRenderViewpoint &oldvp = savedviewpoint; - DAngle angleOffset = deltaangle(oldvp.Angles.Yaw, r_viewpoint.Angles.Yaw); + auto outer_di = di->next; + DAngle angleOffset = deltaangle(outer_di->Viewpoint.Angles.Yaw, di->Viewpoint.Angles.Yaw); di->mClipper->Clear(); @@ -291,8 +290,8 @@ inline void GLPortal::ClearClipper(FDrawInfo *di) di->mClipper->SafeAddClipRange(0,0xffffffff); for (unsigned int i = 0; i < lines.Size(); i++) { - DAngle startAngle = (DVector2(lines[i].glseg.x2, lines[i].glseg.y2) - oldvp.Pos).Angle() + angleOffset; - DAngle endAngle = (DVector2(lines[i].glseg.x1, lines[i].glseg.y1) - oldvp.Pos).Angle() + angleOffset; + 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; if (deltaangle(endAngle, startAngle) < 0) { @@ -301,8 +300,8 @@ inline void GLPortal::ClearClipper(FDrawInfo *di) } // and finally clip it to the visible area - angle_t a1 = drawer->FrustumAngle(); - if (a1 < ANGLE_180) di->mClipper->SafeAddClipRangeRealAngles(r_viewpoint.Angles.Yaw.BAMs() + a1, r_viewpoint.Angles.Yaw.BAMs() - a1); + angle_t a1 = di->FrustumAngle(); + if (a1 < ANGLE_180) di->mClipper->SafeAddClipRangeRealAngles(di->Viewpoint.Angles.Yaw.BAMs() + a1, di->Viewpoint.Angles.Yaw.BAMs() - a1); // lock the parts that have just been clipped out. di->mClipper->SetSilhouette(); @@ -313,7 +312,7 @@ inline void GLPortal::ClearClipper(FDrawInfo *di) // End // //----------------------------------------------------------------------------- -void GLPortal::End(bool usestencil) +void GLPortal::End(FDrawInfo *di, bool usestencil) { bool needdepth = NeedDepthBuffer(); @@ -323,12 +322,12 @@ void GLPortal::End(bool usestencil) if (usestencil) { - if (needdepth) FDrawInfo::EndDrawInfo(); + if (needdepth) di = di->EndDrawInfo(); + auto &vp = di->Viewpoint; // Restore the old view - r_viewpoint = savedviewpoint; - if (r_viewpoint.camera != nullptr) r_viewpoint.camera->renderflags = (r_viewpoint.camera->renderflags & ~RF_MAYBEINVISIBLE) | savedvisibility; - drawer->SetupView(r_viewpoint.Pos.X, r_viewpoint.Pos.Y, r_viewpoint.Pos.Z, r_viewpoint.Angles.Yaw, !!(MirrorFlag & 1), !!(PlaneMirrorFlag & 1)); + if (vp.camera != nullptr) vp.camera->renderflags = (vp.camera->renderflags & ~RF_MAYBEINVISIBLE) | savedvisibility; + drawer->SetupView(vp, vp.Pos.X, vp.Pos.Y, vp.Pos.Z, vp.Angles.Yaw, !!(MirrorFlag & 1), !!(PlaneMirrorFlag & 1)); { ScopedColorMask colorMask(0, 0, 0, 0); // glColorMask(0, 0, 0, 0); // no graphics @@ -371,7 +370,7 @@ void GLPortal::End(bool usestencil) { if (needdepth) { - FDrawInfo::EndDrawInfo(); + di = di->EndDrawInfo(); glClear(GL_DEPTH_BUFFER_BIT); } else @@ -379,10 +378,11 @@ void GLPortal::End(bool usestencil) glEnable(GL_DEPTH_TEST); glDepthMask(true); } + auto &vp = di->Viewpoint; + // Restore the old view - r_viewpoint = savedviewpoint; - if (r_viewpoint.camera != nullptr) r_viewpoint.camera->renderflags |= savedvisibility; - drawer->SetupView(r_viewpoint.Pos.X, r_viewpoint.Pos.Y, r_viewpoint.Pos.Z, r_viewpoint.Angles.Yaw, !!(MirrorFlag&1), !!(PlaneMirrorFlag&1)); + if (vp.camera != nullptr) vp.camera->renderflags = (vp.camera->renderflags & ~RF_MAYBEINVISIBLE) | savedvisibility; + drawer->SetupView(vp, vp.Pos.X, vp.Pos.Y, vp.Pos.Z, vp.Angles.Yaw, !!(MirrorFlag & 1), !!(PlaneMirrorFlag & 1)); // This draws a valid z-buffer into the stencil's contents to ensure it // doesn't get overwritten by the level's geometry. @@ -560,36 +560,36 @@ GLPortal * GLPortal::FindPortal(const void * src) void GLSkyboxPortal::DrawContents(FDrawInfo *di) { int old_pm = PlaneMirrorMode; - int saved_extralight = r_viewpoint.extralight; if (skyboxrecursion >= 3) { ClearScreen(); return; } + auto &vp = di->Viewpoint; skyboxrecursion++; AActor *origin = portal->mSkybox; portal->mFlags |= PORTSF_INSKYBOX; - r_viewpoint.extralight = 0; + vp.extralight = 0; PlaneMirrorMode = 0; bool oldclamp = gl_RenderState.SetDepthClamp(false); - r_viewpoint.Pos = origin->InterpolatedPosition(r_viewpoint.TicFrac); - r_viewpoint.ActorPos = origin->Pos(); - r_viewpoint.Angles.Yaw += (origin->PrevAngles.Yaw + deltaangle(origin->PrevAngles.Yaw, origin->Angles.Yaw) * r_viewpoint.TicFrac); + vp.Pos = origin->InterpolatedPosition(vp.TicFrac); + vp.ActorPos = origin->Pos(); + vp.Angles.Yaw += (origin->PrevAngles.Yaw + deltaangle(origin->PrevAngles.Yaw, origin->Angles.Yaw) * vp.TicFrac); // Don't let the viewpoint be too close to a floor or ceiling double floorh = origin->Sector->floorplane.ZatPoint(origin->Pos()); double ceilh = origin->Sector->ceilingplane.ZatPoint(origin->Pos()); - if (r_viewpoint.Pos.Z < floorh + 4) r_viewpoint.Pos.Z = floorh + 4; - if (r_viewpoint.Pos.Z > ceilh - 4) r_viewpoint.Pos.Z = ceilh - 4; + if (vp.Pos.Z < floorh + 4) vp.Pos.Z = floorh + 4; + if (vp.Pos.Z > ceilh - 4) vp.Pos.Z = ceilh - 4; - r_viewpoint.ViewActor = origin; + vp.ViewActor = origin; inskybox = true; - drawer->SetupView(r_viewpoint.Pos.X, r_viewpoint.Pos.Y, r_viewpoint.Pos.Z, r_viewpoint.Angles.Yaw, !!(MirrorFlag & 1), !!(PlaneMirrorFlag & 1)); + drawer->SetupView(vp, vp.Pos.X, vp.Pos.Y, vp.Pos.Z, vp.Angles.Yaw, !!(MirrorFlag & 1), !!(PlaneMirrorFlag & 1)); di->SetViewArea(); ClearClipper(di); @@ -602,7 +602,6 @@ void GLSkyboxPortal::DrawContents(FDrawInfo *di) skyboxrecursion--; PlaneMirrorMode = old_pm; - r_viewpoint.extralight = saved_extralight; } //----------------------------------------------------------------------------- @@ -688,21 +687,22 @@ void GLSectorStackPortal::SetupCoverage(FDrawInfo *di) void GLSectorStackPortal::DrawContents(FDrawInfo *di) { FSectorPortalGroup *portal = origin; + auto &vp = di->Viewpoint; - r_viewpoint.Pos += origin->mDisplacement; - r_viewpoint.ActorPos += origin->mDisplacement; - r_viewpoint.ViewActor = nullptr; + vp.Pos += origin->mDisplacement; + vp.ActorPos += origin->mDisplacement; + vp.ViewActor = nullptr; // avoid recursions! if (origin->plane != -1) screen->instack[origin->plane]++; - drawer->SetupView(r_viewpoint.Pos.X, r_viewpoint.Pos.Y, r_viewpoint.Pos.Z, r_viewpoint.Angles.Yaw, !!(MirrorFlag&1), !!(PlaneMirrorFlag&1)); + drawer->SetupView(vp, vp.Pos.X, vp.Pos.Y, vp.Pos.Z, vp.Angles.Yaw, !!(MirrorFlag&1), !!(PlaneMirrorFlag&1)); SetupCoverage(di); ClearClipper(di); // If the viewpoint is not within the portal, we need to invalidate the entire clip area. // The portal will re-validate the necessary parts when its subsectors get traversed. - subsector_t *sub = R_PointInSubsector(r_viewpoint.Pos); + subsector_t *sub = R_PointInSubsector(vp.Pos); if (!(di->ss_renderflags[sub->Index()] & SSRF_SEEN)) { di->mClipper->SafeAddClipRange(0, ANGLE_MAX); @@ -740,18 +740,19 @@ void GLPlaneMirrorPortal::DrawContents(FDrawInfo *di) // A plane mirror needs to flip the portal exclusion logic because inside the mirror, up is down and down is up. std::swap(screen->instack[sector_t::floor], screen->instack[sector_t::ceiling]); + auto &vp = di->Viewpoint; int old_pm = PlaneMirrorMode; // the player is always visible in a mirror. - r_viewpoint.showviewer = true; + vp.showviewer = true; - double planez = origin->ZatPoint(r_viewpoint.Pos); - r_viewpoint.Pos.Z = 2 * planez - r_viewpoint.Pos.Z; - r_viewpoint.ViewActor = nullptr; + double planez = origin->ZatPoint(vp.Pos); + vp.Pos.Z = 2 * planez - vp.Pos.Z; + vp.ViewActor = nullptr; PlaneMirrorMode = origin->fC() < 0 ? -1 : 1; PlaneMirrorFlag++; - drawer->SetupView(r_viewpoint.Pos.X, r_viewpoint.Pos.Y, r_viewpoint.Pos.Z, r_viewpoint.Angles.Yaw, !!(MirrorFlag & 1), !!(PlaneMirrorFlag & 1)); + drawer->SetupView(vp, vp.Pos.X, vp.Pos.Y, vp.Pos.Z, vp.Angles.Yaw, !!(MirrorFlag & 1), !!(PlaneMirrorFlag & 1)); ClearClipper(di); di->UpdateCurrentMapSection(); @@ -808,14 +809,14 @@ void GLLinePortal::PopState() gl_RenderState.EnableClipLine(e != 0); } -int GLLinePortal::ClipSeg(seg_t *seg) +int GLLinePortal::ClipSeg(seg_t *seg, const DVector3 &viewpos) { line_t *linedef = seg->linedef; if (!linedef) { return PClip_Inside; // should be handled properly. } - return P_ClipLineToPortal(linedef, line(), r_viewpoint.Pos) ? PClip_InFront : PClip_Inside; + return P_ClipLineToPortal(linedef, line(), viewpos) ? PClip_InFront : PClip_Inside; } int GLLinePortal::ClipSubsector(subsector_t *sub) @@ -861,35 +862,36 @@ void GLMirrorPortal::DrawContents(FDrawInfo *di) return; } + auto &vp = di->Viewpoint; di->UpdateCurrentMapSection(); di->mClipPortal = this; - DAngle StartAngle = r_viewpoint.Angles.Yaw; - DVector3 StartPos = r_viewpoint.Pos; + DAngle StartAngle = vp.Angles.Yaw; + DVector3 StartPos = vp.Pos; vertex_t *v1 = linedef->v1; vertex_t *v2 = linedef->v2; // the player is always visible in a mirror. - r_viewpoint.showviewer = true; + vp.showviewer = true; // Reflect the current view behind the mirror. if (linedef->Delta().X == 0) { // vertical mirror - r_viewpoint.Pos.X = 2 * v1->fX() - StartPos.X; + vp.Pos.X = 2 * v1->fX() - StartPos.X; // Compensation for reendering inaccuracies - if (StartPos.X < v1->fX()) r_viewpoint.Pos.X -= 0.1; - else r_viewpoint.Pos.X += 0.1; + if (StartPos.X < v1->fX()) vp.Pos.X -= 0.1; + else vp.Pos.X += 0.1; } else if (linedef->Delta().Y == 0) { // horizontal mirror - r_viewpoint.Pos.Y = 2*v1->fY() - StartPos.Y; + vp.Pos.Y = 2*v1->fY() - StartPos.Y; // Compensation for reendering inaccuracies - if (StartPos.YfY()) r_viewpoint.Pos.Y -= 0.1; - else r_viewpoint.Pos.Y += 0.1; + if (StartPos.YfY()) vp.Pos.Y -= 0.1; + else vp.Pos.Y += 0.1; } else { @@ -906,27 +908,27 @@ void GLMirrorPortal::DrawContents(FDrawInfo *di) // the above two cases catch len == 0 double r = ((x - x1)*dx + (y - y1)*dy) / (dx*dx + dy*dy); - r_viewpoint.Pos.X = (x1 + r * dx)*2 - x; - r_viewpoint.Pos.Y = (y1 + r * dy)*2 - y; + vp.Pos.X = (x1 + r * dx)*2 - x; + vp.Pos.Y = (y1 + r * dy)*2 - y; // Compensation for reendering inaccuracies FVector2 v(-dx, dy); v.MakeUnit(); - r_viewpoint.Pos.X+= v[1] * renderdepth / 2; - r_viewpoint.Pos.Y+= v[0] * renderdepth / 2; + vp.Pos.X+= v[1] * renderdepth / 2; + vp.Pos.Y+= v[0] * renderdepth / 2; } - r_viewpoint.Angles.Yaw = linedef->Delta().Angle() * 2. - StartAngle; + vp.Angles.Yaw = linedef->Delta().Angle() * 2. - StartAngle; - r_viewpoint.ViewActor = nullptr; + vp.ViewActor = nullptr; MirrorFlag++; - drawer->SetupView(r_viewpoint.Pos.X, r_viewpoint.Pos.Y, r_viewpoint.Pos.Z, r_viewpoint.Angles.Yaw, !!(MirrorFlag&1), !!(PlaneMirrorFlag&1)); + drawer->SetupView(vp, vp.Pos.X, vp.Pos.Y, vp.Pos.Z, vp.Angles.Yaw, !!(MirrorFlag&1), !!(PlaneMirrorFlag&1)); di->mClipper->Clear(); - angle_t af = drawer->FrustumAngle(); - if (afmClipper->SafeAddClipRangeRealAngles(r_viewpoint.Angles.Yaw.BAMs()+af, r_viewpoint.Angles.Yaw.BAMs()-af); + angle_t af = di->FrustumAngle(); + if (afmClipper->SafeAddClipRangeRealAngles(vp.Angles.Yaw.BAMs()+af, vp.Angles.Yaw.BAMs()-af); di->mClipper->SafeAddClipRange(linedef->v1, linedef->v2); @@ -961,27 +963,27 @@ void GLLineToLinePortal::DrawContents(FDrawInfo *di) ClearScreen(); return; } - + auto &vp = di->Viewpoint; di->mClipPortal = this; line_t *origin = glport->lines[0]->mOrigin; - P_TranslatePortalXY(origin, r_viewpoint.Pos.X, r_viewpoint.Pos.Y); - P_TranslatePortalXY(origin, r_viewpoint.ActorPos.X, r_viewpoint.ActorPos.Y); - P_TranslatePortalAngle(origin, r_viewpoint.Angles.Yaw); - P_TranslatePortalZ(origin, r_viewpoint.Pos.Z); - P_TranslatePortalXY(origin, r_viewpoint.Path[0].X, r_viewpoint.Path[0].Y); - P_TranslatePortalXY(origin, r_viewpoint.Path[1].X, r_viewpoint.Path[1].Y); - if (!r_viewpoint.showviewer && r_viewpoint.camera != nullptr && P_PointOnLineSidePrecise(r_viewpoint.Path[0], glport->lines[0]->mDestination) != P_PointOnLineSidePrecise(r_viewpoint.Path[1], glport->lines[0]->mDestination)) + P_TranslatePortalXY(origin, vp.Pos.X, vp.Pos.Y); + P_TranslatePortalXY(origin, vp.ActorPos.X, vp.ActorPos.Y); + P_TranslatePortalAngle(origin, vp.Angles.Yaw); + 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); + 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 = (r_viewpoint.Path[0] - r_viewpoint.Path[1]).Length(); + double distp = (vp.Path[0] - vp.Path[1]).Length(); if (distp > EQUAL_EPSILON) { - double dist1 = (r_viewpoint.Pos - r_viewpoint.Path[0]).Length(); - double dist2 = (r_viewpoint.Pos - r_viewpoint.Path[1]).Length(); + double dist1 = (vp.Pos - vp.Path[0]).Length(); + double dist2 = (vp.Pos - vp.Path[1]).Length(); if (dist1 + dist2 < distp + 1) { - r_viewpoint.camera->renderflags |= RF_MAYBEINVISIBLE; + vp.camera->renderflags |= RF_MAYBEINVISIBLE; } } } @@ -997,8 +999,8 @@ void GLLineToLinePortal::DrawContents(FDrawInfo *di) di->CurrentMapSections.Set(sub->mapsection); } - r_viewpoint.ViewActor = nullptr; - drawer->SetupView(r_viewpoint.Pos.X, r_viewpoint.Pos.Y, r_viewpoint.Pos.Z, r_viewpoint.Angles.Yaw, !!(MirrorFlag&1), !!(PlaneMirrorFlag&1)); + vp.ViewActor = nullptr; + drawer->SetupView(vp, vp.Pos.X, vp.Pos.Y, vp.Pos.Z, vp.Angles.Yaw, !!(MirrorFlag&1), !!(PlaneMirrorFlag&1)); ClearClipper(di); gl_RenderState.SetClipLine(glport->lines[0]->mDestination); @@ -1034,16 +1036,16 @@ void GLLineToLinePortal::RenderAttached(FDrawInfo *di) //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- -GLHorizonPortal::GLHorizonPortal(GLHorizonInfo * pt, bool local) +GLHorizonPortal::GLHorizonPortal(GLHorizonInfo * pt, FRenderViewpoint &vp, bool local) : GLPortal(local) { origin = pt; // create the vertex data for this horizon portal. GLSectorPlane * sp = &origin->plane; - const float vx = r_viewpoint.Pos.X; - const float vy = r_viewpoint.Pos.Y; - const float vz = r_viewpoint.Pos.Z; + const float vx = vp.Pos.X; + const float vy = vp.Pos.Y; + const float vz = vp.Pos.Z; const float z = sp->Texheight; const float tz = (z - vz); @@ -1106,6 +1108,7 @@ void GLHorizonPortal::DrawContents(FDrawInfo *di) PalEntry color; player_t * player=&players[consoleplayer]; GLSectorPlane * sp = &origin->plane; + auto &vp = di->Viewpoint; gltexture=FMaterial::ValidateTexture(sp->texture, false, true); if (!gltexture) @@ -1113,7 +1116,7 @@ void GLHorizonPortal::DrawContents(FDrawInfo *di) ClearScreen(); return; } - gl_RenderState.SetCameraPos(r_viewpoint.Pos.X, r_viewpoint.Pos.Y, r_viewpoint.Pos.Z); + gl_RenderState.SetCameraPos(vp.Pos.X, vp.Pos.Y, vp.Pos.Z); if (gltexture && gltexture->tex->isFullbright()) @@ -1171,6 +1174,7 @@ void GLHorizonPortal::DrawContents(FDrawInfo *di) void GLEEHorizonPortal::DrawContents(FDrawInfo *di) { + auto &vp = di->Viewpoint; sector_t *sector = portal->mOrigin; if (sector->GetTexture(sector_t::floor) == skyflatnum || sector->GetTexture(sector_t::ceiling) == skyflatnum) @@ -1189,9 +1193,9 @@ void GLEEHorizonPortal::DrawContents(FDrawInfo *di) horz.specialcolor = 0xffffffff; if (portal->mType == PORTS_PLANE) { - horz.plane.Texheight = r_viewpoint.Pos.Z + fabs(horz.plane.Texheight); + horz.plane.Texheight = vp.Pos.Z + fabs(horz.plane.Texheight); } - GLHorizonPortal ceil(&horz, true); + GLHorizonPortal ceil(&horz, di->Viewpoint, true); ceil.DrawContents(di); } if (sector->GetTexture(sector_t::floor) != skyflatnum) @@ -1203,9 +1207,9 @@ void GLEEHorizonPortal::DrawContents(FDrawInfo *di) horz.specialcolor = 0xffffffff; if (portal->mType == PORTS_PLANE) { - horz.plane.Texheight = r_viewpoint.Pos.Z - fabs(horz.plane.Texheight); + horz.plane.Texheight = vp.Pos.Z - fabs(horz.plane.Texheight); } - GLHorizonPortal floor(&horz, true); + GLHorizonPortal floor(&horz, di->Viewpoint, true); floor.DrawContents(di); } } diff --git a/src/gl/scene/gl_portal.h b/src/gl/scene/gl_portal.h index b9d2a242d..cc5b5d09d 100644 --- a/src/gl/scene/gl_portal.h +++ b/src/gl/scene/gl_portal.h @@ -72,7 +72,6 @@ private: AActor * savedviewactor; ActorRenderFlags savedvisibility; - FRenderViewpoint savedviewpoint; GLPortal *PrevPortal; TArray mPrimIndices; @@ -84,7 +83,7 @@ protected: virtual ~GLPortal() { } bool Start(bool usestencil, bool doquery, FDrawInfo *outer_di, FDrawInfo **pDi); - void End(bool usestencil); + void End(FDrawInfo *di, bool usestencil); virtual void DrawContents(FDrawInfo *di)=0; virtual void * GetSource() const =0; // GetSource MUST be implemented! void ClearClipper(FDrawInfo *di); @@ -107,7 +106,7 @@ public: if (Start(usestencil, doquery, outer_di, &di)) { DrawContents(di); - End(usestencil); + End(di, usestencil); } } @@ -179,7 +178,7 @@ struct GLLinePortal : public GLPortal return reinterpret_cast(pv); } - virtual int ClipSeg(seg_t *seg); + virtual int ClipSeg(seg_t *seg, const DVector3 &viewpos); virtual int ClipSubsector(subsector_t *sub); virtual int ClipPoint(const DVector2 &pos); virtual bool NeedCap() { return false; } @@ -335,7 +334,7 @@ protected: public: - GLHorizonPortal(GLHorizonInfo * pt, bool local = false); + GLHorizonPortal(GLHorizonInfo * pt, FRenderViewpoint &vp, bool local = false); }; struct GLEEHorizonPortal : public GLPortal diff --git a/src/gl/scene/gl_scene.cpp b/src/gl/scene/gl_scene.cpp index a34c332ea..f11161788 100644 --- a/src/gl/scene/gl_scene.cpp +++ b/src/gl/scene/gl_scene.cpp @@ -72,26 +72,6 @@ EXTERN_CVAR (Bool, r_deathcamera) EXTERN_CVAR (Float, r_visibility) EXTERN_CVAR (Bool, r_drawvoxels) -//----------------------------------------------------------------------------- -// -// R_FrustumAngle -// -//----------------------------------------------------------------------------- -angle_t GLSceneDrawer::FrustumAngle() -{ - float tilt = fabs(GLRenderer->mAngles.Pitch.Degrees); - - // If the pitch is larger than this you can look all around at a FOV of 90° - if (tilt > 46.0f) return 0xffffffff; - - // ok, this is a gross hack that barely works... - // but at least it doesn't overestimate too much... - double floatangle = 2.0 + (45.0 + ((tilt / 1.9)))*GLRenderer->mCurrentFoV*48.0 / AspectMultiplier(r_viewwindow.WidescreenRatio) / 90.0; - angle_t a1 = DAngle(floatangle).BAMs(); - if (a1 >= ANGLE_180) return 0xffffffff; - return a1; -} - //----------------------------------------------------------------------------- // // resets the 3D viewport @@ -140,24 +120,6 @@ void GLSceneDrawer::Set3DViewport(bool mainview) glStencilOp(GL_KEEP,GL_KEEP,GL_REPLACE); } -//----------------------------------------------------------------------------- -// -// Setup the camera position -// -//----------------------------------------------------------------------------- - -void GLSceneDrawer::SetViewAngle(DAngle viewangle) -{ - FRenderViewpoint &vp = r_viewpoint; - GLRenderer->mAngles.Yaw = float(270.0-viewangle.Degrees); - DVector2 v = vp.Angles.Yaw.ToVector(); - vp.ViewVector.X = v.X; - vp.ViewVector.Y = v.Y; - - vp.SetViewAngle(r_viewwindow); -} - - //----------------------------------------------------------------------------- // // SetProjection @@ -177,15 +139,15 @@ void GLSceneDrawer::SetProjection(VSMatrix matrix) // //----------------------------------------------------------------------------- -void GLSceneDrawer::SetViewMatrix(float vx, float vy, float vz, bool mirror, bool planemirror) +void GLSceneDrawer::SetViewMatrix(const FRotator &angles, float vx, float vy, float vz, bool mirror, bool planemirror) { float mult = mirror? -1:1; float planemult = planemirror? -level.info->pixelstretch : level.info->pixelstretch; gl_RenderState.mViewMatrix.loadIdentity(); - gl_RenderState.mViewMatrix.rotate(GLRenderer->mAngles.Roll.Degrees, 0.0f, 0.0f, 1.0f); - gl_RenderState.mViewMatrix.rotate(GLRenderer->mAngles.Pitch.Degrees, 1.0f, 0.0f, 0.0f); - gl_RenderState.mViewMatrix.rotate(GLRenderer->mAngles.Yaw.Degrees, 0.0f, mult, 0.0f); + gl_RenderState.mViewMatrix.rotate(angles.Roll.Degrees, 0.0f, 0.0f, 1.0f); + gl_RenderState.mViewMatrix.rotate(angles.Pitch.Degrees, 1.0f, 0.0f, 0.0f); + gl_RenderState.mViewMatrix.rotate(angles.Yaw.Degrees, 0.0f, mult, 0.0f); gl_RenderState.mViewMatrix.translate(vx * mult, -vz * planemult , -vy); gl_RenderState.mViewMatrix.scale(-mult, planemult, 1); } @@ -197,10 +159,10 @@ void GLSceneDrawer::SetViewMatrix(float vx, float vy, float vz, bool mirror, boo // Setup the view rotation matrix for the given viewpoint // //----------------------------------------------------------------------------- -void GLSceneDrawer::SetupView(float vx, float vy, float vz, DAngle va, bool mirror, bool planemirror) +void GLSceneDrawer::SetupView(FRenderViewpoint &vp, float vx, float vy, float vz, DAngle va, bool mirror, bool planemirror) { - SetViewAngle(va); - SetViewMatrix(vx, vy, vz, mirror, planemirror); + vp.SetViewAngle(r_viewwindow); + SetViewMatrix(vp.HWAngles, vx, vy, vz, mirror, planemirror); gl_RenderState.ApplyMatrices(); } @@ -214,8 +176,9 @@ void GLSceneDrawer::SetupView(float vx, float vy, float vz, DAngle va, bool mirr void GLSceneDrawer::CreateScene(FDrawInfo *di) { - angle_t a1 = FrustumAngle(); - di->mClipper->SafeAddClipRangeRealAngles(r_viewpoint.Angles.Yaw.BAMs() + a1, r_viewpoint.Angles.Yaw.BAMs() - a1); + const auto &vp = di->Viewpoint; + angle_t a1 = di->FrustumAngle(); + di->mClipper->SafeAddClipRangeRealAngles(vp.Angles.Yaw.BAMs() + a1, vp.Angles.Yaw.BAMs() - a1); // reset the portal manager GLPortal::StartFrame(); @@ -230,16 +193,15 @@ void GLSceneDrawer::CreateScene(FDrawInfo *di) GLRenderer->mLights->Begin(); // Give the DrawInfo the viewpoint in fixed point because that's what the nodes are. - di->viewx = FLOAT2FIXED(r_viewpoint.Pos.X); - di->viewy = FLOAT2FIXED(r_viewpoint.Pos.Y); + di->viewx = FLOAT2FIXED(vp.Pos.X); + di->viewy = FLOAT2FIXED(vp.Pos.Y); validcount++; // used for processing sidedefs only once by the renderer. - di->mAngles = GLRenderer->mAngles; di->mShadowMap = &GLRenderer->mShadowMap; di->RenderBSPNode (level.HeadNode()); - di->PreparePlayerSprites(r_viewpoint.sector, di->in_area); + di->PreparePlayerSprites(vp.sector, di->in_area); // Process all the sprites on the current portal's back side which touch the portal. if (GLRenderer->mCurrentPortal != NULL) GLRenderer->mCurrentPortal->RenderAttached(di); @@ -269,12 +231,13 @@ void GLSceneDrawer::CreateScene(FDrawInfo *di) void GLSceneDrawer::RenderScene(FDrawInfo *di, int recursion) { + const auto &vp = di->Viewpoint; RenderAll.Clock(); glDepthMask(true); if (!gl_no_skyclear) GLPortal::RenderFirstSkyPortal(recursion, di); - gl_RenderState.SetCameraPos(r_viewpoint.Pos.X, r_viewpoint.Pos.Y, r_viewpoint.Pos.Z); + gl_RenderState.SetCameraPos(vp.Pos.X, vp.Pos.Y, vp.Pos.Z); gl_RenderState.EnableFog(true); gl_RenderState.BlendFunc(GL_ONE,GL_ZERO); @@ -379,9 +342,11 @@ void GLSceneDrawer::RenderScene(FDrawInfo *di, int recursion) void GLSceneDrawer::RenderTranslucent(FDrawInfo *di) { + const auto &vp = di->Viewpoint; + RenderAll.Clock(); - gl_RenderState.SetCameraPos(r_viewpoint.Pos.X, r_viewpoint.Pos.Y, r_viewpoint.Pos.Z); + gl_RenderState.SetCameraPos(vp.Pos.X, vp.Pos.Y, vp.Pos.Z); // final pass: translucent stuff gl_RenderState.AlphaFunc(GL_GEQUAL, gl_mask_sprite_threshold); @@ -414,6 +379,7 @@ void GLSceneDrawer::DrawScene(FDrawInfo *di, int drawmode) { static int recursion=0; static int ssao_portals_available = 0; + const auto &vp = di->Viewpoint; bool applySSAO = false; if (drawmode == DM_MAINVIEW) @@ -431,11 +397,11 @@ void GLSceneDrawer::DrawScene(FDrawInfo *di, int drawmode) ssao_portals_available--; } - if (r_viewpoint.camera != nullptr) + if (vp.camera != nullptr) { - ActorRenderFlags savedflags = r_viewpoint.camera->renderflags; + ActorRenderFlags savedflags = vp.camera->renderflags; CreateScene(di); - r_viewpoint.camera->renderflags = savedflags; + vp.camera->renderflags = savedflags; } else { @@ -527,7 +493,7 @@ void GLSceneDrawer::ProcessScene(FDrawInfo *di, bool toscreen) iter_dlightf = iter_dlight = draw_dlight = draw_dlightf = 0; GLPortal::BeginScene(); - int mapsection = R_PointInSubsector(r_viewpoint.Pos)->mapsection; + int mapsection = R_PointInSubsector(di->Viewpoint.Pos)->mapsection; di->CurrentMapSections.Set(mapsection); GLRenderer->mCurrentPortal = nullptr; DrawScene(di, toscreen ? DM_MAINVIEW : DM_OFFSCREEN); @@ -540,37 +506,37 @@ void GLSceneDrawer::ProcessScene(FDrawInfo *di, bool toscreen) // //----------------------------------------------------------------------------- -sector_t * GLSceneDrawer::RenderViewpoint (AActor * camera, IntRect * bounds, float fov, float ratio, float fovratio, bool mainview, bool toscreen) +sector_t * GLSceneDrawer::RenderViewpoint (FRenderViewpoint &mainvp, AActor * camera, IntRect * bounds, float fov, float ratio, float fovratio, bool mainview, bool toscreen) { sector_t * lviewsector; GLRenderer->mSceneClearColor[0] = 0.0f; GLRenderer->mSceneClearColor[1] = 0.0f; GLRenderer->mSceneClearColor[2] = 0.0f; - R_SetupFrame (r_viewpoint, r_viewwindow, camera); + R_SetupFrame (mainvp, r_viewwindow, camera); GLRenderer->mGlobVis = R_GetGlobVis(r_viewwindow, r_visibility); // We have to scale the pitch to account for the pixel stretching, because the playsim doesn't know about this and treats it as 1:1. - double radPitch = r_viewpoint.Angles.Pitch.Normalized180().Radians(); + double radPitch = mainvp.Angles.Pitch.Normalized180().Radians(); double angx = cos(radPitch); double angy = sin(radPitch) * level.info->pixelstretch; double alen = sqrt(angx*angx + angy*angy); - GLRenderer->mAngles.Pitch = (float)RAD2DEG(asin(angy / alen)); - GLRenderer->mAngles.Roll.Degrees = r_viewpoint.Angles.Roll.Degrees; + mainvp.HWAngles.Pitch = (float)RAD2DEG(asin(angy / alen)); + mainvp.HWAngles.Roll.Degrees = mainvp.Angles.Roll.Degrees; if (camera->player && camera->player - players == consoleplayer && ((camera->player->cheats & CF_CHASECAM) || (r_deathcamera && camera->health <= 0)) && camera == camera->player->mo) { - r_viewpoint.ViewActor = nullptr; + mainvp.ViewActor = nullptr; } else { - r_viewpoint.ViewActor = camera; + mainvp.ViewActor = camera; } // 'viewsector' will not survive the rendering so it cannot be used anymore below. - lviewsector = r_viewpoint.sector; + lviewsector = mainvp.sector; // Render (potentially) multiple views for stereo 3d float viewShift[3]; @@ -583,20 +549,21 @@ sector_t * GLSceneDrawer::RenderViewpoint (AActor * camera, IntRect * bounds, fl screen->SetViewportRects(bounds); Set3DViewport(mainview); GLRenderer->mDrawingScene2D = true; - GLRenderer->mCurrentFoV = fov; - FDrawInfo *di = FDrawInfo::StartDrawInfo(this); + FDrawInfo *di = FDrawInfo::StartDrawInfo(this, mainvp); + auto vp = di->Viewpoint; di->SetViewArea(); - auto cm = di->SetFullbrightFlags(mainview ? r_viewpoint.camera->player : nullptr); + auto cm = di->SetFullbrightFlags(mainview ? vp.camera->player : nullptr); + di->Viewpoint.FieldOfView = fov; // Set the real FOV for the current scene (it's not necessarily the same as the global setting in r_viewpoint) // Stereo mode specific perspective projection SetProjection( eye->GetProjection(fov, ratio, fovratio) ); // SetProjection(fov, ratio, fovratio); // switch to perspective mode and set up clipper - SetViewAngle(r_viewpoint.Angles.Yaw); + vp.SetViewAngle(r_viewwindow); // Stereo mode specific viewpoint adjustment - temporarily shifts global ViewPos - eye->GetViewShift(GLRenderer->mAngles.Yaw.Degrees, viewShift); - ScopedViewShifter viewShifter(r_viewpoint.Pos, viewShift); - SetViewMatrix(r_viewpoint.Pos.X, r_viewpoint.Pos.Y, r_viewpoint.Pos.Z, false, false); + eye->GetViewShift(vp.HWAngles.Yaw.Degrees, viewShift); + ScopedViewShifter viewShifter(vp.Pos, viewShift); + SetViewMatrix(vp.HWAngles, vp.Pos.X, vp.Pos.Y, vp.Pos.Z, false, false); gl_RenderState.ApplyMatrices(); ProcessScene(di, toscreen); @@ -617,7 +584,7 @@ sector_t * GLSceneDrawer::RenderViewpoint (AActor * camera, IntRect * bounds, fl gl_RenderState.ApplyMatrices(); } } - FDrawInfo::EndDrawInfo(); + di->EndDrawInfo(); GLRenderer->mDrawingScene2D = false; if (!stereo3dMode.IsMono()) GLRenderer->mBuffers->BlitToEyeTexture(eye_ix); @@ -654,7 +621,9 @@ void GLSceneDrawer::WriteSavePic (player_t *player, FileWriter *file, int width, GLRenderer->mVBO->Reset(); GLRenderer->mLights->Clear(); - sector_t *viewsector = RenderViewpoint(players[consoleplayer].camera, &bounds, r_viewpoint.FieldOfView.Degrees, 1.6f, 1.6f, true, false); + // This shouldn't overwrite the global viewpoint even for a short time. + FRenderViewpoint savevp; + sector_t *viewsector = RenderViewpoint(savevp, players[consoleplayer].camera, &bounds, r_viewpoint.FieldOfView.Degrees, 1.6f, 1.6f, true, false); glDisable(GL_STENCIL_TEST); gl_RenderState.SetSoftLightLevel(-1); GLRenderer->CopyToBackbuffer(&bounds, false); diff --git a/src/gl/scene/gl_scenedrawer.h b/src/gl/scene/gl_scenedrawer.h index 3f088fd6b..2382c550d 100644 --- a/src/gl/scene/gl_scenedrawer.h +++ b/src/gl/scene/gl_scenedrawer.h @@ -28,11 +28,8 @@ public: GLPortal::drawer = this; } - angle_t FrustumAngle(); - - void SetViewMatrix(float vx, float vy, float vz, bool mirror, bool planemirror); - void SetupView(float vx, float vy, float vz, DAngle va, bool mirror, bool planemirror); - void SetViewAngle(DAngle viewangle); + void SetViewMatrix(const FRotator &angles, float vx, float vy, float vz, bool mirror, bool planemirror); + void SetupView(FRenderViewpoint &vp, float vx, float vy, float vz, DAngle va, bool mirror, bool planemirror); void SetProjection(VSMatrix matrix); void Set3DViewport(bool mainview); void Reset3DViewport(); @@ -41,7 +38,7 @@ public: void EndDrawScene(FDrawInfo *di, sector_t * viewsector); void DrawEndScene2D(FDrawInfo *di, sector_t * viewsector); - sector_t *RenderViewpoint(AActor * camera, IntRect * bounds, float fov, float ratio, float fovratio, bool mainview, bool toscreen); + sector_t *RenderViewpoint(FRenderViewpoint &mainvp, AActor * camera, IntRect * bounds, float fov, float ratio, float fovratio, bool mainview, bool toscreen); sector_t *RenderView(player_t *player); void WriteSavePic(player_t *player, FileWriter *file, int width, int height); }; diff --git a/src/gl/scene/gl_skydome.cpp b/src/gl/scene/gl_skydome.cpp index 30ff36e9e..a916c535a 100644 --- a/src/gl/scene/gl_skydome.cpp +++ b/src/gl/scene/gl_skydome.cpp @@ -212,6 +212,7 @@ static void RenderBox(FTextureID texno, FMaterial * gltex, float x_offset, bool void GLSkyPortal::DrawContents(FDrawInfo *di) { bool drawBoth = false; + auto &vp = di->Viewpoint; // We have no use for Doom lighting special handling here, so disable it for this function. int oldlightmode = ::level.lightmode; @@ -229,7 +230,7 @@ void GLSkyPortal::DrawContents(FDrawInfo *di) bool oldClamp = gl_RenderState.SetDepthClamp(true); gl_MatrixStack.Push(gl_RenderState.mViewMatrix); - drawer->SetupView(0, 0, 0, r_viewpoint.Angles.Yaw, !!(MirrorFlag & 1), !!(PlaneMirrorFlag & 1)); + drawer->SetupView(vp, 0, 0, 0, vp.Angles.Yaw, !!(MirrorFlag & 1), !!(PlaneMirrorFlag & 1)); gl_RenderState.SetVertexBuffer(GLRenderer->mSkyVBO); if (origin->texture[0] && origin->texture[0]->tex->bSkybox) diff --git a/src/gl/scene/gl_sprite.cpp b/src/gl/scene/gl_sprite.cpp index 02f477513..1a417c577 100644 --- a/src/gl/scene/gl_sprite.cpp +++ b/src/gl/scene/gl_sprite.cpp @@ -79,7 +79,7 @@ void FDrawInfo::DrawSprite(GLSprite *sprite, int pass) bool additivefog = false; bool foglayer = false; int rel = sprite->fullbright? 0 : getExtraLight(); - auto &vp = r_viewpoint; + auto &vp = Viewpoint; if (pass==GLPASS_TRANSLUCENT) { diff --git a/src/gl/scene/gl_walls_draw.cpp b/src/gl/scene/gl_walls_draw.cpp index 173c3311e..117c42823 100644 --- a/src/gl/scene/gl_walls_draw.cpp +++ b/src/gl/scene/gl_walls_draw.cpp @@ -349,7 +349,7 @@ void FDrawInfo::AddPortal(GLWall *wall, int ptype) case PORTALTYPE_HORIZON: wall->horizon = UniqueHorizons.Get(wall->horizon); portal = GLPortal::FindPortal(wall->horizon); - if (!portal) portal = new GLHorizonPortal(wall->horizon); + if (!portal) portal = new GLHorizonPortal(wall->horizon, Viewpoint); portal->AddLine(wall); break; diff --git a/src/hwrenderer/scene/hw_bsp.cpp b/src/hwrenderer/scene/hw_bsp.cpp index d44bf0679..18884dab0 100644 --- a/src/hwrenderer/scene/hw_bsp.cpp +++ b/src/hwrenderer/scene/hw_bsp.cpp @@ -89,7 +89,7 @@ void HWDrawInfo::AddLine (seg_t *seg, bool portalclip) if (portalclip) { - int clipres = mClipPortal->ClipSeg(seg); + int clipres = mClipPortal->ClipSeg(seg, Viewpoint.Pos); if (clipres == PClip_InFront) return; } @@ -353,7 +353,7 @@ void HWDrawInfo::RenderThings(subsector_t * sub, sector_t * sector) SetupSprite.Clock(); sector_t * sec=sub->sector; // Handle all things in sector. - auto &vp = r_viewpoint; + const auto &vp = Viewpoint; for (auto p = sec->touching_renderthings; p != nullptr; p = p->m_snext) { auto thing = p->m_thing; diff --git a/src/hwrenderer/scene/hw_drawinfo.h b/src/hwrenderer/scene/hw_drawinfo.h index 0de3cd359..06a42f1eb 100644 --- a/src/hwrenderer/scene/hw_drawinfo.h +++ b/src/hwrenderer/scene/hw_drawinfo.h @@ -2,6 +2,7 @@ #include #include "r_defs.h" +#include "r_utility.h" struct FSectorPortalGroup; @@ -94,9 +95,10 @@ struct HWDrawInfo int FullbrightFlags; std::atomic spriteindex; IPortal *mClipPortal; - FRotator mAngles; + //FRotator mAngles; IShadowMap *mShadowMap; Clipper *mClipper; + FRenderViewpoint Viewpoint; TArray MissingUpperTextures; TArray MissingLowerTextures; @@ -186,6 +188,7 @@ public: void PrepareTargeterSprites(); void UpdateCurrentMapSection(); + angle_t FrustumAngle(); virtual void DrawWall(GLWall *wall, int pass) = 0; virtual void DrawFlat(GLFlat *flat, int pass, bool trans) = 0; diff --git a/src/hwrenderer/scene/hw_drawlist.cpp b/src/hwrenderer/scene/hw_drawlist.cpp index 1df8d5763..c1677646b 100644 --- a/src/hwrenderer/scene/hw_drawlist.cpp +++ b/src/hwrenderer/scene/hw_drawlist.cpp @@ -688,7 +688,7 @@ SortNode * HWDrawList::DoSort(HWDrawInfo *di, SortNode * head) //========================================================================== void HWDrawList::Sort(HWDrawInfo *di) { - SortZ = r_viewpoint.Pos.Z; + SortZ = di->Viewpoint.Pos.Z; MakeSortList(); sorted = DoSort(di, SortNodes[SortNodeStart]); } diff --git a/src/hwrenderer/scene/hw_fakeflat.cpp b/src/hwrenderer/scene/hw_fakeflat.cpp index 5b877704d..3dbdff4c9 100644 --- a/src/hwrenderer/scene/hw_fakeflat.cpp +++ b/src/hwrenderer/scene/hw_fakeflat.cpp @@ -394,7 +394,7 @@ sector_t * hw_FakeFlat(sector_t * sec, sector_t * dest, area_t in_area, bool bac //----------------------------------------------------------------------------- void HWDrawInfo::SetViewArea() { - auto &vp = r_viewpoint; + auto &vp = Viewpoint; // The render_sector is better suited to represent the current position in GL vp.sector = R_PointInSubsector(vp.Pos)->render_sector; @@ -424,7 +424,7 @@ int HWDrawInfo::SetFullbrightFlags(player_t *player) if (cplayer->extralight == INT_MIN) { cm = CM_FIRSTSPECIALCOLORMAP + INVERSECOLORMAP; - r_viewpoint.extralight = 0; + Viewpoint.extralight = 0; FullbrightFlags = Fullbright; // This does never set stealth vision. } @@ -463,3 +463,24 @@ int HWDrawInfo::SetFullbrightFlags(player_t *player) return CM_DEFAULT; } } + +//----------------------------------------------------------------------------- +// +// R_FrustumAngle +// +//----------------------------------------------------------------------------- +angle_t HWDrawInfo::FrustumAngle() +{ + float tilt = fabs(Viewpoint.HWAngles.Pitch.Degrees); + + // If the pitch is larger than this you can look all around at a FOV of 90° + if (tilt > 46.0f) return 0xffffffff; + + // ok, this is a gross hack that barely works... + // but at least it doesn't overestimate too much... + double floatangle = 2.0 + (45.0 + ((tilt / 1.9)))*Viewpoint.FieldOfView.Degrees*48.0 / AspectMultiplier(r_viewwindow.WidescreenRatio) / 90.0; + angle_t a1 = DAngle(floatangle).BAMs(); + if (a1 >= ANGLE_180) return 0xffffffff; + return a1; +} + diff --git a/src/hwrenderer/scene/hw_flats.cpp b/src/hwrenderer/scene/hw_flats.cpp index 0fa14f2e1..91cb8027e 100644 --- a/src/hwrenderer/scene/hw_flats.cpp +++ b/src/hwrenderer/scene/hw_flats.cpp @@ -306,7 +306,7 @@ void GLFlat::ProcessSector(HWDrawInfo *di, sector_t * frontsector) dynlightindex = -1; uint8_t &srf = di->sectorrenderflags[sector->sectornum]; - auto &vp = r_viewpoint; + const auto &vp = di->Viewpoint; // // diff --git a/src/hwrenderer/scene/hw_portal.h b/src/hwrenderer/scene/hw_portal.h index 695daaa98..b4a313c94 100644 --- a/src/hwrenderer/scene/hw_portal.h +++ b/src/hwrenderer/scene/hw_portal.h @@ -37,7 +37,7 @@ class IPortal { public: virtual ~IPortal() {} - virtual int ClipSeg(seg_t *seg) { return PClip_Inside; } + virtual int ClipSeg(seg_t *seg, const DVector3 &viewpos) { return PClip_Inside; } virtual int ClipSubsector(subsector_t *sub) { return PClip_Inside; } virtual int ClipPoint(const DVector2 &pos) { return PClip_Inside; } virtual line_t *ClipLine() { return nullptr; } diff --git a/src/hwrenderer/scene/hw_renderhacks.cpp b/src/hwrenderer/scene/hw_renderhacks.cpp index 74c5b3f0e..7277b3704 100644 --- a/src/hwrenderer/scene/hw_renderhacks.cpp +++ b/src/hwrenderer/scene/hw_renderhacks.cpp @@ -88,7 +88,7 @@ void HWDrawInfo::ClearBuffers() void HWDrawInfo::UpdateCurrentMapSection() { - const int mapsection = R_PointInSubsector(r_viewpoint.Pos)->mapsection; + const int mapsection = R_PointInSubsector(Viewpoint.Pos)->mapsection; CurrentMapSections.Set(mapsection); } @@ -484,7 +484,7 @@ void HWDrawInfo::HandleMissingTextures(area_t in_area) HandledSubsectors.Clear(); validcount++; - if (MissingUpperTextures[i].Planez > r_viewpoint.Pos.Z) + if (MissingUpperTextures[i].Planez > Viewpoint.Pos.Z) { // close the hole only if all neighboring sectors are an exact height match // Otherwise just fill in the missing textures. @@ -556,7 +556,7 @@ void HWDrawInfo::HandleMissingTextures(area_t in_area) HandledSubsectors.Clear(); validcount++; - if (MissingLowerTextures[i].Planez < r_viewpoint.Pos.Z) + if (MissingLowerTextures[i].Planez < Viewpoint.Pos.Z) { // close the hole only if all neighboring sectors are an exact height match // Otherwise just fill in the missing textures. @@ -642,7 +642,7 @@ void HWDrawInfo::DrawUnhandledMissingTextures() // already done! if (seg->linedef->validcount == validcount) continue; // already done seg->linedef->validcount = validcount; - if (seg->frontsector->GetPlaneTexZ(sector_t::ceiling) < r_viewpoint.Pos.Z) continue; // out of sight + if (seg->frontsector->GetPlaneTexZ(sector_t::ceiling) < Viewpoint.Pos.Z) continue; // out of sight // FIXME: The check for degenerate subsectors should be more precise if (seg->PartnerSeg && (seg->PartnerSeg->Subsector->flags & SSECF_DEGENERATE)) continue; @@ -664,7 +664,7 @@ void HWDrawInfo::DrawUnhandledMissingTextures() if (seg->linedef->validcount == validcount) continue; // already done seg->linedef->validcount = validcount; if (!(sectorrenderflags[seg->backsector->sectornum] & SSRF_RENDERFLOOR)) continue; - if (seg->frontsector->GetPlaneTexZ(sector_t::floor) > r_viewpoint.Pos.Z) continue; // out of sight + if (seg->frontsector->GetPlaneTexZ(sector_t::floor) > Viewpoint.Pos.Z) continue; // out of sight if (seg->backsector->transdoor) continue; if (seg->backsector->GetTexture(sector_t::floor) == skyflatnum) continue; if (seg->backsector->ValidatePortal(sector_t::floor) != NULL) continue; @@ -757,7 +757,7 @@ bool HWDrawInfo::CollectSubsectorsFloor(subsector_t * sub, sector_t * anchor) sub->render_sector->GetPlaneTexZ(sector_t::floor) != anchor->GetPlaneTexZ(sector_t::floor) || sub->render_sector->GetFloorLight() != anchor->GetFloorLight()) { - if (sub == viewsubsector && r_viewpoint.Pos.Z < anchor->GetPlaneTexZ(sector_t::floor)) inview = true; + if (sub == viewsubsector && Viewpoint.Pos.Z < anchor->GetPlaneTexZ(sector_t::floor)) inview = true; HandledSubsectors.Push(sub); } } @@ -903,7 +903,7 @@ bool HWDrawInfo::CollectSubsectorsCeiling(subsector_t * sub, sector_t * anchor) void HWDrawInfo::HandleHackedSubsectors() { - viewsubsector = R_PointInSubsector(r_viewpoint.Pos); + viewsubsector = R_PointInSubsector(Viewpoint.Pos); // Each subsector may only be processed once in this loop! validcount++; diff --git a/src/hwrenderer/scene/hw_sky.cpp b/src/hwrenderer/scene/hw_sky.cpp index 666aeecde..57eeb0eee 100644 --- a/src/hwrenderer/scene/hw_sky.cpp +++ b/src/hwrenderer/scene/hw_sky.cpp @@ -154,7 +154,7 @@ void GLWall::SkyPlane(HWDrawInfo *di, sector_t *sector, int plane, bool allowref } else if (allowreflect && sector->GetReflect(plane) > 0) { - auto vpz = r_viewpoint.Pos.Z; + auto vpz = di->Viewpoint.Pos.Z; if ((plane == sector_t::ceiling && vpz > sector->ceilingplane.fD()) || (plane == sector_t::floor && vpz < -sector->floorplane.fD())) return; ptype = PORTALTYPE_PLANEMIRROR; @@ -341,7 +341,7 @@ void GLWall::SkyBottom(HWDrawInfo *di, seg_t * seg,sector_t * fs,sector_t * bs,v else { // Special hack for Vrack2b - if (bs->floorplane.ZatPoint(r_viewpoint.Pos) > r_viewpoint.Pos.Z) return; + if (bs->floorplane.ZatPoint(di->Viewpoint.Pos) > di->Viewpoint.Pos.Z) return; } } zbottom[0]=zbottom[1]=-32768.0f; diff --git a/src/hwrenderer/scene/hw_skydome.cpp b/src/hwrenderer/scene/hw_skydome.cpp index 1de0999f6..de8a51af1 100644 --- a/src/hwrenderer/scene/hw_skydome.cpp +++ b/src/hwrenderer/scene/hw_skydome.cpp @@ -289,7 +289,7 @@ void FSkyDomeCreator::SetupMatrices(FMaterial *tex, float x_offset, float y_offs // smaller sky textures must be tiled. We restrict it to 128 sky pixels, though modelMatrix.translate(0.f, -1250.f, 0.f); modelMatrix.scale(1.f, 128 / 230.f, 1.f); - yscale = 128 / texh; // intentionally left as integer. + yscale = float(128 / texh); // intentionally left as integer. } else if (texh < 200) { diff --git a/src/hwrenderer/scene/hw_sprites.cpp b/src/hwrenderer/scene/hw_sprites.cpp index e0f9b3bed..abdc50853 100644 --- a/src/hwrenderer/scene/hw_sprites.cpp +++ b/src/hwrenderer/scene/hw_sprites.cpp @@ -70,6 +70,7 @@ EXTERN_CVAR(Float, transsouls) bool GLSprite::CalculateVertices(HWDrawInfo *di, FVector3 *v, DVector3 *vp) { + const auto &HWAngles = di->Viewpoint.HWAngles; if (actor != nullptr && (actor->renderflags & RF_SPRITETYPEMASK) == RF_FLATSPRITE) { Matrix3x4 mat; @@ -149,7 +150,7 @@ bool GLSprite::CalculateVertices(HWDrawInfo *di, FVector3 *v, DVector3 *vp) float xrel = xcenter - vp->X; float yrel = ycenter - vp->Y; float absAngleDeg = RAD2DEG(atan2(-yrel, xrel)); - float counterRotationDeg = 270. - di->mAngles.Yaw.Degrees; // counteracts existing sprite rotation + float counterRotationDeg = 270. - HWAngles.Yaw.Degrees; // counteracts existing sprite rotation float relAngleDeg = counterRotationDeg + absAngleDeg; mat.Rotate(0, 1, 0, relAngleDeg); @@ -157,7 +158,7 @@ bool GLSprite::CalculateVertices(HWDrawInfo *di, FVector3 *v, DVector3 *vp) // [fgsfds] calculate yaw vectors float yawvecX = 0, yawvecY = 0, rollDegrees = 0; - float angleRad = (270. - di->mAngles.Yaw).Radians(); + float angleRad = (270. - HWAngles.Yaw).Radians(); if (actor) rollDegrees = Angles.Roll.Degrees; if (isFlatSprite) { @@ -181,7 +182,7 @@ bool GLSprite::CalculateVertices(HWDrawInfo *di, FVector3 *v, DVector3 *vp) if (useOffsets) mat.Translate(xx, zz, yy); if (drawWithXYBillboard) { - mat.Rotate(-sin(angleRad), 0, cos(angleRad), -di->mAngles.Pitch.Degrees); + mat.Rotate(-sin(angleRad), 0, cos(angleRad), -HWAngles.Pitch.Degrees); } mat.Rotate(cos(angleRad), 0, sin(angleRad), rollDegrees); if (useOffsets) mat.Translate(-xx, -zz, -yy); @@ -191,7 +192,7 @@ bool GLSprite::CalculateVertices(HWDrawInfo *di, FVector3 *v, DVector3 *vp) // Rotate the sprite about the vector starting at the center of the sprite // triangle strip and with direction orthogonal to where the player is looking // in the x/y plane. - mat.Rotate(-sin(angleRad), 0, cos(angleRad), -di->mAngles.Pitch.Degrees); + mat.Rotate(-sin(angleRad), 0, cos(angleRad), -HWAngles.Pitch.Degrees); } mat.Translate(-xcenter, -zcenter, -ycenter); // retreat from sprite center @@ -403,7 +404,7 @@ void GLSprite::Process(HWDrawInfo *di, AActor* thing, sector_t * sector, area_t return; } - auto &vp = r_viewpoint; + const auto &vp = di->Viewpoint; AActor *camera = vp.camera; if (thing->renderflags & RF_INVISIBLE || !thing->RenderStyle.IsVisible(thing->Alpha)) @@ -924,7 +925,7 @@ void GLSprite::ProcessParticle (HWDrawInfo *di, particle_t *particle, sector_t * } } - auto &vp = r_viewpoint; + const auto &vp = di->Viewpoint; double timefrac = vp.TicFrac; if (paused || bglobal.freeze || (level.flags2 & LEVEL2_FROZEN)) timefrac = 0.; @@ -982,7 +983,7 @@ void HWDrawInfo::ProcessActorsInPortal(FLinePortalSpan *glport, area_t in_area) TMap processcheck; if (glport->validcount == validcount) return; // only process once per frame glport->validcount = validcount; - auto &vp = r_viewpoint; + const auto &vp = Viewpoint; for (auto port : glport->lines) { line_t *line = port->mOrigin; diff --git a/src/hwrenderer/scene/hw_walls.cpp b/src/hwrenderer/scene/hw_walls.cpp index 3cb181378..6c22e560a 100644 --- a/src/hwrenderer/scene/hw_walls.cpp +++ b/src/hwrenderer/scene/hw_walls.cpp @@ -169,7 +169,7 @@ void GLWall::PutWall(HWDrawInfo *di, bool translucent) if (translucent) { flags |= GLWF_TRANSLUCENT; - ViewDistance = (r_viewpoint.Pos - (seg->linedef->v1->fPos() + seg->linedef->Delta() / 2)).XY().LengthSquared(); + ViewDistance = (di->Viewpoint.Pos - (seg->linedef->v1->fPos() + seg->linedef->Delta() / 2)).XY().LengthSquared(); } if (di->isFullbrightScene()) @@ -443,7 +443,7 @@ bool GLWall::DoHorizon(HWDrawInfo *di, seg_t * seg,sector_t * fs, vertex_t * v1, ztop[1] = ztop[0] = fs->GetPlaneTexZ(sector_t::ceiling); zbottom[1] = zbottom[0] = fs->GetPlaneTexZ(sector_t::floor); - auto vpz = r_viewpoint.Pos.Z; + auto vpz = di->Viewpoint.Pos.Z; if (vpz < fs->GetPlaneTexZ(sector_t::ceiling)) { if (vpz > fs->GetPlaneTexZ(sector_t::floor)) diff --git a/src/hwrenderer/scene/hw_weapon.cpp b/src/hwrenderer/scene/hw_weapon.cpp index 0125e3f8f..b0861e8bd 100644 --- a/src/hwrenderer/scene/hw_weapon.cpp +++ b/src/hwrenderer/scene/hw_weapon.cpp @@ -427,7 +427,7 @@ void HWDrawInfo::PreparePlayerSprites(sector_t * viewsector, area_t in_area) player_t * player = playermo->player; const bool hudModelStep = IsHUDModelForPlayerAvailable(player); - auto &vp = r_viewpoint; + const auto &vp = Viewpoint; AActor *camera = vp.camera; @@ -507,7 +507,7 @@ void HWDrawInfo::PrepareTargeterSprites() { AActor * playermo = players[consoleplayer].camera; player_t * player = playermo->player; - AActor *camera = r_viewpoint.camera; + AActor *camera = Viewpoint.camera; // this is the same as above if (!player || diff --git a/src/r_utility.cpp b/src/r_utility.cpp index 82ab62f2b..04875eb30 100644 --- a/src/r_utility.cpp +++ b/src/r_utility.cpp @@ -598,7 +598,8 @@ void R_ResetViewInterpolation () //========================================================================== // -// R_SetViewAngle +// R_SetViewAngle +// sets all values derived from the view angle. // //========================================================================== @@ -609,6 +610,12 @@ void FRenderViewpoint::SetViewAngle (const FViewWindow &viewwindow) TanSin = viewwindow.FocalTangent * Sin; TanCos = viewwindow.FocalTangent * Cos; + + DVector2 v = Angles.Yaw.ToVector(); + ViewVector.X = v.X; + ViewVector.Y = v.Y; + HWAngles.Yaw = float(270.0 - Angles.Yaw.Degrees); + } //========================================================================== diff --git a/src/r_utility.h b/src/r_utility.h index 35cedde8f..b18588ab9 100644 --- a/src/r_utility.h +++ b/src/r_utility.h @@ -21,6 +21,7 @@ struct FRenderViewpoint DVector3 Pos; // Camera position DVector3 ActorPos; // Camera actor's position DRotator Angles; // Camera angles + FRotator HWAngles; // Actual rotation angles for the hardware renderer DVector2 ViewVector; // HWR only: direction the camera is facing. AActor *ViewActor; // either the same as camera or nullptr diff --git a/src/vectors.h b/src/vectors.h index 5f20e4115..65a30345f 100644 --- a/src/vectors.h +++ b/src/vectors.h @@ -1180,7 +1180,7 @@ struct TAngle TAngle &operator= (double other) { - Degrees = other; + Degrees = (decltype(Degrees))other; return *this; }