Added visual rendering for LinePortals and SkyPortals for OoB viewpoints. SkyPortals will be stenciled, and will always use perspective projection. Disabled interpolation when portalgroup changes (portal transition occurs) if viewpoint is OoB (was necessary for fog of war when r_radarclipper is set to true). Tightened up radar clipper by making it more aggressive. Voided walls wont' get filled in by a floor or ceiling sky (because of the stencil). Ceiling sky will be half-infinitely tall upwards, and floor sky will be half-infinitely tall downwards. Use only floor skies and a good GLSKYBOX for top-down/isometric cameras. Level.ReplaceTextures("F_SKY1", "SKY1", TexMan.NOT_FLOOR); (zscript) is a nice trick for WorldLoaded().
This commit is contained in:
parent
2223ea6227
commit
42947d04dc
11 changed files with 118 additions and 111 deletions
|
|
@ -167,6 +167,7 @@ sector_t* RenderViewpoint(FRenderViewpoint& mainvp, AActor* camera, IntRect* bou
|
|||
bool iso_ortho = (camera->ViewPos != NULL) && (camera->ViewPos->Flags & VPSF_ORTHOGRAPHIC);
|
||||
if (iso_ortho && (camera->ViewPos->Offset.Length() > 0)) inv_iso_dist = 1.0/camera->ViewPos->Offset.Length();
|
||||
di->VPUniforms.mProjectionMatrix = eye.GetProjection(fov, ratio, fovratio * inv_iso_dist, iso_ortho);
|
||||
di->ProjectionMatrix2 = eye.GetProjection(fov, ratio, fovratio, false); // Regular ol' perspective projection matrix
|
||||
|
||||
// Stereo mode specific viewpoint adjustment
|
||||
vp.Pos += eye.GetViewShift(vp.HWAngles.Yaw.Degrees());
|
||||
|
|
|
|||
|
|
@ -287,15 +287,16 @@ void HWDrawInfo::AddLine (seg_t *seg, bool portalclip)
|
|||
auto &clipperr = *rClipper;
|
||||
angle_t startAngleR = clipperr.PointToPseudoAngle(seg->v2->fX(), seg->v2->fY());
|
||||
angle_t endAngleR = clipperr.PointToPseudoAngle(seg->v1->fX(), seg->v1->fY());
|
||||
angle_t paddingR = 0x00200000; // Make radar clipping more aggressive (reveal less)
|
||||
|
||||
if(Viewpoint.IsAllowedOoB() && r_radarclipper && !(Level->flags3 & LEVEL3_NOFOGOFWAR) && (startAngleR - endAngleR >= ANGLE_180))
|
||||
{
|
||||
if (!seg->backsector) clipperr.SafeAddClipRange(startAngleR, endAngleR);
|
||||
if (!seg->backsector) clipperr.SafeAddClipRange(startAngleR - paddingR, endAngleR + paddingR);
|
||||
else if((seg->sidedef != nullptr) && !uint8_t(seg->sidedef->Flags & WALLF_POLYOBJ) && (currentsector->sectornum != seg->backsector->sectornum))
|
||||
{
|
||||
if (in_area == area_default) in_area = hw_CheckViewArea(seg->v1, seg->v2, seg->frontsector, seg->backsector);
|
||||
backsector = hw_FakeFlat(seg->backsector, in_area, true);
|
||||
if (hw_CheckClip(seg->sidedef, currentsector, backsector)) clipperr.SafeAddClipRange(startAngleR, endAngleR);
|
||||
if (hw_CheckClip(seg->sidedef, currentsector, backsector)) clipperr.SafeAddClipRange(startAngleR - paddingR, endAngleR + paddingR);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -313,7 +314,7 @@ void HWDrawInfo::AddLine (seg_t *seg, bool portalclip)
|
|||
{
|
||||
currentsubsector->flags |= SSECMF_DRAWN;
|
||||
}
|
||||
if ((r_radarclipper || !(Level->flags3 & LEVEL3_NOFOGOFWAR)) && clipperr.SafeCheckRange(startAngleR, endAngleR))
|
||||
if (Viewpoint.IsAllowedOoB() && (r_radarclipper && !(Level->flags3 & LEVEL3_NOFOGOFWAR)) && clipperr.SafeCheckRange(startAngleR, endAngleR))
|
||||
{
|
||||
currentsubsector->flags |= SSECMF_DRAWN;
|
||||
}
|
||||
|
|
@ -326,31 +327,7 @@ void HWDrawInfo::AddLine (seg_t *seg, bool portalclip)
|
|||
return;
|
||||
}
|
||||
|
||||
if (Viewpoint.IsAllowedOoB()) // No need for vertical clipping if viewpoint not allowed out of bounds
|
||||
{
|
||||
auto &clipperv = *vClipper;
|
||||
angle_t startPitch = clipperv.PointToPseudoPitch(seg->v1->fX(), seg->v1->fY(), currentsector->floorplane.ZatPoint(seg->v1));
|
||||
angle_t endPitch = clipperv.PointToPseudoPitch(seg->v1->fX(), seg->v1->fY(), currentsector->ceilingplane.ZatPoint(seg->v1));
|
||||
angle_t startPitch2 = clipperv.PointToPseudoPitch(seg->v2->fX(), seg->v2->fY(), currentsector->floorplane.ZatPoint(seg->v2));
|
||||
angle_t endPitch2 = clipperv.PointToPseudoPitch(seg->v2->fX(), seg->v2->fY(), currentsector->ceilingplane.ZatPoint(seg->v2));
|
||||
angle_t temp;
|
||||
// Wall can be tilted from viewpoint perspective. Find vertical extent on screen in psuedopitch units (0 to 2, bottom to top)
|
||||
if(int(startPitch) > int(startPitch2)) // Handle zero crossing
|
||||
{
|
||||
temp = startPitch; startPitch = startPitch2; startPitch2 = temp; // exchange
|
||||
}
|
||||
if(int(endPitch) > int(endPitch2)) // Handle zero crossing
|
||||
{
|
||||
temp = endPitch; endPitch = endPitch2; endPitch2 = temp; // exchange
|
||||
}
|
||||
|
||||
if (!clipperv.SafeCheckRange(startPitch, endPitch2))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!r_radarclipper || (Level->flags3 & LEVEL3_NOFOGOFWAR) || clipperr.SafeCheckRange(startAngleR, endAngleR))
|
||||
if (Viewpoint.IsAllowedOoB() && (!r_radarclipper || (Level->flags3 & LEVEL3_NOFOGOFWAR) || clipperr.SafeCheckRange(startAngleR, endAngleR)))
|
||||
currentsubsector->flags |= SSECMF_DRAWN;
|
||||
|
||||
uint8_t ispoly = uint8_t(seg->sidedef->Flags & WALLF_POLYOBJ);
|
||||
|
|
@ -729,8 +706,8 @@ void HWDrawInfo::DoSubsector(subsector_t * sub)
|
|||
|
||||
if(Viewpoint.IsAllowedOoB() && sector->isSecret() && sector->wasSecret() && !r_radarclipper) return;
|
||||
|
||||
// cull everything if subsector outside vertical clipper
|
||||
if ((sub->polys == nullptr) && (!Viewpoint.IsOrtho() || !((Level->flags3 & LEVEL3_NOFOGOFWAR) || !r_radarclipper)))
|
||||
// cull everything if subsector outside all relevant clippers
|
||||
if ((sub->polys == nullptr))
|
||||
{
|
||||
auto &clipper = *mClipper;
|
||||
auto &clipperv = *vClipper;
|
||||
|
|
@ -739,7 +716,7 @@ void HWDrawInfo::DoSubsector(subsector_t * sub)
|
|||
seg_t * seg = sub->firstline;
|
||||
bool anglevisible = false;
|
||||
bool pitchvisible = !(Viewpoint.IsAllowedOoB()); // No vertical clipping if viewpoint is not allowed out of bounds
|
||||
bool radarvisible = false;
|
||||
bool radarvisible = !(Viewpoint.IsAllowedOoB()) || !r_radarclipper || (Level->flags3 & LEVEL3_NOFOGOFWAR) || ((sub->flags & SSECMF_DRAWN) && !deathmatch);
|
||||
angle_t pitchtemp;
|
||||
angle_t pitchmin = ANGLE_90;
|
||||
angle_t pitchmax = 0;
|
||||
|
|
@ -748,13 +725,19 @@ void HWDrawInfo::DoSubsector(subsector_t * sub)
|
|||
{
|
||||
if((seg->v1 != nullptr) && (seg->v2 != nullptr))
|
||||
{
|
||||
angle_t startAngle = clipper.GetClipAngle(seg->v2);
|
||||
angle_t endAngle = clipper.GetClipAngle(seg->v1);
|
||||
if (startAngle-endAngle >= ANGLE_180) anglevisible |= clipper.SafeCheckRange(startAngle, endAngle);
|
||||
angle_t startAngleR = clipperr.PointToPseudoAngle(seg->v2->fX(), seg->v2->fY());
|
||||
angle_t endAngleR = clipperr.PointToPseudoAngle(seg->v1->fX(), seg->v1->fY());
|
||||
if (startAngleR-endAngleR >= ANGLE_180)
|
||||
radarvisible |= (clipperr.SafeCheckRange(startAngleR, endAngleR) || (Level->flags3 & LEVEL3_NOFOGOFWAR) || ((sub->flags & SSECMF_DRAWN) && !deathmatch));
|
||||
if (!anglevisible)
|
||||
{
|
||||
angle_t startAngle = clipper.GetClipAngle(seg->v2);
|
||||
angle_t endAngle = clipper.GetClipAngle(seg->v1);
|
||||
if (startAngle-endAngle >= ANGLE_180) anglevisible |= clipper.SafeCheckRange(startAngle, endAngle);
|
||||
}
|
||||
if (!radarvisible)
|
||||
{
|
||||
angle_t startAngleR = clipperr.PointToPseudoAngle(seg->v2->fX(), seg->v2->fY());
|
||||
angle_t endAngleR = clipperr.PointToPseudoAngle(seg->v1->fX(), seg->v1->fY());
|
||||
if (startAngleR-endAngleR >= ANGLE_180) radarvisible |= clipperr.SafeCheckRange(startAngleR, endAngleR);
|
||||
}
|
||||
|
||||
if (!pitchvisible)
|
||||
{
|
||||
pitchmin = clipperv.PointToPseudoPitch(seg->v1->fX(), seg->v1->fY(), sector->floorplane.ZatPoint(seg->v1));
|
||||
|
|
@ -988,8 +971,8 @@ void HWDrawInfo::RenderOrthoNoFog()
|
|||
{
|
||||
if (Viewpoint.IsOrtho() && ((Level->flags3 & LEVEL3_NOFOGOFWAR) || !r_radarclipper))
|
||||
{
|
||||
double vxdbl = Viewpoint.camera->X();
|
||||
double vydbl = Viewpoint.camera->Y();
|
||||
double vxdbl = Viewpoint.OffPos.X;
|
||||
double vydbl = Viewpoint.OffPos.Y;
|
||||
double ext = Viewpoint.camera->ViewPos->Offset.Length() ?
|
||||
3.0 * Viewpoint.camera->ViewPos->Offset.Length() * tan (Viewpoint.FieldOfView.Radians()*0.5) : 100.0;
|
||||
FBoundingBox viewbox(vxdbl, vydbl, ext);
|
||||
|
|
@ -1014,16 +997,8 @@ void HWDrawInfo::RenderBSP(void *node, bool drawpsprites)
|
|||
viewy = FLOAT2FIXED(Viewpoint.Pos.Y);
|
||||
if (r_radarclipper && !(Level->flags3 & LEVEL3_NOFOGOFWAR) && Viewpoint.IsAllowedOoB())
|
||||
{
|
||||
if (Viewpoint.camera->tracer != NULL)
|
||||
{
|
||||
viewx = FLOAT2FIXED(Viewpoint.camera->tracer->X());
|
||||
viewy = FLOAT2FIXED(Viewpoint.camera->tracer->Y());
|
||||
}
|
||||
else
|
||||
{
|
||||
viewx = FLOAT2FIXED(Viewpoint.camera->X());
|
||||
viewy = FLOAT2FIXED(Viewpoint.camera->Y());
|
||||
}
|
||||
viewx = FLOAT2FIXED(Viewpoint.OffPos.X);
|
||||
viewy = FLOAT2FIXED(Viewpoint.OffPos.Y);
|
||||
}
|
||||
|
||||
validcount++; // used for processing sidedefs only once by the renderer.
|
||||
|
|
|
|||
|
|
@ -394,18 +394,10 @@ angle_t Clipper::PointToPseudoAngle(double x, double y)
|
|||
{
|
||||
double vecx = x - viewpoint->Pos.X;
|
||||
double vecy = y - viewpoint->Pos.Y;
|
||||
if ((viewpoint->camera != NULL) && amRadar)
|
||||
if (amRadar)
|
||||
{
|
||||
if (viewpoint->camera->tracer != NULL)
|
||||
{
|
||||
vecx = x - viewpoint->camera->tracer->X();
|
||||
vecy = y - viewpoint->camera->tracer->Y();
|
||||
}
|
||||
else
|
||||
{
|
||||
vecx = x - viewpoint->camera->X();
|
||||
vecy = y - viewpoint->camera->Y();
|
||||
}
|
||||
vecx = x - viewpoint->OffPos.X;
|
||||
vecy = y - viewpoint->OffPos.Y;
|
||||
}
|
||||
|
||||
if (vecx == 0 && vecy == 0)
|
||||
|
|
@ -467,7 +459,7 @@ angle_t Clipper::PointToPseudoPitch(double x, double y, double z)
|
|||
|
||||
angle_t Clipper::PointToPseudoOrthoAngle(double x, double y)
|
||||
{
|
||||
DVector3 disp = DVector3( x, y, 0 ) - viewpoint->camera->Pos();
|
||||
DVector3 disp = DVector3(x, y, 0) - viewpoint->OffPos;
|
||||
if (viewpoint->camera->ViewPos->Offset.XY().Length() == 0)
|
||||
{
|
||||
return AngleToPseudo( viewpoint->Angles.Yaw.BAMs() );
|
||||
|
|
@ -491,7 +483,7 @@ angle_t Clipper::PointToPseudoOrthoAngle(double x, double y)
|
|||
|
||||
angle_t Clipper::PointToPseudoOrthoPitch(double x, double y, double z)
|
||||
{
|
||||
DVector3 disp = DVector3( x, y, z ) - viewpoint->camera->Pos();
|
||||
DVector3 disp = DVector3(x, y, z) - viewpoint->OffPos;
|
||||
if (viewpoint->camera->ViewPos->Offset.XY().Length() > 0)
|
||||
{
|
||||
double yproj = viewpoint->PitchSin * disp.XY().Length() * deltaangle(disp.Angle(), viewpoint->Angles.Yaw).Cos();
|
||||
|
|
|
|||
|
|
@ -160,6 +160,7 @@ void HWDrawInfo::StartScene(FRenderViewpoint &parentvp, HWViewpointUniforms *uni
|
|||
VPUniforms.mProjectionMatrix.loadIdentity();
|
||||
VPUniforms.mViewMatrix.loadIdentity();
|
||||
VPUniforms.mNormalViewMatrix.loadIdentity();
|
||||
ProjectionMatrix2.loadIdentity();
|
||||
VPUniforms.mViewHeight = viewheight;
|
||||
if (lightmode == ELightMode::Build)
|
||||
{
|
||||
|
|
@ -684,60 +685,70 @@ void HWDrawInfo::DrawCorona(FRenderState& state, ACorona* corona, double dist)
|
|||
|
||||
static ETraceStatus TraceCallbackForDitherTransparency(FTraceResults& res, void* userdata)
|
||||
{
|
||||
int* count = (int*)userdata;
|
||||
BitArray* CurMapSections = (BitArray*)userdata;
|
||||
double bf, bc;
|
||||
(*count)++;
|
||||
|
||||
switch(res.HitType)
|
||||
{
|
||||
case TRACE_HitWall:
|
||||
if (!(res.Line->sidedef[res.Side]->Flags & WALLF_DITHERTRANS))
|
||||
{
|
||||
bf = res.Line->sidedef[res.Side]->sector->floorplane.ZatPoint(res.HitPos.XY());
|
||||
bc = res.Line->sidedef[res.Side]->sector->ceilingplane.ZatPoint(res.HitPos.XY());
|
||||
if ((res.HitPos.Z <= bc) && (res.HitPos.Z >= bf)) res.Line->sidedef[res.Side]->Flags |= WALLF_DITHERTRANS;
|
||||
sector_t* linesec = res.Line->sidedef[res.Side]->sector;
|
||||
if (linesec->subsectorcount > 0 && (*CurMapSections)[linesec->subsectors[0]->mapsection])
|
||||
{
|
||||
bf = res.Line->sidedef[res.Side]->sector->floorplane.ZatPoint(res.HitPos.XY());
|
||||
bc = res.Line->sidedef[res.Side]->sector->ceilingplane.ZatPoint(res.HitPos.XY());
|
||||
if ((res.HitPos.Z <= bc) && (res.HitPos.Z >= bf)) res.Line->sidedef[res.Side]->Flags |= WALLF_DITHERTRANS;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case TRACE_HitFloor:
|
||||
if (res.HitPos.Z == res.Sector->floorplane.ZatPoint(res.HitPos))
|
||||
if (res.Sector->subsectorcount > 0 && (*CurMapSections)[res.Sector->subsectors[0]->mapsection])
|
||||
{
|
||||
res.Sector->floorplane.dithertransflag = true;
|
||||
}
|
||||
else if (res.Sector->e->XFloor.ffloors.Size()) // Maybe it was 3D floors
|
||||
{
|
||||
F3DFloor *rover;
|
||||
int kk;
|
||||
for (kk = 0; kk < (int)res.Sector->e->XFloor.ffloors.Size(); kk++)
|
||||
if (res.HitPos.Z == res.Sector->floorplane.ZatPoint(res.HitPos))
|
||||
{
|
||||
rover = res.Sector->e->XFloor.ffloors[kk];
|
||||
if ((rover->flags&(FF_EXISTS | FF_RENDERPLANES | FF_THISINSIDE)) == (FF_EXISTS | FF_RENDERPLANES))
|
||||
res.Sector->floorplane.dithertransflag = true;
|
||||
}
|
||||
else if (res.Sector->e->XFloor.ffloors.Size()) // Maybe it was 3D floors
|
||||
{
|
||||
F3DFloor *rover;
|
||||
int kk;
|
||||
for (kk = 0; kk < (int)res.Sector->e->XFloor.ffloors.Size(); kk++)
|
||||
{
|
||||
if (res.HitPos.Z == rover->top.plane->ZatPoint(res.HitPos))
|
||||
rover = res.Sector->e->XFloor.ffloors[kk];
|
||||
if ((rover->flags&(FF_EXISTS | FF_RENDERPLANES | FF_THISINSIDE)) == (FF_EXISTS | FF_RENDERPLANES))
|
||||
{
|
||||
rover->top.plane->dithertransflag = true;
|
||||
break; // Out of for loop
|
||||
if (res.HitPos.Z == rover->top.plane->ZatPoint(res.HitPos))
|
||||
{
|
||||
rover->top.plane->dithertransflag = true;
|
||||
break; // Out of for loop
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case TRACE_HitCeiling:
|
||||
if (res.HitPos.Z == res.Sector->ceilingplane.ZatPoint(res.HitPos))
|
||||
if (res.Sector->subsectorcount > 0 && (*CurMapSections)[res.Sector->subsectors[0]->mapsection])
|
||||
{
|
||||
res.Sector->ceilingplane.dithertransflag = true;
|
||||
}
|
||||
else if (res.Sector->e->XFloor.ffloors.Size()) // Maybe it was 3D floors
|
||||
{
|
||||
F3DFloor *rover;
|
||||
int kk;
|
||||
for (kk = 0; kk < (int)res.Sector->e->XFloor.ffloors.Size(); kk++)
|
||||
if (res.HitPos.Z == res.Sector->ceilingplane.ZatPoint(res.HitPos))
|
||||
{
|
||||
rover = res.Sector->e->XFloor.ffloors[kk];
|
||||
if ((rover->flags&(FF_EXISTS | FF_RENDERPLANES | FF_THISINSIDE)) == (FF_EXISTS | FF_RENDERPLANES))
|
||||
res.Sector->ceilingplane.dithertransflag = true;
|
||||
}
|
||||
else if (res.Sector->e->XFloor.ffloors.Size()) // Maybe it was 3D floors
|
||||
{
|
||||
F3DFloor *rover;
|
||||
int kk;
|
||||
for (kk = 0; kk < (int)res.Sector->e->XFloor.ffloors.Size(); kk++)
|
||||
{
|
||||
if (res.HitPos.Z == rover->bottom.plane->ZatPoint(res.HitPos))
|
||||
rover = res.Sector->e->XFloor.ffloors[kk];
|
||||
if ((rover->flags&(FF_EXISTS | FF_RENDERPLANES | FF_THISINSIDE)) == (FF_EXISTS | FF_RENDERPLANES))
|
||||
{
|
||||
rover->bottom.plane->dithertransflag = true;
|
||||
break; // Out of for loop
|
||||
if (res.HitPos.Z == rover->bottom.plane->ZatPoint(res.HitPos))
|
||||
{
|
||||
rover->bottom.plane->dithertransflag = true;
|
||||
break; // Out of for loop
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -763,13 +774,11 @@ void HWDrawInfo::SetDitherTransFlags(AActor* actor)
|
|||
DVector3 vvec = actorpos - Viewpoint.Pos;
|
||||
if (Viewpoint.IsOrtho())
|
||||
{
|
||||
vvec += Viewpoint.camera->Pos() - actorpos;
|
||||
vvec *= 5.0; // Should be 4.0? (since zNear is behind screen by 3*dist in VREyeInfo::GetProjection())
|
||||
vvec = 5.0 * Viewpoint.camera->ViewPos->Offset.Length() * Viewpoint.ViewVector3D; // Should be 4.0? (since zNear is behind screen by 3*dist in VREyeInfo::GetProjection())
|
||||
}
|
||||
double distance = vvec.Length() - actor->radius;
|
||||
DVector3 campos = actorpos - vvec;
|
||||
sector_t* startsec;
|
||||
int count = 0;
|
||||
|
||||
vvec = vvec.Unit();
|
||||
campos.X -= horix; campos.Y += horiy; campos.Z += actor->Height * 0.25;
|
||||
|
|
@ -777,10 +786,10 @@ void HWDrawInfo::SetDitherTransFlags(AActor* actor)
|
|||
{
|
||||
startsec = Level->PointInRenderSubsector(campos)->sector;
|
||||
Trace(campos, startsec, vvec, distance,
|
||||
0, 0, actor, results, 0, TraceCallbackForDitherTransparency, &count);
|
||||
0, 0, actor, results, TRACE_PortalRestrict, TraceCallbackForDitherTransparency, &CurrentMapSections);
|
||||
campos.Z += actor->Height * 0.5;
|
||||
Trace(campos, startsec, vvec, distance,
|
||||
0, 0, actor, results, 0, TraceCallbackForDitherTransparency, &count);
|
||||
0, 0, actor, results, TRACE_PortalRestrict, TraceCallbackForDitherTransparency, &CurrentMapSections);
|
||||
campos.Z -= actor->Height * 0.5;
|
||||
campos.X += horix; campos.Y -= horiy;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -150,6 +150,7 @@ struct HWDrawInfo
|
|||
Clipper *rClipper; // Radar clipper
|
||||
FRenderViewpoint Viewpoint;
|
||||
HWViewpointUniforms VPUniforms; // per-viewpoint uniform state
|
||||
VSMatrix ProjectionMatrix2;
|
||||
TArray<HWPortal *> Portals;
|
||||
TArray<HWDecal *> Decals[2]; // the second slot is for mirrors which get rendered in a separate pass.
|
||||
TArray<HUDSprite> hudsprites; // These may just be stored by value.
|
||||
|
|
|
|||
|
|
@ -125,6 +125,7 @@ bool FPortalSceneState::RenderFirstSkyPortal(int recursion, HWDrawInfo *outer_di
|
|||
{
|
||||
HWPortal * best = nullptr;
|
||||
unsigned bestindex = 0;
|
||||
bool usestencil = outer_di->Viewpoint.IsAllowedOoB();
|
||||
|
||||
// Find the one with the highest amount of lines.
|
||||
// Normally this is also the one that saves the largest amount
|
||||
|
|
@ -145,7 +146,7 @@ bool FPortalSceneState::RenderFirstSkyPortal(int recursion, HWDrawInfo *outer_di
|
|||
}
|
||||
|
||||
// If the portal area contains the current camera viewpoint, let's always use it because it's likely to give the largest area.
|
||||
if (p->boundingBox.contains(outer_di->Viewpoint.Pos))
|
||||
if (p->boundingBox.contains(usestencil ? outer_di->Viewpoint.OffPos : outer_di->Viewpoint.Pos))
|
||||
{
|
||||
best = p;
|
||||
bestindex = i;
|
||||
|
|
@ -157,7 +158,13 @@ bool FPortalSceneState::RenderFirstSkyPortal(int recursion, HWDrawInfo *outer_di
|
|||
if (best)
|
||||
{
|
||||
portals.Delete(bestindex);
|
||||
RenderPortal(best, state, false, outer_di);
|
||||
if (usestencil)
|
||||
{
|
||||
tempmatrix = outer_di->VPUniforms.mProjectionMatrix; // ensure perspective projection matrix for skies
|
||||
outer_di->VPUniforms.mProjectionMatrix = outer_di->ProjectionMatrix2;
|
||||
}
|
||||
RenderPortal(best, state, usestencil, outer_di);
|
||||
if (usestencil) outer_di->VPUniforms.mProjectionMatrix = tempmatrix;
|
||||
delete best;
|
||||
return true;
|
||||
}
|
||||
|
|
@ -410,20 +417,23 @@ void HWScenePortalBase::ClearClipper(HWDrawInfo *di, Clipper *clipper)
|
|||
|
||||
// Set the clipper to the minimal visible area
|
||||
clipper->SafeAddClipRange(0, 0xffffffff);
|
||||
auto outvp = outer_di->Viewpoint;
|
||||
DVector3 outPos = clipper->amRadar ? outvp.OffPos : outvp.Pos;
|
||||
angle_t padding = clipper->amRadar ? 0x00200000 : 0x00000000; // Make radar clipping more aggressive (reveal less)
|
||||
for (unsigned int i = 0; i < lines.Size(); i++)
|
||||
{
|
||||
DAngle startAngle = (DVector2(lines[i].glseg.x2, lines[i].glseg.y2) - outer_di->Viewpoint.Pos).Angle() + angleOffset;
|
||||
DAngle endAngle = (DVector2(lines[i].glseg.x1, lines[i].glseg.y1) - outer_di->Viewpoint.Pos).Angle() + angleOffset;
|
||||
DAngle startAngle = (DVector2(lines[i].glseg.x2, lines[i].glseg.y2) - outPos).Angle() + angleOffset;
|
||||
DAngle endAngle = (DVector2(lines[i].glseg.x1, lines[i].glseg.y1) - outPos).Angle() + angleOffset;
|
||||
|
||||
if (deltaangle(endAngle, startAngle) < nullAngle)
|
||||
{
|
||||
clipper->SafeRemoveClipRangeRealAngles(startAngle.BAMs(), endAngle.BAMs());
|
||||
clipper->SafeRemoveClipRangeRealAngles(startAngle.BAMs() + padding, endAngle.BAMs() - padding);
|
||||
}
|
||||
}
|
||||
|
||||
// and finally clip it to the visible area
|
||||
angle_t a1 = di->FrustumAngle();
|
||||
if (a1 < ANGLE_180) clipper->SafeAddClipRangeRealAngles(di->Viewpoint.Angles.Yaw.BAMs() + a1, di->Viewpoint.Angles.Yaw.BAMs() - a1);
|
||||
if (!clipper->amRadar && a1 < ANGLE_180) clipper->SafeAddClipRangeRealAngles(di->Viewpoint.Angles.Yaw.BAMs() + a1, di->Viewpoint.Angles.Yaw.BAMs() - a1);
|
||||
|
||||
// lock the parts that have just been clipped out.
|
||||
clipper->SetSilhouette();
|
||||
|
|
@ -608,6 +618,8 @@ bool HWLineToLinePortal::Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *cl
|
|||
P_TranslatePortalZ(origin, vp.Pos.Z);
|
||||
P_TranslatePortalXY(origin, vp.Path[0].X, vp.Path[0].Y);
|
||||
P_TranslatePortalXY(origin, vp.Path[1].X, vp.Path[1].Y);
|
||||
P_TranslatePortalXY(origin, vp.OffPos.X, vp.OffPos.Y);
|
||||
P_TranslatePortalZ(origin, vp.OffPos.Z);
|
||||
if (!vp.showviewer && vp.camera != nullptr && P_PointOnLineSidePrecise(vp.Path[0], glport->lines[0]->mDestination) != P_PointOnLineSidePrecise(vp.Path[1], glport->lines[0]->mDestination))
|
||||
{
|
||||
double distp = (vp.Path[0] - vp.Path[1]).Length();
|
||||
|
|
|
|||
|
|
@ -112,6 +112,8 @@ struct FPortalSceneState
|
|||
|
||||
int skyboxrecursion = 0;
|
||||
|
||||
VSMatrix tempmatrix;
|
||||
|
||||
void BeginScene()
|
||||
{
|
||||
UniqueSkies.Clear();
|
||||
|
|
@ -145,7 +147,7 @@ public:
|
|||
virtual bool NeedDepthBuffer() { return true; }
|
||||
virtual void DrawContents(HWDrawInfo *di, FRenderState &state)
|
||||
{
|
||||
if (Setup(di, state, di->mClipper))
|
||||
if (Setup(di, state, (di->Viewpoint.IsAllowedOoB() ? di->rClipper : di->mClipper)))
|
||||
{
|
||||
di->DrawScene(DM_PORTAL);
|
||||
Shutdown(di, state);
|
||||
|
|
|
|||
|
|
@ -130,7 +130,6 @@ void HWSkyInfo::init(HWDrawInfo *di, sector_t* sec, int skypos, int sky1, PalEnt
|
|||
void HWWall::SkyPlane(HWWallDispatcher *di, sector_t *sector, int plane, bool allowreflect)
|
||||
{
|
||||
int ptype = -1;
|
||||
if (di->di && di->di->Viewpoint.IsAllowedOoB()) return; // Couldn't prevent sky portal occlusion. Skybox is bad in ortho too.
|
||||
|
||||
FSectorPortal *sportal = sector->ValidatePortal(plane);
|
||||
if (sportal != nullptr && sportal->mFlags & PORTSF_INSKYBOX) sportal = nullptr; // no recursions, delete it here to simplify the following code
|
||||
|
|
@ -155,6 +154,7 @@ void HWWall::SkyPlane(HWWallDispatcher *di, sector_t *sector, int plane, bool al
|
|||
case PORTS_PORTAL:
|
||||
case PORTS_LINKEDPORTAL:
|
||||
{
|
||||
if (di->di && di->di->Viewpoint.IsAllowedOoB()) return;
|
||||
auto glport = sector->GetPortalGroup(plane);
|
||||
if (glport != NULL)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -2181,8 +2181,6 @@ void HWWall::Process(HWWallDispatcher *di, seg_t *seg, sector_t * frontsector, s
|
|||
}
|
||||
|
||||
bool isportal = seg->linedef->isVisualPortal() && seg->sidedef == seg->linedef->sidedef[0];
|
||||
// Don't render portal insides if in orthographic mode
|
||||
if (di->di) isportal &= !(di->di->Viewpoint.IsOrtho());
|
||||
|
||||
//return;
|
||||
// [GZ] 3D middle textures are necessarily two-sided, even if they lack the explicit two-sided flag
|
||||
|
|
|
|||
|
|
@ -550,8 +550,12 @@ void R_InterpolateView(FRenderViewpoint& viewPoint, const player_t* const player
|
|||
const int prevPortalGroup = viewLvl->PointInRenderSubsector(iView->Old.Pos)->sector->PortalGroup;
|
||||
const int curPortalGroup = viewLvl->PointInRenderSubsector(iView->New.Pos)->sector->PortalGroup;
|
||||
|
||||
const DVector2 portalOffset = viewLvl->Displacements.getOffset(prevPortalGroup, curPortalGroup);
|
||||
viewPoint.Pos = iView->Old.Pos * inverseTicFrac + (iView->New.Pos - portalOffset) * ticFrac;
|
||||
if (viewPoint.IsAllowedOoB() && prevPortalGroup != curPortalGroup) viewPoint.Pos = iView->New.Pos;
|
||||
else
|
||||
{
|
||||
const DVector2 portalOffset = viewLvl->Displacements.getOffset(prevPortalGroup, curPortalGroup);
|
||||
viewPoint.Pos = iView->Old.Pos * inverseTicFrac + (iView->New.Pos - portalOffset) * ticFrac;
|
||||
}
|
||||
viewPoint.Path[0] = viewPoint.Path[1] = iView->New.Pos;
|
||||
}
|
||||
}
|
||||
|
|
@ -708,6 +712,18 @@ void FRenderViewpoint::SetViewAngle(const FViewWindow& viewWindow)
|
|||
ViewVector3D.Y = v.Y * PitchCos;
|
||||
ViewVector3D.Z = -PitchSin;
|
||||
|
||||
if (IsOrtho() || IsAllowedOoB()) // These auto-ensure that camera and camera->ViewPos exist
|
||||
{
|
||||
if (camera->tracer != NULL)
|
||||
{
|
||||
OffPos = camera->tracer->Pos();
|
||||
}
|
||||
else
|
||||
{
|
||||
OffPos = Pos + ViewVector3D * camera->ViewPos->Offset.Length();
|
||||
}
|
||||
}
|
||||
|
||||
if (IsOrtho() && (camera->ViewPos->Offset.XY().Length() > 0.0))
|
||||
{
|
||||
ScreenProj = 1.34396 / camera->ViewPos->Offset.Length() / tan (FieldOfView.Radians()*0.5); // [DVR] Estimated. +/-1 should be top/bottom of screen.
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ struct FRenderViewpoint
|
|||
FRotator HWAngles; // Actual rotation angles for the hardware renderer
|
||||
DVector2 ViewVector; // HWR only: direction the camera is facing.
|
||||
DVector3 ViewVector3D; // 3D direction the camera is facing.
|
||||
DVector3 OffPos; // Viewpoint position to use for Ortho and OoB calculations
|
||||
AActor *ViewActor; // either the same as camera or nullptr
|
||||
FLevelLocals *ViewLevel; // The level this viewpoint is on.
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue