From 7b99c883e1d2eaf2cf932e6ab3b908ac45947aa0 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 18 Jun 2016 12:14:20 +0200 Subject: [PATCH] - use the exact same semantics and methods to handle player visibility as in the software renderer. This fixes invisible player sprites in recursive line portals. --- src/gl/renderer/gl_renderer.h | 8 +++++++- src/gl/scene/gl_portal.cpp | 27 +++++++++++++-------------- src/gl/scene/gl_portal.h | 2 +- src/gl/scene/gl_scene.cpp | 22 ++++++++++++++++++---- src/gl/scene/gl_sprite.cpp | 15 ++++++--------- 5 files changed, 45 insertions(+), 29 deletions(-) diff --git a/src/gl/renderer/gl_renderer.h b/src/gl/renderer/gl_renderer.h index 3da5a22df..e8ef87157 100644 --- a/src/gl/renderer/gl_renderer.h +++ b/src/gl/renderer/gl_renderer.h @@ -53,6 +53,12 @@ struct GL_IRECT } }; +enum +{ + DM_MAINVIEW, + DM_OFFSCREEN, + DM_PORTAL +}; class FGLRenderer { @@ -106,7 +112,7 @@ public: void RenderMultipassStuff(); void RenderScene(int recursion); void RenderTranslucent(); - void DrawScene(bool toscreen = false); + void DrawScene(int drawmode); void DrawBlend(sector_t * viewsector); void DrawPSprite (player_t * player,DPSprite *psp,float sx, float sy, bool hudModelStep, int OverrideShader, bool alphatexture); diff --git a/src/gl/scene/gl_portal.cpp b/src/gl/scene/gl_portal.cpp index e4603cd1e..6082c6f4f 100644 --- a/src/gl/scene/gl_portal.cpp +++ b/src/gl/scene/gl_portal.cpp @@ -306,9 +306,10 @@ bool GLPortal::Start(bool usestencil, bool doquery) savedAngle = ViewAngle; savedviewactor=GLRenderer->mViewActor; savedviewarea=in_area; - savedshowviewer = r_showviewer; savedviewpath[0] = ViewPath[0]; savedviewpath[1] = ViewPath[1]; + savedvisibility = camera ? camera->renderflags & RF_INVISIBLE : ActorRenderFlags::FromInt(0); + PrevPortal = GLRenderer->mCurrentPortal; PrevClipPortal = GLRenderer->mClipPortal; @@ -375,7 +376,7 @@ void GLPortal::End(bool usestencil) ViewAngle = savedAngle; GLRenderer->mViewActor=savedviewactor; in_area=savedviewarea; - r_showviewer = savedshowviewer; + if (camera != nullptr) camera->renderflags = (camera->renderflags & ~RF_INVISIBLE) | savedvisibility; GLRenderer->SetupView(ViewPos.X, ViewPos.Y, ViewPos.Z, ViewAngle, !!(MirrorFlag & 1), !!(PlaneMirrorFlag & 1)); { @@ -432,7 +433,7 @@ void GLPortal::End(bool usestencil) ViewAngle = savedAngle; GLRenderer->mViewActor=savedviewactor; in_area=savedviewarea; - r_showviewer = savedshowviewer; + if (camera != nullptr) camera->renderflags |= savedvisibility; GLRenderer->SetupView(ViewPos.X, ViewPos.Y, ViewPos.Z, ViewAngle, !!(MirrorFlag&1), !!(PlaneMirrorFlag&1)); // This draws a valid z-buffer into the stencil's contents to ensure it @@ -665,7 +666,7 @@ void GLSkyboxPortal::DrawContents() SaveMapSection(); currentmapsection[mapsection >> 3] |= 1 << (mapsection & 7); - GLRenderer->DrawScene(); + GLRenderer->DrawScene(DM_PORTAL); portal->mFlags &= ~PORTSF_INSKYBOX; inskybox = false; gl_RenderState.SetDepthClamp(oldclamp); @@ -755,7 +756,7 @@ void GLSectorStackPortal::DrawContents() SaveMapSection(); SetupCoverage(); ClearClipper(); - GLRenderer->DrawScene(); + GLRenderer->DrawScene(DM_PORTAL); RestoreMapSection(); if (origin->plane != -1) instack[origin->plane]--; @@ -791,14 +792,13 @@ void GLPlaneMirrorPortal::DrawContents() ViewPos.Z = 2 * planez - ViewPos.Z; GLRenderer->mViewActor = NULL; PlaneMirrorMode = origin->fC() < 0 ? -1 : 1; - r_showviewer = true; - + PlaneMirrorFlag++; GLRenderer->SetupView(ViewPos.X, ViewPos.Y, ViewPos.Z, ViewAngle, !!(MirrorFlag&1), !!(PlaneMirrorFlag&1)); ClearClipper(); gl_RenderState.SetClipHeight(planez, PlaneMirrorMode < 0? -1.f : 1.f); - GLRenderer->DrawScene(); + GLRenderer->DrawScene(DM_PORTAL); gl_RenderState.SetClipHeight(0.f, 0.f); PlaneMirrorFlag--; PlaneMirrorMode=old_pm; @@ -955,7 +955,6 @@ void GLMirrorPortal::DrawContents() ViewAngle = linedef->Delta().Angle() * 2. - StartAngle; GLRenderer->mViewActor = NULL; - r_showviewer = true; MirrorFlag++; GLRenderer->SetupView(ViewPos.X, ViewPos.Y, ViewPos.Z, ViewAngle, !!(MirrorFlag&1), !!(PlaneMirrorFlag&1)); @@ -971,7 +970,7 @@ void GLMirrorPortal::DrawContents() gl_RenderState.SetClipLine(linedef); gl_RenderState.EnableClipLine(true); - GLRenderer->DrawScene(); + GLRenderer->DrawScene(DM_PORTAL); gl_RenderState.EnableClipLine(false); MirrorFlag--; @@ -1009,7 +1008,7 @@ void GLLineToLinePortal::DrawContents() P_TranslatePortalZ(origin, ViewPos.Z); P_TranslatePortalXY(origin, ViewPath[0].X, ViewPath[0].Y); P_TranslatePortalXY(origin, ViewPath[1].X, ViewPath[1].Y); - if (!r_showviewer) + if (!r_showviewer && camera != nullptr && P_PointOnLineSidePrecise(ViewPath[0], glport->lines[0]->mDestination) != P_PointOnLineSidePrecise(ViewPath[1], glport->lines[0]->mDestination)) { double distp = (ViewPath[0] - ViewPath[1]).Length(); if (distp > EQUAL_EPSILON) @@ -1017,9 +1016,9 @@ void GLLineToLinePortal::DrawContents() double dist1 = (ViewPos - ViewPath[0]).Length(); double dist2 = (ViewPos - ViewPath[1]).Length(); - if (dist1 + dist2 > distp + 1) + if (dist1 + dist2 < distp + 1) { - r_showviewer = true; + camera->renderflags |= RF_INVISIBLE; } } } @@ -1044,7 +1043,7 @@ void GLLineToLinePortal::DrawContents() ClearClipper(); gl_RenderState.SetClipLine(glport->lines[0]->mDestination); gl_RenderState.EnableClipLine(true); - GLRenderer->DrawScene(); + GLRenderer->DrawScene(DM_PORTAL); gl_RenderState.EnableClipLine(false); RestoreMapSection(); } diff --git a/src/gl/scene/gl_portal.h b/src/gl/scene/gl_portal.h index c8afee2a6..9ebfe083b 100644 --- a/src/gl/scene/gl_portal.h +++ b/src/gl/scene/gl_portal.h @@ -105,7 +105,7 @@ private: DAngle savedAngle; AActor * savedviewactor; area_t savedviewarea; - bool savedshowviewer; + ActorRenderFlags savedvisibility; DVector3 savedviewpath[2]; GLPortal *PrevPortal; GLPortal *PrevClipPortal; diff --git a/src/gl/scene/gl_scene.cpp b/src/gl/scene/gl_scene.cpp index 44368775a..6352ca0cd 100644 --- a/src/gl/scene/gl_scene.cpp +++ b/src/gl/scene/gl_scene.cpp @@ -98,6 +98,7 @@ EXTERN_CVAR (Bool, r_deathcamera) extern int viewpitch; extern bool NoInterpolateView; +extern bool r_showviewer; DWORD gl_fixedcolormap; area_t in_area; @@ -501,16 +502,29 @@ void FGLRenderer::RenderTranslucent() //----------------------------------------------------------------------------- EXTERN_CVAR(Bool, gl_draw_sync) -void FGLRenderer::DrawScene(bool toscreen) +void FGLRenderer::DrawScene(int drawmode) { static int recursion=0; - CreateScene(); + if (camera != nullptr) + { + ActorRenderFlags savedflags = camera->renderflags; + if (drawmode != DM_PORTAL && !r_showviewer) + { + camera->renderflags |= RF_INVISIBLE; + } + CreateScene(); + camera->renderflags = savedflags; + } + else + { + CreateScene(); + } GLRenderer->mClipPortal = NULL; // this must be reset before any portal recursion takes place. // Up to this point in the main draw call no rendering is performed so we can wait // with swapping the render buffer until now. - if (!gl_draw_sync && toscreen) + if (!gl_draw_sync && drawmode == DM_MAINVIEW) { All.Unclock(); static_cast(screen)->Swap(); @@ -734,7 +748,7 @@ void FGLRenderer::ProcessScene(bool toscreen) int mapsection = R_PointInSubsector(ViewPos)->mapsection; memset(¤tmapsection[0], 0, currentmapsection.Size()); currentmapsection[mapsection>>3] |= 1 << (mapsection & 7); - DrawScene(toscreen); + DrawScene(toscreen ? DM_MAINVIEW : DM_OFFSCREEN); FDrawInfo::EndDrawInfo(); } diff --git a/src/gl/scene/gl_sprite.cpp b/src/gl/scene/gl_sprite.cpp index 447e6b78e..59e001416 100644 --- a/src/gl/scene/gl_sprite.cpp +++ b/src/gl/scene/gl_sprite.cpp @@ -81,7 +81,6 @@ CUSTOM_CVAR(Int, gl_fuzztype, 0, CVAR_ARCHIVE) if (self < 0 || self > 7) self = 0; } -extern bool r_showviewer; EXTERN_CVAR (Float, transsouls) extern TArray sprites; @@ -552,8 +551,6 @@ void GLSprite::Process(AActor* thing, sector_t * sector, int thruportal) { sector_t rs; sector_t * rendersector; - // don't draw the thing that's used as camera (for viewshifts during quakes!) - if (thing == GLRenderer->mViewActor || (thing == players[consoleplayer].camera && !r_showviewer)) return; // Don't waste time projecting sprites that are definitely not visible. if (thing == NULL || thing->sprite == 0 || !thing->IsVisibleToPlayer()) @@ -561,6 +558,12 @@ void GLSprite::Process(AActor* thing, sector_t * sector, int thruportal) return; } + if (thing->renderflags & RF_INVISIBLE || !thing->RenderStyle.IsVisible(thing->Alpha)) + { + if (!(thing->flags & MF_STEALTH) || !gl_fixedcolormap || !gl_enhanced_nightvision || thing == camera) + return; + } + int spritenum = thing->sprite; DVector2 sprscale = thing->Scale; if (thing->player != NULL) @@ -568,12 +571,6 @@ void GLSprite::Process(AActor* thing, sector_t * sector, int thruportal) P_CheckPlayerSprite(thing, spritenum, sprscale); } - if (thing->renderflags & RF_INVISIBLE || !thing->RenderStyle.IsVisible(thing->Alpha)) - { - if (!(thing->flags & MF_STEALTH) || !gl_fixedcolormap || !gl_enhanced_nightvision) - return; - } - // If this thing is in a map section that's not in view it can't possibly be visible if (!thruportal && !(currentmapsection[thing->subsector->mapsection >> 3] & (1 << (thing->subsector->mapsection & 7)))) return;