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; }