Allow portal rendering and sky rendering (with stencils) and reflective flats with OoB and Ortho viewpoints. Works with r_radarclipper too.
This commit is contained in:
parent
51bd612f6f
commit
6c93c3d564
13 changed files with 300 additions and 137 deletions
|
|
@ -1226,6 +1226,9 @@ enum
|
|||
WALLF_ABSLIGHTING_BOTTOM = WALLF_ABSLIGHTING_TIER << 2, // Bottom tier light is absolute instead of relative
|
||||
|
||||
WALLF_DITHERTRANS = 8192, // Render with dithering transparency shader (gets reset every frame)
|
||||
WALLF_DITHERTRANS_TOP = WALLF_DITHERTRANS << 0, // Top tier (gets reset every frame)
|
||||
WALLF_DITHERTRANS_MID = WALLF_DITHERTRANS << 1, // Mid tier (gets reset every frame)
|
||||
WALLF_DITHERTRANS_BOTTOM = WALLF_DITHERTRANS << 2, // Bottom tier (gets reset every frame)
|
||||
};
|
||||
|
||||
struct side_t
|
||||
|
|
@ -1303,6 +1306,8 @@ struct side_t
|
|||
int numsegs;
|
||||
int sidenum;
|
||||
|
||||
int dithertranscount;
|
||||
|
||||
int GetLightLevel (bool foggy, int baselight, int which, bool is3dlight=false, int *pfakecontrast_usedbygzdoom=NULL) const;
|
||||
|
||||
void SetLight(int16_t l)
|
||||
|
|
|
|||
|
|
@ -174,6 +174,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());
|
||||
|
|
@ -470,4 +471,4 @@ ADD_STAT(lightprobes)
|
|||
FString out;
|
||||
out.Format("Rendering probe: %d / %d", lightProbeBuilder.GetStep(), level.lightProbes.Size());
|
||||
return out;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -290,15 +290,17 @@ void HWDrawInfo::AddLine (seg_t *seg, bool portalclip, FRenderState& state)
|
|||
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(drawctx, 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);
|
||||
backsector = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -316,7 +318,7 @@ void HWDrawInfo::AddLine (seg_t *seg, bool portalclip, FRenderState& state)
|
|||
{
|
||||
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;
|
||||
}
|
||||
|
|
@ -329,31 +331,7 @@ void HWDrawInfo::AddLine (seg_t *seg, bool portalclip, FRenderState& state)
|
|||
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);
|
||||
|
|
@ -361,7 +339,7 @@ void HWDrawInfo::AddLine (seg_t *seg, bool portalclip, FRenderState& state)
|
|||
if (!seg->backsector)
|
||||
{
|
||||
if(!Viewpoint.IsAllowedOoB())
|
||||
if (!(seg->sidedef->Flags & WALLF_DITHERTRANS)) clipper.SafeAddClipRange(startAngle, endAngle);
|
||||
if (!(seg->sidedef->Flags & WALLF_DITHERTRANS_MID)) clipper.SafeAddClipRange(startAngle, endAngle);
|
||||
}
|
||||
else if (!ispoly) // Two-sided polyobjects never obstruct the view
|
||||
{
|
||||
|
|
@ -388,7 +366,7 @@ void HWDrawInfo::AddLine (seg_t *seg, bool portalclip, FRenderState& state)
|
|||
|
||||
if (hw_CheckClip(seg->sidedef, currentsector, backsector))
|
||||
{
|
||||
if(!Viewpoint.IsAllowedOoB() && !(seg->sidedef->Flags & WALLF_DITHERTRANS))
|
||||
if(!Viewpoint.IsAllowedOoB() && !(seg->sidedef->Flags & WALLF_DITHERTRANS_MID))
|
||||
clipper.SafeAddClipRange(startAngle, endAngle);
|
||||
}
|
||||
}
|
||||
|
|
@ -732,8 +710,8 @@ void HWDrawInfo::DoSubsector(subsector_t * sub, FRenderState& state)
|
|||
|
||||
if(Viewpoint.IsAllowedOoB() && sector->isSecret() && sector->wasSecret() && !r_radarclipper) return;
|
||||
|
||||
// cull everything if subsector outside all clippers
|
||||
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;
|
||||
|
|
@ -742,7 +720,10 @@ void HWDrawInfo::DoSubsector(subsector_t * sub, FRenderState& state)
|
|||
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);
|
||||
bool ceilreflect = (mCurrentPortal && strcmp(mCurrentPortal->GetName(), "Planemirror ceiling"));
|
||||
bool floorreflect = (mCurrentPortal && strcmp(mCurrentPortal->GetName(), "Planemirror floor"));
|
||||
double planez = (ceilreflect ? sector->ceilingplane.ZatPoint(Viewpoint.Pos) : sector->floorplane.ZatPoint(Viewpoint.Pos));
|
||||
angle_t pitchtemp;
|
||||
angle_t pitchmin = ANGLE_90;
|
||||
angle_t pitchmax = 0;
|
||||
|
|
@ -751,25 +732,43 @@ void HWDrawInfo::DoSubsector(subsector_t * sub, FRenderState& state)
|
|||
{
|
||||
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));
|
||||
pitchmax = clipperv.PointToPseudoPitch(seg->v1->fX(), seg->v1->fY(), sector->ceilingplane.ZatPoint(seg->v1));
|
||||
pitchmin = clipperv.PointToPseudoPitch(seg->v1->fX(), seg->v1->fY(),
|
||||
(ceilreflect || floorreflect) ?
|
||||
2 * planez - sector->floorplane.ZatPoint(seg->v1) :
|
||||
sector->floorplane.ZatPoint(seg->v1));
|
||||
pitchmax = clipperv.PointToPseudoPitch(seg->v1->fX(), seg->v1->fY(),
|
||||
(ceilreflect || floorreflect) ?
|
||||
2 * planez - sector->ceilingplane.ZatPoint(seg->v1) :
|
||||
sector->ceilingplane.ZatPoint(seg->v1));
|
||||
pitchvisible |= clipperv.SafeCheckRange(pitchmin, pitchmax);
|
||||
}
|
||||
if (pitchvisible && anglevisible && radarvisible) break;
|
||||
if (!pitchvisible)
|
||||
{
|
||||
pitchtemp = clipperv.PointToPseudoPitch(seg->v2->fX(), seg->v2->fY(), sector->floorplane.ZatPoint(seg->v2));
|
||||
pitchtemp = clipperv.PointToPseudoPitch(seg->v2->fX(), seg->v2->fY(),
|
||||
(ceilreflect || floorreflect) ?
|
||||
2 * planez - sector->floorplane.ZatPoint(seg->v2) :
|
||||
sector->floorplane.ZatPoint(seg->v2));
|
||||
if (int(pitchmin) > int(pitchtemp)) pitchmin = pitchtemp;
|
||||
pitchtemp = clipperv.PointToPseudoPitch(seg->v2->fX(), seg->v2->fY(), sector->ceilingplane.ZatPoint(seg->v2));
|
||||
pitchtemp = clipperv.PointToPseudoPitch(seg->v2->fX(), seg->v2->fY(),
|
||||
(ceilreflect || floorreflect) ?
|
||||
2 * planez - sector->ceilingplane.ZatPoint(seg->v2) :
|
||||
sector->ceilingplane.ZatPoint(seg->v2));
|
||||
if (int(pitchmax) < int(pitchtemp)) pitchmax = pitchtemp;
|
||||
pitchvisible |= clipperv.SafeCheckRange(pitchmin, pitchmax);
|
||||
}
|
||||
|
|
@ -838,7 +837,7 @@ void HWDrawInfo::DoSubsector(subsector_t * sub, FRenderState& state)
|
|||
SetupSprite.Unclock();
|
||||
}
|
||||
}
|
||||
if (r_dithertransparency && Viewpoint.IsAllowedOoB() && (RTnum < MAXDITHERACTORS))
|
||||
if (r_dithertransparency && Viewpoint.IsAllowedOoB() && (RTnum < MAXDITHERACTORS) && mCurrentPortal == nullptr)
|
||||
{
|
||||
// [DVR] Not parallelizable due to variables RTnum and RenderedTargets[]
|
||||
for (auto p = sector->touching_renderthings; p != nullptr; p = p->m_snext)
|
||||
|
|
@ -992,8 +991,8 @@ void HWDrawInfo::RenderOrthoNoFog(FRenderState& state)
|
|||
{
|
||||
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);
|
||||
|
|
@ -1018,16 +1017,8 @@ void HWDrawInfo::RenderBSP(void *node, bool drawpsprites, FRenderState& state)
|
|||
viewy = FLOAT2FIXED(Viewpoint.Pos.Y);
|
||||
if (r_radarclipper && !(Level->flags3 & LEVEL3_NOFOGOFWAR) && Viewpoint.IsAllowedOoB())
|
||||
{
|
||||
if (Viewpoint.camera->tracer != nullptr)
|
||||
{
|
||||
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.
|
||||
|
|
|
|||
|
|
@ -387,18 +387,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)
|
||||
|
|
@ -460,7 +452,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() );
|
||||
|
|
@ -484,7 +476,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();
|
||||
|
|
|
|||
|
|
@ -113,6 +113,7 @@ void HWDrawInfo::StartScene(FRenderViewpoint &parentvp, HWViewpointUniforms *uni
|
|||
VPUniforms.mProjectionMatrix.loadIdentity();
|
||||
VPUniforms.mViewMatrix.loadIdentity();
|
||||
VPUniforms.mNormalViewMatrix.loadIdentity();
|
||||
ProjectionMatrix2.loadIdentity();
|
||||
VPUniforms.mViewOffsetX = -screen->mSceneViewport.left;
|
||||
VPUniforms.mViewOffsetY = -screen->mSceneViewport.top;
|
||||
VPUniforms.mViewHeight = viewheight;
|
||||
|
|
@ -926,63 +927,84 @@ static ETraceStatus CheckForViewpointActor(FTraceResults& res, void* userdata)
|
|||
|
||||
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))
|
||||
sector_t* linesec = res.Line->sidedef[res.Side]->sector;
|
||||
if (linesec->subsectorcount > 0 && (*CurMapSections)[linesec->subsectors[0]->mapsection])
|
||||
{
|
||||
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.Line->sidedef[!res.Side])
|
||||
{
|
||||
// Two sided line! So let's find out if mid, top, or bottom texture needs dithered transparency
|
||||
bf = max(bf, res.Line->sidedef[!res.Side]->sector->floorplane.ZatPoint(res.HitPos.XY()));
|
||||
bc = min(bc, res.Line->sidedef[!res.Side]->sector->ceilingplane.ZatPoint(res.HitPos.XY()));
|
||||
if (res.HitPos.Z <= bf) res.Line->sidedef[res.Side]->Flags |= WALLF_DITHERTRANS_BOTTOM;
|
||||
else if (res.HitPos.Z < bc) res.Line->sidedef[res.Side]->Flags |= WALLF_DITHERTRANS_MID;
|
||||
else res.Line->sidedef[res.Side]->Flags |= WALLF_DITHERTRANS_TOP;
|
||||
|
||||
res.Line->sidedef[res.Side]->dithertranscount = max<int>(1, res.Line->sidedef[!res.Side]->sector->e->XFloor.ffloors.Size());
|
||||
}
|
||||
else if ((res.HitPos.Z <= bc) && (res.HitPos.Z >= bf))
|
||||
{
|
||||
res.Line->sidedef[res.Side]->Flags |= WALLF_DITHERTRANS_MID;
|
||||
res.Line->sidedef[res.Side]->dithertranscount = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
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.HitVector.dot(res.Sector->floorplane.Normal()) < 0.0)
|
||||
{
|
||||
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.HitVector.dot(res.Sector->ceilingplane.Normal()) < 0.0)
|
||||
{
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -999,6 +1021,7 @@ static ETraceStatus TraceCallbackForDitherTransparency(FTraceResults& res, void*
|
|||
|
||||
void HWDrawInfo::SetDitherTransFlags(AActor* actor)
|
||||
{
|
||||
// This should really be moved to a shader and have the GPU do some shape-tracing.
|
||||
if (actor && actor->Sector)
|
||||
{
|
||||
FTraceResults results;
|
||||
|
|
@ -1008,13 +1031,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;
|
||||
|
|
@ -1022,13 +1043,25 @@ 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;
|
||||
}
|
||||
|
||||
// Tracers don't work on 3D floors when you are starting in the same sector (standing under them, for example)
|
||||
if (actor->Sector->e->XFloor.ffloors.Size()) // 3D floor
|
||||
{
|
||||
F3DFloor *rover;
|
||||
for (int kk = 0; kk < (int)actor->Sector->e->XFloor.ffloors.Size(); kk++)
|
||||
{
|
||||
rover = actor->Sector->e->XFloor.ffloors[kk];
|
||||
rover->top.plane->dithertransflag = true;
|
||||
rover->bottom.plane->dithertransflag = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -152,6 +152,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.
|
||||
|
|
|
|||
|
|
@ -330,6 +330,7 @@ void HWFlat::DrawFlat(HWFlatDispatcher *di, FRenderState &state, bool translucen
|
|||
int rel = getExtraLight();
|
||||
|
||||
state.SetNormal(plane.plane.Normal().X, plane.plane.Normal().Z, plane.plane.Normal().Y);
|
||||
double zshift = (plane.plane.Normal().Z > 0.0 ? 0.01f : -0.01f); // The HWPlaneMirrorPortal::DrawPortalStencil() z-fights with flats
|
||||
state.SetLightProbeIndex(sector->lightProbe.index);
|
||||
|
||||
SetColor(state, di->Level, di->lightmode, lightlevel, rel, di->isFullbrightScene(), Colormap, alpha);
|
||||
|
|
@ -384,7 +385,18 @@ void HWFlat::DrawFlat(HWFlatDispatcher *di, FRenderState &state, bool translucen
|
|||
else state.AlphaFunc(Alpha_GEqual, 0.f);
|
||||
state.SetMaterial(texture, UF_Texture, 0, CLAMP_NONE, NO_TRANSLATION, -1);
|
||||
bool texmatrix = SetPlaneTextureRotation(state, &plane, texture);
|
||||
if (di->di && di->di->Viewpoint.IsAllowedOoB())
|
||||
{
|
||||
di->di->VPUniforms.mViewMatrix.translate(0.0, zshift, 0.0);
|
||||
di->di->vpIndex = state.SetViewpoint(di->di->VPUniforms);
|
||||
// screen->mViewpoints->SetViewpoint(state, &di->di->VPUniforms);
|
||||
}
|
||||
DrawSubsectors(di, state);
|
||||
if (di->di && di->di->Viewpoint.IsAllowedOoB())
|
||||
{
|
||||
di->di->VPUniforms.mViewMatrix.translate(0.0, -zshift, 0.0);
|
||||
di->di->vpIndex = state.SetViewpoint(di->di->VPUniforms);
|
||||
}
|
||||
if (texmatrix)
|
||||
state.SetTextureMatrix(VSMatrix::identity());
|
||||
}
|
||||
|
|
@ -557,7 +569,7 @@ void HWFlat::ProcessSector(HWFlatDispatcher *di, FRenderState& state, sector_t *
|
|||
//
|
||||
//
|
||||
//
|
||||
if (((which & SSRF_RENDERFLOOR) && (!di->di || (((frontsector->floorplane.ZatPoint(vp->Pos) <= vp->Pos.Z) && (!section || !(section->flags & FSection::DONTRENDERFLOOR)))))) && !(di->di && vp->IsOrtho() && (vp->PitchSin < 0.0)))
|
||||
if ((which & SSRF_RENDERFLOOR) && ((di->di && vp->IsOrtho()) ? vp->ViewVector3D.dot(frontsector->floorplane.Normal()) < 0.0 : (!di->di || (frontsector->floorplane.ZatPoint(vp->Pos) <= vp->Pos.Z))) && (!section || !(section->flags & FSection::DONTRENDERFLOOR)))
|
||||
{
|
||||
// process the original floor first.
|
||||
|
||||
|
|
@ -615,7 +627,7 @@ void HWFlat::ProcessSector(HWFlatDispatcher *di, FRenderState& state, sector_t *
|
|||
//
|
||||
//
|
||||
//
|
||||
if (((which & SSRF_RENDERCEILING) && ((!di->di || ((frontsector->ceilingplane.ZatPoint(vp->Pos) >= vp->Pos.Z) && (!section || !(section->flags & FSection::DONTRENDERCEILING)))))) && !(di->di && vp->IsOrtho() && (vp->PitchSin > 0.0)))
|
||||
if ((which & SSRF_RENDERCEILING) && ((di->di && vp->IsOrtho()) ? vp->ViewVector3D.dot(frontsector->ceilingplane.Normal()) < 0.0 : (!di->di || (frontsector->ceilingplane.ZatPoint(vp->Pos) >= vp->Pos.Z))) && (!section || !(section->flags & FSection::DONTRENDERCEILING)))
|
||||
{
|
||||
// process the original ceiling first.
|
||||
|
||||
|
|
@ -700,7 +712,7 @@ void HWFlat::ProcessSector(HWFlatDispatcher *di, FRenderState& state, sector_t *
|
|||
double ff_top = rover->top.plane->ZatPoint(sector->centerspot);
|
||||
if (ff_top < lastceilingheight)
|
||||
{
|
||||
if (!di->di || vp->Pos.Z <= rover->top.plane->ZatPoint(vp->Pos))
|
||||
if (!di->di || (vp->IsOrtho() ? vp->ViewVector3D.dot(rover->top.plane->Normal()) > 0.0 : vp->Pos.Z <= rover->top.plane->ZatPoint(vp->Pos)))
|
||||
{
|
||||
SetFrom3DFloor(rover, true, !!(rover->flags&FF_FOG));
|
||||
Colormap.FadeColor = frontsector->Colormap.FadeColor;
|
||||
|
|
@ -714,7 +726,7 @@ void HWFlat::ProcessSector(HWFlatDispatcher *di, FRenderState& state, sector_t *
|
|||
double ff_bottom = rover->bottom.plane->ZatPoint(sector->centerspot);
|
||||
if (ff_bottom < lastceilingheight)
|
||||
{
|
||||
if (!di->di || vp->Pos.Z <= rover->bottom.plane->ZatPoint(vp->Pos))
|
||||
if (!di->di || (vp->IsOrtho() ? vp->ViewVector3D.dot(rover->bottom.plane->Normal()) > 0.0 : vp->Pos.Z <= rover->bottom.plane->ZatPoint(vp->Pos)))
|
||||
{
|
||||
SetFrom3DFloor(rover, false, !(rover->flags&FF_FOG));
|
||||
Colormap.FadeColor = frontsector->Colormap.FadeColor;
|
||||
|
|
@ -740,7 +752,7 @@ void HWFlat::ProcessSector(HWFlatDispatcher *di, FRenderState& state, sector_t *
|
|||
double ff_bottom = rover->bottom.plane->ZatPoint(sector->centerspot);
|
||||
if (ff_bottom > lastfloorheight || (rover->flags&FF_FIX))
|
||||
{
|
||||
if (!di->di || vp->Pos.Z >= rover->bottom.plane->ZatPoint(vp->Pos))
|
||||
if (!di->di || (vp->IsOrtho() ? vp->ViewVector3D.dot(rover->bottom.plane->Normal()) > 0.0 : vp->Pos.Z >= rover->bottom.plane->ZatPoint(vp->Pos)))
|
||||
{
|
||||
SetFrom3DFloor(rover, false, !(rover->flags&FF_FOG));
|
||||
Colormap.FadeColor = frontsector->Colormap.FadeColor;
|
||||
|
|
@ -761,7 +773,7 @@ void HWFlat::ProcessSector(HWFlatDispatcher *di, FRenderState& state, sector_t *
|
|||
double ff_top = rover->top.plane->ZatPoint(sector->centerspot);
|
||||
if (ff_top > lastfloorheight)
|
||||
{
|
||||
if (!di->di || vp->Pos.Z >= rover->top.plane->ZatPoint(vp->Pos))
|
||||
if (!di->di || (vp->IsOrtho() ? vp->ViewVector3D.dot(rover->top.plane->Normal()) > 0.0 : vp->Pos.Z >= rover->top.plane->ZatPoint(vp->Pos)))
|
||||
{
|
||||
SetFrom3DFloor(rover, true, !!(rover->flags&FF_FOG));
|
||||
Colormap.FadeColor = frontsector->Colormap.FadeColor;
|
||||
|
|
|
|||
|
|
@ -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,14 @@ bool FPortalSceneState::RenderFirstSkyPortal(int recursion, HWDrawInfo *outer_di
|
|||
if (best)
|
||||
{
|
||||
portals.Delete(bestindex);
|
||||
RenderPortal(best, state, false, outer_di);
|
||||
if (usestencil && ((strcmp(best->GetName(), "Sky") == 0) || (strcmp(best->GetName(), "Skybox") == 0)))
|
||||
{
|
||||
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 && ((strcmp(best->GetName(), "Sky") == 0) || (strcmp(best->GetName(), "Skybox") == 0)))
|
||||
outer_di->VPUniforms.mProjectionMatrix = tempmatrix;
|
||||
delete best;
|
||||
return true;
|
||||
}
|
||||
|
|
@ -408,20 +416,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();
|
||||
|
|
@ -493,6 +504,7 @@ bool HWMirrorPortal::Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *clippe
|
|||
}
|
||||
|
||||
auto &vp = di->Viewpoint;
|
||||
state->vpIsAllowedOoB = vp.IsAllowedOoB();
|
||||
di->UpdateCurrentMapSection();
|
||||
|
||||
di->mClipPortal = this;
|
||||
|
|
@ -597,6 +609,7 @@ bool HWLineToLinePortal::Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *cl
|
|||
return false;
|
||||
}
|
||||
auto &vp = di->Viewpoint;
|
||||
state->vpIsAllowedOoB = vp.IsAllowedOoB();
|
||||
di->mClipPortal = this;
|
||||
|
||||
line_t *origin = glport->lines[0]->mOrigin;
|
||||
|
|
@ -606,6 +619,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();
|
||||
|
|
@ -674,6 +689,7 @@ bool HWSkyboxPortal::Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *clippe
|
|||
return false;
|
||||
}
|
||||
auto &vp = di->Viewpoint;
|
||||
state->vpIsAllowedOoB = vp.IsAllowedOoB();
|
||||
|
||||
state->skyboxrecursion++;
|
||||
state->PlaneMirrorMode = 0;
|
||||
|
|
@ -785,14 +801,21 @@ bool HWSectorStackPortal::Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *c
|
|||
|
||||
FSectorPortalGroup *portal = origin;
|
||||
auto &vp = di->Viewpoint;
|
||||
state->vpIsAllowedOoB = vp.IsAllowedOoB();
|
||||
|
||||
vp.Pos += origin->mDisplacement;
|
||||
vp.ActorPos += origin->mDisplacement;
|
||||
vp.ViewActor = nullptr;
|
||||
vp.OffPos += origin->mDisplacement;
|
||||
|
||||
// avoid recursions!
|
||||
if (origin->plane != -1) screen->instack[origin->plane]++;
|
||||
|
||||
if (vp.IsAllowedOoB() && lines.Size() > 0)
|
||||
{
|
||||
flat.plane.GetFromSector(lines[0].sub->sector, origin->plane);
|
||||
di->SetClipHeight(flat.plane.plane.ZatPoint(vp.Pos),
|
||||
flat.plane.plane.Normal().Z > 0 ? -1.f : 1.f);
|
||||
}
|
||||
di->SetupView(rstate, vp.Pos.X, vp.Pos.Y, vp.Pos.Z, !!(state->MirrorFlag & 1), !!(state->PlaneMirrorFlag & 1));
|
||||
SetupCoverage(di);
|
||||
ClearClipper(di, clipper);
|
||||
|
|
@ -800,6 +823,7 @@ bool HWSectorStackPortal::Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *c
|
|||
// 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 = di->Level->PointInRenderSubsector(vp.Pos);
|
||||
if (vp.IsAllowedOoB()) sub = di->Level->PointInRenderSubsector(vp.OffPos);
|
||||
if (!(di->ss_renderflags[sub->Index()] & SSRF_SEEN))
|
||||
{
|
||||
clipper->SafeAddClipRange(0, ANGLE_MAX);
|
||||
|
|
@ -809,6 +833,30 @@ bool HWSectorStackPortal::Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *c
|
|||
}
|
||||
|
||||
|
||||
void HWSectorStackPortal::DrawPortalStencil(FRenderState &state, int pass)
|
||||
{
|
||||
if (mState->vpIsAllowedOoB)
|
||||
{
|
||||
bool isceiling = planesused & (1 << sector_t::ceiling);
|
||||
for (unsigned i = 0; i<subsectors.Size(); i++)
|
||||
{
|
||||
subsector_t *sub = subsectors[i];
|
||||
flat.section = sub->section;
|
||||
flat.iboindex = sub->sector->iboindex[isceiling ? sector_t::ceiling : sector_t::floor];
|
||||
flat.plane.GetFromSector(sub->sector, isceiling ? sector_t::ceiling : sector_t::floor);
|
||||
// if (isceiling) flat.plane.plane.FlipVert(); // Doesn't do anything. Stencil is a screen-space projection
|
||||
|
||||
state.SetNormal(flat.plane.plane.Normal().X, flat.plane.plane.Normal().Z, flat.plane.plane.Normal().Y);
|
||||
state.DrawIndexed(DT_Triangles, flat.iboindex + flat.section->vertexindex, flat.section->vertexcount, i == 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
HWPortal::DrawPortalStencil(state, pass);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void HWSectorStackPortal::Shutdown(HWDrawInfo *di, FRenderState &rstate)
|
||||
{
|
||||
if (origin->plane != -1) screen->instack[origin->plane]--;
|
||||
|
|
@ -843,6 +891,7 @@ bool HWPlaneMirrorPortal::Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *c
|
|||
std::swap(screen->instack[sector_t::floor], screen->instack[sector_t::ceiling]);
|
||||
|
||||
auto &vp = di->Viewpoint;
|
||||
state->vpIsAllowedOoB = vp.IsAllowedOoB();
|
||||
old_pm = state->PlaneMirrorMode;
|
||||
|
||||
// the player is always visible in a mirror.
|
||||
|
|
@ -856,12 +905,38 @@ bool HWPlaneMirrorPortal::Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *c
|
|||
state->PlaneMirrorFlag++;
|
||||
di->SetClipHeight(planez, state->PlaneMirrorMode < 0 ? -1.f : 1.f);
|
||||
di->SetupView(rstate, vp.Pos.X, vp.Pos.Y, vp.Pos.Z, !!(state->MirrorFlag & 1), !!(state->PlaneMirrorFlag & 1));
|
||||
vp.ViewVector3D.Z = - vp.ViewVector3D.Z;
|
||||
vp.OffPos.Z = 2 * planez - vp.OffPos.Z;
|
||||
ClearClipper(di, clipper);
|
||||
|
||||
di->UpdateCurrentMapSection();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void HWPlaneMirrorPortal::DrawPortalStencil(FRenderState &state, int pass)
|
||||
{
|
||||
if (mState->vpIsAllowedOoB)
|
||||
{
|
||||
bool isceiling = planesused & (1 << sector_t::ceiling);
|
||||
for (unsigned int i = 0; i < lines.Size(); i++)
|
||||
{
|
||||
flat.section = lines[i].sub->section;
|
||||
flat.iboindex = lines[i].sub->sector->iboindex[isceiling ? sector_t::ceiling : sector_t::floor];
|
||||
flat.plane.GetFromSector(lines[i].sub->sector, isceiling ? sector_t::ceiling : sector_t::floor);
|
||||
// if (isceiling) flat.plane.plane.FlipVert(); // Doesn't do anything. Stencil is a screen-space projection
|
||||
|
||||
state.SetNormal(flat.plane.plane.Normal().X, flat.plane.plane.Normal().Z, flat.plane.plane.Normal().Y);
|
||||
state.DrawIndexed(DT_Triangles, flat.iboindex + flat.section->vertexindex, flat.section->vertexcount, i == 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
HWPortal::DrawPortalStencil(state, pass);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void HWPlaneMirrorPortal::Shutdown(HWDrawInfo *di, FRenderState &rstate)
|
||||
{
|
||||
auto state = mState;
|
||||
|
|
|
|||
|
|
@ -59,13 +59,12 @@ class HWPortal
|
|||
TArray<unsigned int> mPrimIndices;
|
||||
unsigned int mTopCap = ~0u, mBottomCap = ~0u;
|
||||
|
||||
void DrawPortalStencil(FRenderState &state, int pass);
|
||||
|
||||
public:
|
||||
FPortalSceneState * mState;
|
||||
TArray<HWWall> lines;
|
||||
BoundingRect boundingBox;
|
||||
int planesused = 0;
|
||||
HWFlat flat;
|
||||
|
||||
HWPortal(FPortalSceneState *s, bool local = false) : mState(s), boundingBox(false)
|
||||
{
|
||||
|
|
@ -83,6 +82,7 @@ public:
|
|||
virtual bool NeedDepthBuffer() { return true; }
|
||||
virtual void DrawContents(HWDrawInfo *di, FRenderState &state) = 0;
|
||||
virtual void RenderAttached(HWDrawInfo *di, FRenderState& state) {}
|
||||
virtual void DrawPortalStencil(FRenderState &state, int pass);
|
||||
void SetupStencil(HWDrawInfo *di, FRenderState &state, bool usestencil);
|
||||
void RemoveStencil(HWDrawInfo *di, FRenderState &state, bool usestencil);
|
||||
|
||||
|
|
@ -105,6 +105,7 @@ struct FPortalSceneState
|
|||
|
||||
int PlaneMirrorMode = 0;
|
||||
bool inskybox = 0;
|
||||
bool vpIsAllowedOoB = 0;
|
||||
|
||||
UniqueList<HWSkyInfo> UniqueSkies;
|
||||
UniqueList<HWHorizonInfo> UniqueHorizons;
|
||||
|
|
@ -112,6 +113,8 @@ struct FPortalSceneState
|
|||
|
||||
int skyboxrecursion = 0;
|
||||
|
||||
VSMatrix tempmatrix;
|
||||
|
||||
void BeginScene()
|
||||
{
|
||||
UniqueSkies.Clear();
|
||||
|
|
@ -144,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, state);
|
||||
Shutdown(di, state);
|
||||
|
|
@ -266,6 +269,7 @@ struct HWSectorStackPortal : public HWScenePortalBase
|
|||
TArray<subsector_t *> subsectors;
|
||||
protected:
|
||||
bool Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *clipper) override;
|
||||
void DrawPortalStencil(FRenderState &state, int pass) override;
|
||||
void Shutdown(HWDrawInfo *di, FRenderState &rstate) override;
|
||||
virtual void * GetSource() const { return origin; }
|
||||
virtual bool IsSky() { return true; } // although this isn't a real sky it can be handled as one.
|
||||
|
|
@ -292,6 +296,7 @@ struct HWPlaneMirrorPortal : public HWScenePortalBase
|
|||
protected:
|
||||
bool Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *clipper) override;
|
||||
void Shutdown(HWDrawInfo *di, FRenderState &rstate) override;
|
||||
void DrawPortalStencil(FRenderState &state, int pass) override;
|
||||
virtual void * GetSource() const { return origin; }
|
||||
virtual const char *GetName();
|
||||
secplane_t * origin;
|
||||
|
|
|
|||
|
|
@ -130,7 +130,6 @@ void HWSkyInfo::init(HWDrawInfo *di, sector_t* sec, int skypos, int sky1, PalEnt
|
|||
void HWWall::SkyPlane(HWWallDispatcher *di, FRenderState& state, 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,13 @@ void HWWall::SkyPlane(HWWallDispatcher *di, FRenderState& state, sector_t *secto
|
|||
case PORTS_PORTAL:
|
||||
case PORTS_LINKEDPORTAL:
|
||||
{
|
||||
if (di->di && di->di->Viewpoint.IsAllowedOoB())
|
||||
{
|
||||
secplane_t myplane = plane ? sector->ceilingplane : sector->floorplane;
|
||||
if (di->di->Viewpoint.IsOrtho() && di->di->Viewpoint.ViewVector3D.dot(myplane.Normal()) > 0.0) return;
|
||||
else if (plane==1 && di->di->Viewpoint.Pos.Z >= myplane.ZatPoint(di->di->Viewpoint.Pos)) return;
|
||||
else if (plane==0 && di->di->Viewpoint.Pos.Z <= myplane.ZatPoint(di->di->Viewpoint.Pos)) return;
|
||||
}
|
||||
auto glport = sector->GetPortalGroup(plane);
|
||||
if (glport != NULL)
|
||||
{
|
||||
|
|
@ -314,7 +320,10 @@ void HWWall::SkyTop(HWWallDispatcher *di, FRenderState& state, seg_t * seg,secto
|
|||
if (backreflect > 0 && bs->ceilingplane.fD() == fs->ceilingplane.fD() && !bs->isClosed())
|
||||
{
|
||||
// Don't add intra-portal line to the portal.
|
||||
return;
|
||||
if (!(di->di && di->di->Viewpoint.IsAllowedOoB()))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
@ -393,7 +402,10 @@ void HWWall::SkyBottom(HWWallDispatcher *di, FRenderState& state, seg_t * seg,se
|
|||
if (backreflect > 0 && bs->floorplane.fD() == fs->floorplane.fD() && !bs->isClosed())
|
||||
{
|
||||
// Don't add intra-portal line to the portal.
|
||||
return;
|
||||
if (!(di->di && di->di->Viewpoint.IsAllowedOoB()))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
|
|||
|
|
@ -84,16 +84,32 @@ void SetSplitPlanes(FRenderState& state, const secplane_t& top, const secplane_t
|
|||
|
||||
void HWWall::RenderWall(FRenderState &state, int textured)
|
||||
{
|
||||
if (seg->sidedef->Flags & WALLF_DITHERTRANS) state.SetEffect(EFF_DITHERTRANS);
|
||||
bool ditherT = (type == RENDERWALL_BOTTOM) && (seg->sidedef->Flags & WALLF_DITHERTRANS_BOTTOM);
|
||||
ditherT |= (type == RENDERWALL_TOP) && (seg->sidedef->Flags & WALLF_DITHERTRANS_TOP);
|
||||
ditherT = ditherT || (seg->sidedef->Flags & WALLF_DITHERTRANS_MID);
|
||||
if (ditherT)
|
||||
{
|
||||
state.SetEffect(EFF_DITHERTRANS);
|
||||
}
|
||||
assert(vertcount > 0);
|
||||
state.SetLightIndex(dynlightindex);
|
||||
state.SetLightProbeIndex(seg->sidedef->lightProbe.index);
|
||||
state.Draw(DT_TriangleFan, vertindex, vertcount);
|
||||
vertexcount += vertcount;
|
||||
if (seg->sidedef->Flags & WALLF_DITHERTRANS)
|
||||
if (ditherT)
|
||||
{
|
||||
state.SetEffect(EFF_NONE);
|
||||
seg->sidedef->Flags &= ~WALLF_DITHERTRANS; // reset this every frame
|
||||
switch(type) // reset this every frame
|
||||
{
|
||||
case RENDERWALL_TOP:
|
||||
seg->sidedef->Flags &= ~WALLF_DITHERTRANS_TOP;
|
||||
break;
|
||||
case RENDERWALL_BOTTOM:
|
||||
seg->sidedef->Flags &= ~WALLF_DITHERTRANS_BOTTOM;
|
||||
break;
|
||||
default:
|
||||
if (seg->sidedef->dithertranscount-- <= 0) seg->sidedef->Flags &= ~WALLF_DITHERTRANS_MID;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -609,7 +625,8 @@ void HWWall::PutPortal(HWWallDispatcher *di, FRenderState& state, int ptype, int
|
|||
break;
|
||||
|
||||
case PORTALTYPE_PLANEMIRROR:
|
||||
if (ddi->drawctx->portalState.PlaneMirrorMode * planemirror->fC() <= 0)
|
||||
if (ddi->Viewpoint.IsOrtho() ? (ddi->Viewpoint.ViewVector3D.dot(planemirror->Normal()) < 0)
|
||||
: (ddi->drawctx->portalState.PlaneMirrorMode * planemirror->fC() <= 0))
|
||||
{
|
||||
planemirror = ddi->drawctx->portalState.UniquePlaneMirrors.Get(planemirror);
|
||||
portal = ddi->FindPortal(planemirror);
|
||||
|
|
@ -2049,8 +2066,6 @@ void HWWall::Process(HWWallDispatcher *di, FRenderState& state, seg_t *seg, sect
|
|||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
@ -704,6 +708,21 @@ void FRenderViewpoint::SetViewAngle(const FViewWindow& viewWindow)
|
|||
ViewVector.X = v.X;
|
||||
ViewVector.Y = v.Y;
|
||||
HWAngles.Yaw = FAngle::fromDeg(270.0 - Angles.Yaw.Degrees());
|
||||
ViewVector3D.X = v.X * PitchCos;
|
||||
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))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -25,6 +25,8 @@ struct FRenderViewpoint
|
|||
DRotator Angles; // Camera angles
|
||||
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