- fixed view clipping for portal sectors.

All lines within the portal must neither be added to the clipper nor checked for obstruction by other parts of the map.
This commit is contained in:
Christoph Oelckers 2021-04-06 19:25:40 +02:00
parent 5c2335bbeb
commit d823ae255e
5 changed files with 30 additions and 27 deletions

View file

@ -91,7 +91,7 @@ void BunchDrawer::StartScene()
//
//==========================================================================
void BunchDrawer::StartBunch(int sectnum, int linenum, binangle startan, binangle endan)
void BunchDrawer::StartBunch(int sectnum, int linenum, binangle startan, binangle endan, bool portal)
{
FBunch* bunch = &Bunches[LastBunch = Bunches.Reserve(1)];
@ -99,6 +99,7 @@ void BunchDrawer::StartBunch(int sectnum, int linenum, binangle startan, binangl
bunch->startline = bunch->endline = linenum;
bunch->startangle = startan;
bunch->endangle = endan;
bunch->portal = portal;
}
//==========================================================================
@ -182,7 +183,7 @@ bool BunchDrawer::CheckClip(walltype* wal)
//
//==========================================================================
int BunchDrawer::ClipLine(int line)
int BunchDrawer::ClipLine(int line, bool portal)
{
auto wal = &wall[line];
@ -195,7 +196,7 @@ int BunchDrawer::ClipLine(int line)
return CL_Skip;
}
if (!clipper->SafeCheckRange(startAngle, endAngle))
if (!portal && !clipper->SafeCheckRange(startAngle, endAngle))
{
return CL_Skip;
}
@ -203,7 +204,7 @@ int BunchDrawer::ClipLine(int line)
if (wal->nextwall == -1 || (wal->cstat & CSTAT_WALL_1WAY) || CheckClip(wal))
{
// one-sided
clipper->SafeAddClipRange(startAngle, endAngle);
if (!portal) clipper->SafeAddClipRange(startAngle, endAngle);
return CL_Draw;
}
else
@ -225,7 +226,7 @@ void BunchDrawer::ProcessBunch(int bnch)
ClipWall.Clock();
for (int i = bunch->startline; i <= bunch->endline; i++)
{
int clipped = ClipLine(i);
int clipped = ClipLine(i, bunch->portal);
if (clipped & CL_Draw)
{
@ -250,7 +251,7 @@ void BunchDrawer::ProcessBunch(int bnch)
if (clipped & CL_Pass)
{
ClipWall.Unclock();
ProcessSector(wall[i].nextsector);
ProcessSector(wall[i].nextsector, false);
ClipWall.Clock();
}
}
@ -425,7 +426,7 @@ int BunchDrawer::FindClosestBunch()
//
//==========================================================================
void BunchDrawer::ProcessSector(int sectnum)
void BunchDrawer::ProcessSector(int sectnum, bool portal)
{
if (gotsector[sectnum]) return;
gotsector.Set(sectnum);
@ -503,7 +504,7 @@ void BunchDrawer::ProcessSector(int sectnum)
// situation where 2 bunches may overlap at both ends.
startangle = ang1;
StartBunch(sectnum, sect->wallptr + i, ang1, ang2);
StartBunch(sectnum, sect->wallptr + i, ang1, ang2, portal);
inbunch = true;
}
else
@ -520,11 +521,11 @@ void BunchDrawer::ProcessSector(int sectnum)
//
//==========================================================================
void BunchDrawer::RenderScene(const int* viewsectors, unsigned sectcount)
void BunchDrawer::RenderScene(const int* viewsectors, unsigned sectcount, bool portal)
{
Bsp.Clock();
for(unsigned i=0;i<sectcount;i++)
ProcessSector(viewsectors[i]);
ProcessSector(viewsectors[i], portal);
while (Bunches.Size() > 0)
{
int closest = FindClosestBunch();

View file

@ -11,6 +11,7 @@ struct FBunch
int sectnum;
int startline;
int endline;
bool portal;
binangle startangle; // in pseudo angles for the clipper
binangle endangle;
};
@ -38,19 +39,19 @@ private:
};
void StartScene();
void StartBunch(int sectnum, int linenum, binangle startan, binangle endan);
void StartBunch(int sectnum, int linenum, binangle startan, binangle endan, bool portal);
void AddLineToBunch(int line, binangle newan);
void DeleteBunch(int index);
bool CheckClip(walltype* wal);
int ClipLine(int line);
int ClipLine(int line, bool portal);
void ProcessBunch(int bnch);
int WallInFront(int wall1, int wall2);
int BunchInFront(FBunch* b1, FBunch* b2);
int FindClosestBunch();
void ProcessSector(int sectnum);
void ProcessSector(int sectnum, bool portal);
public:
void Init(HWDrawInfo* _di, Clipper* c, vec2_t& view);
void RenderScene(const int* viewsectors, unsigned sectcount);
void RenderScene(const int* viewsectors, unsigned sectcount, bool portal);
const FixedBitArray<MAXSECTORS>& GotSector() const { return gotsector; }
};

View file

@ -364,7 +364,7 @@ void HWDrawInfo::DispatchSprites()
//
//-----------------------------------------------------------------------------
void HWDrawInfo::CreateScene()
void HWDrawInfo::CreateScene(bool portal)
{
const auto& vp = Viewpoint;
@ -387,9 +387,9 @@ void HWDrawInfo::CreateScene()
vec2_t view = { int(vp.Pos.X * 16), int(vp.Pos.Y * -16) };
mDrawer.Init(this, mClipper, view);
if (vp.SectNums)
mDrawer.RenderScene(vp.SectNums, vp.SectCount);
mDrawer.RenderScene(vp.SectNums, vp.SectCount, portal);
else
mDrawer.RenderScene(&vp.SectCount, 1);
mDrawer.RenderScene(&vp.SectCount, 1, portal);
SetupSprite.Clock();
gi->processSprites(tsprite, spritesortcnt, view.x, view.y, vp.Pos.Z * -256, bamang(vp.RotAngle), vp.TicFrac * 65536);
@ -422,7 +422,7 @@ void HWDrawInfo::CreateScene()
mClipper->Clear();
mClipper->SafeAddClipRange(bamang(vp.RotAngle + a1), bamang(vp.RotAngle - a1));
mDrawer.Init(this, mClipper, view);
mDrawer.RenderScene(&drawsect, 1);
mDrawer.RenderScene(&drawsect, 1, false);
for (int i = 0; i < eff.geocnt; i++)
{
@ -453,7 +453,7 @@ void HWDrawInfo::CreateScene()
mClipper->Clear();
mClipper->SafeAddClipRange(bamang(vp.RotAngle + a1), bamang(vp.RotAngle - a1));
mDrawer.Init(this, mClipper, view);
mDrawer.RenderScene(&drawsect, 1);
mDrawer.RenderScene(&drawsect, 1, false);
for (int i = 0; i < eff.geocnt; i++)
{
@ -670,7 +670,7 @@ void HWDrawInfo::Set3DViewport(FRenderState &state)
//
//-----------------------------------------------------------------------------
void HWDrawInfo::DrawScene(int drawmode)
void HWDrawInfo::DrawScene(int drawmode, bool portal)
{
static int recursion = 0;
static int ssao_portals_available = 0;
@ -692,7 +692,7 @@ void HWDrawInfo::DrawScene(int drawmode)
ssao_portals_available--;
}
CreateScene();
CreateScene(portal);
auto& RenderState = *screen->RenderState();
RenderState.SetDepthMask(true);
@ -725,7 +725,7 @@ void HWDrawInfo::DrawScene(int drawmode)
void HWDrawInfo::ProcessScene(bool toscreen)
{
portalState.BeginScene();
DrawScene(toscreen ? DM_MAINVIEW : DM_OFFSCREEN);
DrawScene(toscreen ? DM_MAINVIEW : DM_OFFSCREEN, false);
if (toscreen && isBlood())
{
gotsector = mDrawer.GotSector(); // Blood needs this to implement some lighting effect hacks. Needs to be refactored to use better info.

View file

@ -158,8 +158,8 @@ public:
void ClearBuffers();
HWDrawInfo *EndDrawInfo();
void DrawScene(int drawmode);
void CreateScene();
void DrawScene(int drawmode, bool portal);
void CreateScene(bool portal);
void DispatchSprites();
void RenderScene(FRenderState &state);
void RenderTranslucent(FRenderState &state);

View file

@ -400,9 +400,10 @@ void HWScenePortalBase::DrawContents(HWDrawInfo* di, FRenderState& state)
{
if (Setup(di, state, di->mClipper))
{
gi->EnterPortal(di->Viewpoint.CameraSprite, GetType());
di->DrawScene(DM_PORTAL);
gi->LeavePortal(di->Viewpoint.CameraSprite, GetType());
auto type = GetType();
gi->EnterPortal(di->Viewpoint.CameraSprite, type);
di->DrawScene(DM_PORTAL, type == PORTAL_SECTOR_CEILING);
gi->LeavePortal(di->Viewpoint.CameraSprite, type);
Shutdown(di, state);
}
else state.ClearScreen();