Merge remote-tracking branch 'gzdoom/modern' into hw_postprocess
This commit is contained in:
commit
32d837cdf1
164 changed files with 23408 additions and 12966 deletions
|
|
@ -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,6 +353,7 @@ void HWDrawInfo::RenderThings(subsector_t * sub, sector_t * sector)
|
|||
SetupSprite.Clock();
|
||||
sector_t * sec=sub->sector;
|
||||
// Handle all things in sector.
|
||||
const auto &vp = Viewpoint;
|
||||
for (auto p = sec->touching_renderthings; p != nullptr; p = p->m_snext)
|
||||
{
|
||||
auto thing = p->m_thing;
|
||||
|
|
@ -362,7 +363,7 @@ void HWDrawInfo::RenderThings(subsector_t * sub, sector_t * sector)
|
|||
FIntCVar *cvar = thing->GetInfo()->distancecheck;
|
||||
if (cvar != nullptr && *cvar >= 0)
|
||||
{
|
||||
double dist = (thing->Pos() - r_viewpoint.Pos).LengthSquared();
|
||||
double dist = (thing->Pos() - vp.Pos).LengthSquared();
|
||||
double check = (double)**cvar;
|
||||
if (dist >= check * check)
|
||||
{
|
||||
|
|
@ -383,7 +384,7 @@ void HWDrawInfo::RenderThings(subsector_t * sub, sector_t * sector)
|
|||
FIntCVar *cvar = thing->GetInfo()->distancecheck;
|
||||
if (cvar != nullptr && *cvar >= 0)
|
||||
{
|
||||
double dist = (thing->Pos() - r_viewpoint.Pos).LengthSquared();
|
||||
double dist = (thing->Pos() - vp.Pos).LengthSquared();
|
||||
double check = (double)**cvar;
|
||||
if (dist >= check * check)
|
||||
{
|
||||
|
|
@ -537,13 +538,13 @@ void HWDrawInfo::DoSubsector(subsector_t * sub)
|
|||
portal = fakesector->GetPortalGroup(sector_t::ceiling);
|
||||
if (portal != nullptr)
|
||||
{
|
||||
portal->AddSubsector(sub);
|
||||
AddSubsectorToPortal(portal, sub);
|
||||
}
|
||||
|
||||
portal = fakesector->GetPortalGroup(sector_t::floor);
|
||||
if (portal != nullptr)
|
||||
{
|
||||
portal->AddSubsector(sub);
|
||||
AddSubsectorToPortal(portal, sub);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -373,10 +373,10 @@ angle_t Clipper::AngleToPseudo(angle_t ang)
|
|||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
angle_t R_PointToPseudoAngle(double x, double y)
|
||||
angle_t Clipper::PointToPseudoAngle(double x, double y)
|
||||
{
|
||||
double vecx = x - r_viewpoint.Pos.X;
|
||||
double vecy = y - r_viewpoint.Pos.Y;
|
||||
double vecx = x - viewpoint->Pos.X;
|
||||
double vecy = y - viewpoint->Pos.Y;
|
||||
|
||||
if (vecx == 0 && vecy == 0)
|
||||
{
|
||||
|
|
@ -427,14 +427,15 @@ bool Clipper::CheckBox(const float *bspcoord)
|
|||
|
||||
// Find the corners of the box
|
||||
// that define the edges from current viewpoint.
|
||||
boxpos = (r_viewpoint.Pos.X <= bspcoord[BOXLEFT] ? 0 : r_viewpoint.Pos.X < bspcoord[BOXRIGHT ] ? 1 : 2) +
|
||||
(r_viewpoint.Pos.Y >= bspcoord[BOXTOP ] ? 0 : r_viewpoint.Pos.Y > bspcoord[BOXBOTTOM] ? 4 : 8);
|
||||
auto &vp = viewpoint;
|
||||
boxpos = (vp->Pos.X <= bspcoord[BOXLEFT] ? 0 : vp->Pos.X < bspcoord[BOXRIGHT ] ? 1 : 2) +
|
||||
(vp->Pos.Y >= bspcoord[BOXTOP ] ? 0 : vp->Pos.Y > bspcoord[BOXBOTTOM] ? 4 : 8);
|
||||
|
||||
if (boxpos == 5) return true;
|
||||
|
||||
check = checkcoord[boxpos];
|
||||
angle1 = R_PointToPseudoAngle (bspcoord[check[0]], bspcoord[check[1]]);
|
||||
angle2 = R_PointToPseudoAngle (bspcoord[check[2]], bspcoord[check[3]]);
|
||||
angle1 = PointToPseudoAngle (bspcoord[check[0]], bspcoord[check[1]]);
|
||||
angle2 = PointToPseudoAngle (bspcoord[check[2]], bspcoord[check[3]]);
|
||||
|
||||
return SafeCheckRange(angle2, angle1);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,14 +6,6 @@
|
|||
#include "r_utility.h"
|
||||
#include "memarena.h"
|
||||
|
||||
angle_t R_PointToPseudoAngle(double x, double y);
|
||||
|
||||
// Used to speed up angle calculations during clipping
|
||||
inline angle_t vertex_t::GetClipAngle()
|
||||
{
|
||||
return R_PointToPseudoAngle(p.X, p.Y);
|
||||
}
|
||||
|
||||
class ClipNode
|
||||
{
|
||||
friend class Clipper;
|
||||
|
|
@ -37,6 +29,7 @@ class Clipper
|
|||
ClipNode * clipnodes = nullptr;
|
||||
ClipNode * cliphead = nullptr;
|
||||
ClipNode * silhouette = nullptr; // will be preserved even when RemoveClipRange is called
|
||||
const FRenderViewpoint *viewpoint = nullptr;
|
||||
bool blocked = false;
|
||||
|
||||
static angle_t AngleToPseudo(angle_t ang);
|
||||
|
|
@ -78,6 +71,11 @@ public:
|
|||
c->next = c->prev = NULL;
|
||||
return c;
|
||||
}
|
||||
|
||||
void SetViewpoint(const FRenderViewpoint &vp)
|
||||
{
|
||||
viewpoint = &vp;
|
||||
}
|
||||
|
||||
void SetSilhouette();
|
||||
|
||||
|
|
@ -105,6 +103,13 @@ public:
|
|||
AddClipRange(startangle, endangle);
|
||||
}
|
||||
}
|
||||
|
||||
void SafeAddClipRange(const vertex_t *v1, const vertex_t *v2)
|
||||
{
|
||||
angle_t a2 = PointToPseudoAngle(v1->p.X, v1->p.Y);
|
||||
angle_t a1 = PointToPseudoAngle(v2->p.X, v2->p.Y);
|
||||
SafeAddClipRange(a1,a2);
|
||||
}
|
||||
|
||||
void SafeAddClipRangeRealAngles(angle_t startangle, angle_t endangle)
|
||||
{
|
||||
|
|
@ -141,13 +146,15 @@ public:
|
|||
{
|
||||
return blocked;
|
||||
}
|
||||
|
||||
angle_t PointToPseudoAngle(double x, double y);
|
||||
|
||||
bool CheckBox(const float *bspcoord);
|
||||
|
||||
// Used to speed up angle calculations during clipping
|
||||
inline angle_t GetClipAngle(vertex_t *v)
|
||||
{
|
||||
return unsigned(v->angletime) == starttime ? v->viewangle : (v->angletime = starttime, v->viewangle = R_PointToPseudoAngle(v->p.X, v->p.Y));
|
||||
return unsigned(v->angletime) == starttime ? v->viewangle : (v->angletime = starttime, v->viewangle = PointToPseudoAngle(v->p.X, v->p.Y));
|
||||
}
|
||||
|
||||
};
|
||||
|
|
|
|||
284
src/hwrenderer/scene/hw_drawinfo.cpp
Normal file
284
src/hwrenderer/scene/hw_drawinfo.cpp
Normal file
|
|
@ -0,0 +1,284 @@
|
|||
//
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// Copyright(C) 2000-2018 Christoph Oelckers
|
||||
// All rights reserved.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with this program. If not, see http://www.gnu.org/licenses/
|
||||
//
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
/*
|
||||
** gl_drawinfo.cpp
|
||||
** Basic scene draw info management class
|
||||
**
|
||||
*/
|
||||
|
||||
#include "a_sharedglobal.h"
|
||||
#include "r_utility.h"
|
||||
#include "r_sky.h"
|
||||
#include "d_player.h"
|
||||
#include "g_levellocals.h"
|
||||
#include "hw_fakeflat.h"
|
||||
#include "hw_drawinfo.h"
|
||||
#include "hw_portal.h"
|
||||
#include "hwrenderer/utility/hw_clock.h"
|
||||
#include "hwrenderer/utility/hw_cvars.h"
|
||||
|
||||
EXTERN_CVAR(Float, r_visibility)
|
||||
CVAR(Bool, gl_bandedswlight, false, CVAR_ARCHIVE)
|
||||
|
||||
sector_t * hw_FakeFlat(sector_t * sec, sector_t * dest, area_t in_area, bool back);
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void HWDrawInfo::ClearBuffers()
|
||||
{
|
||||
for(unsigned int i=0;i< otherfloorplanes.Size();i++)
|
||||
{
|
||||
gl_subsectorrendernode * node = otherfloorplanes[i];
|
||||
while (node)
|
||||
{
|
||||
gl_subsectorrendernode * n = node;
|
||||
node = node->next;
|
||||
delete n;
|
||||
}
|
||||
}
|
||||
otherfloorplanes.Clear();
|
||||
|
||||
for(unsigned int i=0;i< otherceilingplanes.Size();i++)
|
||||
{
|
||||
gl_subsectorrendernode * node = otherceilingplanes[i];
|
||||
while (node)
|
||||
{
|
||||
gl_subsectorrendernode * n = node;
|
||||
node = node->next;
|
||||
delete n;
|
||||
}
|
||||
}
|
||||
otherceilingplanes.Clear();
|
||||
|
||||
// clear all the lists that might not have been cleared already
|
||||
MissingUpperTextures.Clear();
|
||||
MissingLowerTextures.Clear();
|
||||
MissingUpperSegs.Clear();
|
||||
MissingLowerSegs.Clear();
|
||||
SubsectorHacks.Clear();
|
||||
CeilingStacks.Clear();
|
||||
FloorStacks.Clear();
|
||||
HandledSubsectors.Clear();
|
||||
spriteindex = 0;
|
||||
|
||||
CurrentMapSections.Resize(level.NumMapSections);
|
||||
CurrentMapSections.Zero();
|
||||
|
||||
sectorrenderflags.Resize(level.sectors.Size());
|
||||
ss_renderflags.Resize(level.subsectors.Size());
|
||||
no_renderflags.Resize(level.subsectors.Size());
|
||||
|
||||
memset(§orrenderflags[0], 0, level.sectors.Size() * sizeof(sectorrenderflags[0]));
|
||||
memset(&ss_renderflags[0], 0, level.subsectors.Size() * sizeof(ss_renderflags[0]));
|
||||
memset(&no_renderflags[0], 0, level.nodes.Size() * sizeof(no_renderflags[0]));
|
||||
|
||||
mClipPortal = nullptr;
|
||||
mCurrentPortal = nullptr;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void HWDrawInfo::UpdateCurrentMapSection()
|
||||
{
|
||||
const int mapsection = R_PointInSubsector(Viewpoint.Pos)->mapsection;
|
||||
CurrentMapSections.Set(mapsection);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Sets the area the camera is in
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void HWDrawInfo::SetViewArea()
|
||||
{
|
||||
auto &vp = Viewpoint;
|
||||
// The render_sector is better suited to represent the current position in GL
|
||||
vp.sector = R_PointInSubsector(vp.Pos)->render_sector;
|
||||
|
||||
// Get the heightsec state from the render sector, not the current one!
|
||||
if (vp.sector->GetHeightSec())
|
||||
{
|
||||
in_area = vp.Pos.Z <= vp.sector->heightsec->floorplane.ZatPoint(vp.Pos) ? area_below :
|
||||
(vp.Pos.Z > vp.sector->heightsec->ceilingplane.ZatPoint(vp.Pos) &&
|
||||
!(vp.sector->heightsec->MoreFlags&SECMF_FAKEFLOORONLY)) ? area_above : area_normal;
|
||||
}
|
||||
else
|
||||
{
|
||||
in_area = level.HasHeightSecs ? area_default : area_normal; // depends on exposed lower sectors, if map contains heightsecs.
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
int HWDrawInfo::SetFullbrightFlags(player_t *player)
|
||||
{
|
||||
FullbrightFlags = 0;
|
||||
|
||||
// check for special colormaps
|
||||
player_t * cplayer = player? player->camera->player : nullptr;
|
||||
if (cplayer)
|
||||
{
|
||||
int cm = CM_DEFAULT;
|
||||
if (cplayer->extralight == INT_MIN)
|
||||
{
|
||||
cm = CM_FIRSTSPECIALCOLORMAP + INVERSECOLORMAP;
|
||||
Viewpoint.extralight = 0;
|
||||
FullbrightFlags = Fullbright;
|
||||
// This does never set stealth vision.
|
||||
}
|
||||
else if (cplayer->fixedcolormap != NOFIXEDCOLORMAP)
|
||||
{
|
||||
cm = CM_FIRSTSPECIALCOLORMAP + cplayer->fixedcolormap;
|
||||
FullbrightFlags = Fullbright;
|
||||
if (gl_enhanced_nv_stealth > 2) FullbrightFlags |= StealthVision;
|
||||
}
|
||||
else if (cplayer->fixedlightlevel != -1)
|
||||
{
|
||||
auto torchtype = PClass::FindActor(NAME_PowerTorch);
|
||||
auto litetype = PClass::FindActor(NAME_PowerLightAmp);
|
||||
for (AInventory * in = cplayer->mo->Inventory; in; in = in->Inventory)
|
||||
{
|
||||
//PalEntry color = in->CallGetBlend();
|
||||
|
||||
// Need special handling for light amplifiers
|
||||
if (in->IsKindOf(torchtype))
|
||||
{
|
||||
FullbrightFlags = Fullbright;
|
||||
if (gl_enhanced_nv_stealth > 1) FullbrightFlags |= StealthVision;
|
||||
}
|
||||
else if (in->IsKindOf(litetype))
|
||||
{
|
||||
FullbrightFlags = Fullbright;
|
||||
if (gl_enhanced_nightvision) FullbrightFlags |= Nightvision;
|
||||
if (gl_enhanced_nv_stealth > 0) FullbrightFlags |= StealthVision;
|
||||
}
|
||||
}
|
||||
}
|
||||
return cm;
|
||||
}
|
||||
else
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Setup the modelview matrix
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void HWDrawInfo::SetViewMatrix(const FRotator &angles, float vx, float vy, float vz, bool mirror, bool planemirror)
|
||||
{
|
||||
float mult = mirror ? -1.f : 1.f;
|
||||
float planemult = planemirror ? -level.info->pixelstretch : level.info->pixelstretch;
|
||||
|
||||
VPUniforms.mViewMatrix.loadIdentity();
|
||||
VPUniforms.mViewMatrix.rotate(angles.Roll.Degrees, 0.0f, 0.0f, 1.0f);
|
||||
VPUniforms.mViewMatrix.rotate(angles.Pitch.Degrees, 1.0f, 0.0f, 0.0f);
|
||||
VPUniforms.mViewMatrix.rotate(angles.Yaw.Degrees, 0.0f, mult, 0.0f);
|
||||
VPUniforms.mViewMatrix.translate(vx * mult, -vz * planemult, -vy);
|
||||
VPUniforms.mViewMatrix.scale(-mult, planemult, 1);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// SetupView
|
||||
// Setup the view rotation matrix for the given viewpoint
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
void HWDrawInfo::SetupView(float vx, float vy, float vz, bool mirror, bool planemirror)
|
||||
{
|
||||
auto &vp = Viewpoint;
|
||||
vp.SetViewAngle(r_viewwindow);
|
||||
SetViewMatrix(vp.HWAngles, vx, vy, vz, mirror, planemirror);
|
||||
SetCameraPos(vp.Pos);
|
||||
ApplyVPUniforms();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
IPortal * HWDrawInfo::FindPortal(const void * src)
|
||||
{
|
||||
int i = Portals.Size() - 1;
|
||||
|
||||
while (i >= 0 && Portals[i] && Portals[i]->GetSource() != src) i--;
|
||||
return i >= 0 ? Portals[i] : nullptr;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void HWViewpointUniforms::SetDefaults()
|
||||
{
|
||||
mProjectionMatrix.loadIdentity();
|
||||
mViewMatrix.loadIdentity();
|
||||
mNormalViewMatrix.loadIdentity();
|
||||
mViewHeight = viewheight;
|
||||
mGlobVis = (float)R_GetGlobVis(r_viewwindow, r_visibility) / 32.f;
|
||||
mPalLightLevels = static_cast<int>(gl_bandedswlight) | (static_cast<int>(gl_fogmode) << 8);
|
||||
mClipLine.X = -10000000.0f;
|
||||
|
||||
}
|
||||
|
|
@ -1,7 +1,11 @@
|
|||
#pragma once
|
||||
|
||||
#include <atomic>
|
||||
#include "vectors.h"
|
||||
#include "r_defs.h"
|
||||
#include "r_utility.h"
|
||||
#include "hw_viewpointuniforms.h"
|
||||
#include "v_video.h"
|
||||
|
||||
|
||||
struct FSectorPortalGroup;
|
||||
|
|
@ -18,6 +22,8 @@ struct HUDSprite;
|
|||
class Clipper;
|
||||
class IPortal;
|
||||
class FFlatVertexGenerator;
|
||||
class IRenderQueue;
|
||||
class HWScenePortalBase;
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
|
|
@ -53,7 +59,10 @@ enum EPortalClip
|
|||
|
||||
struct HWDrawInfo
|
||||
{
|
||||
virtual ~HWDrawInfo() {}
|
||||
virtual ~HWDrawInfo()
|
||||
{
|
||||
ClearBuffers();
|
||||
}
|
||||
|
||||
struct wallseg
|
||||
{
|
||||
|
|
@ -91,14 +100,17 @@ struct HWDrawInfo
|
|||
bool isNightvision() const { return !!(FullbrightFlags & Nightvision); }
|
||||
bool isStealthVision() const { return !!(FullbrightFlags & StealthVision); }
|
||||
|
||||
HWDrawInfo * outer = nullptr;
|
||||
int FullbrightFlags;
|
||||
std::atomic<int> spriteindex;
|
||||
IPortal *mClipPortal;
|
||||
FRotator mAngles;
|
||||
FVector2 mViewVector;
|
||||
AActor *mViewActor;
|
||||
HWScenePortalBase *mClipPortal;
|
||||
IPortal *mCurrentPortal;
|
||||
//FRotator mAngles;
|
||||
IShadowMap *mShadowMap;
|
||||
Clipper *mClipper;
|
||||
FRenderViewpoint Viewpoint;
|
||||
HWViewpointUniforms VPUniforms; // per-viewpoint uniform state
|
||||
TArray<IPortal *> Portals;
|
||||
|
||||
TArray<MissingTextureInfo> MissingUpperTextures;
|
||||
TArray<MissingTextureInfo> MissingLowerTextures;
|
||||
|
|
@ -138,6 +150,7 @@ private:
|
|||
|
||||
sector_t fakesec; // this is a struct member because it gets used in recursively called functions so it cannot be put on the stack.
|
||||
|
||||
|
||||
void UnclipSubsector(subsector_t *sub);
|
||||
void AddLine(seg_t *seg, bool portalclip);
|
||||
void PolySubsector(subsector_t * sub);
|
||||
|
|
@ -148,6 +161,31 @@ private:
|
|||
void RenderThings(subsector_t * sub, sector_t * sector);
|
||||
void DoSubsector(subsector_t * sub);
|
||||
public:
|
||||
|
||||
void SetCameraPos(const DVector3 &pos)
|
||||
{
|
||||
VPUniforms.mCameraPos = { (float)pos.X, (float)pos.Z, (float)pos.Y, 0.f };
|
||||
}
|
||||
|
||||
void SetClipHeight(float h, float d)
|
||||
{
|
||||
VPUniforms.mClipHeight = h;
|
||||
VPUniforms.mClipHeightDirection = d;
|
||||
VPUniforms.mClipLine.X = -1000001.f;
|
||||
}
|
||||
|
||||
void SetClipLine(line_t *line)
|
||||
{
|
||||
VPUniforms.mClipLine = { (float)line->v1->fX(), (float)line->v1->fY(), (float)line->Delta().X, (float)line->Delta().Y };
|
||||
VPUniforms.mClipHeight = 0;
|
||||
}
|
||||
|
||||
bool ClipLineShouldBeActive()
|
||||
{
|
||||
return (screen->hwcaps & RFL_NO_CLIP_PLANES) && VPUniforms.mClipLine.X > -1000000.f;
|
||||
}
|
||||
|
||||
IPortal * FindPortal(const void * src);
|
||||
void RenderBSPNode(void *node);
|
||||
|
||||
void ClearBuffers();
|
||||
|
|
@ -188,6 +226,9 @@ public:
|
|||
void PrepareTargeterSprites();
|
||||
|
||||
void UpdateCurrentMapSection();
|
||||
void SetViewMatrix(const FRotator &angles, float vx, float vy, float vz, bool mirror, bool planemirror);
|
||||
void SetupView(float vx, float vy, float vz, bool mirror, bool planemirror);
|
||||
angle_t FrustumAngle();
|
||||
|
||||
virtual void DrawWall(GLWall *wall, int pass) = 0;
|
||||
virtual void DrawFlat(GLFlat *flat, int pass, bool trans) = 0;
|
||||
|
|
@ -195,7 +236,7 @@ public:
|
|||
|
||||
virtual void FloodUpperGap(seg_t * seg) = 0;
|
||||
virtual void FloodLowerGap(seg_t * seg) = 0;
|
||||
virtual void ProcessLowerMinisegs(TArray<seg_t *> &lowersegs) = 0;
|
||||
void ProcessLowerMinisegs(TArray<seg_t *> &lowersegs);
|
||||
virtual void AddSubsectorToPortal(FSectorPortalGroup *portal, subsector_t *sub) = 0;
|
||||
|
||||
virtual void AddWall(GLWall *w) = 0;
|
||||
|
|
@ -206,6 +247,8 @@ public:
|
|||
virtual void AddHUDSprite(HUDSprite *huds) = 0;
|
||||
|
||||
virtual int UploadLights(FDynLightData &data) = 0;
|
||||
virtual void ApplyVPUniforms() = 0;
|
||||
virtual bool SetDepthClamp(bool on) = 0;
|
||||
|
||||
virtual GLDecal *AddDecal(bool onmirror) = 0;
|
||||
virtual std::pair<FFlatVertex *, unsigned int> AllocVertices(unsigned int count) = 0;
|
||||
|
|
|
|||
|
|
@ -121,7 +121,7 @@ inline void SortNode::AddToEqual(SortNode *child)
|
|||
{
|
||||
child->UnlinkFromChain();
|
||||
child->equal=equal;
|
||||
equal=child;
|
||||
equal=child;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
|
@ -269,7 +269,7 @@ void HWDrawList::SortWallIntoPlane(SortNode * head, SortNode * sort)
|
|||
GLFlat * fh = flats[drawitems[head->itemindex].index];
|
||||
GLWall * ws = walls[drawitems[sort->itemindex].index];
|
||||
|
||||
bool ceiling = fh->z > r_viewpoint.Pos.Z;
|
||||
bool ceiling = fh->z > SortZ;
|
||||
|
||||
if ((ws->ztop[0] > fh->z || ws->ztop[1] > fh->z) && (ws->zbottom[0] < fh->z || ws->zbottom[1] < fh->z))
|
||||
{
|
||||
|
|
@ -327,7 +327,7 @@ void HWDrawList::SortSpriteIntoPlane(SortNode * head, SortNode * sort)
|
|||
GLFlat * fh = flats[drawitems[head->itemindex].index];
|
||||
GLSprite * ss = sprites[drawitems[sort->itemindex].index];
|
||||
|
||||
bool ceiling = fh->z > r_viewpoint.Pos.Z;
|
||||
bool ceiling = fh->z > SortZ;
|
||||
|
||||
auto hiz = ss->z1 > ss->z2 ? ss->z1 : ss->z2;
|
||||
auto loz = ss->z1 < ss->z2 ? ss->z1 : ss->z2;
|
||||
|
|
@ -688,6 +688,7 @@ SortNode * HWDrawList::DoSort(HWDrawInfo *di, SortNode * head)
|
|||
//==========================================================================
|
||||
void HWDrawList::Sort(HWDrawInfo *di)
|
||||
{
|
||||
SortZ = di->Viewpoint.Pos.Z;
|
||||
MakeSortList();
|
||||
sorted = DoSort(di, SortNodes[SortNodeStart]);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -61,6 +61,7 @@ struct HWDrawList
|
|||
TArray<GLSprite*> sprites;
|
||||
TArray<GLDrawItem> drawitems;
|
||||
int SortNodeStart;
|
||||
float SortZ;
|
||||
SortNode * sorted;
|
||||
|
||||
public:
|
||||
|
|
|
|||
|
|
@ -384,7 +384,7 @@ public:
|
|||
|
||||
void SplitSprite(HWDrawInfo *di, sector_t * frontsector, bool translucent);
|
||||
void PerformSpriteClipAdjustment(AActor *thing, const DVector2 &thingpos, float spriteheight);
|
||||
bool CalculateVertices(HWDrawInfo *di, FVector3 *v);
|
||||
bool CalculateVertices(HWDrawInfo *di, FVector3 *v, DVector3 *vp);
|
||||
|
||||
public:
|
||||
|
||||
|
|
|
|||
|
|
@ -386,79 +386,3 @@ sector_t * hw_FakeFlat(sector_t * sec, sector_t * dest, area_t in_area, bool bac
|
|||
}
|
||||
return dest;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Sets the area the camera is in
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
void HWDrawInfo::SetViewArea()
|
||||
{
|
||||
// The render_sector is better suited to represent the current position in GL
|
||||
r_viewpoint.sector = R_PointInSubsector(r_viewpoint.Pos)->render_sector;
|
||||
|
||||
// Get the heightsec state from the render sector, not the current one!
|
||||
if (r_viewpoint.sector->GetHeightSec())
|
||||
{
|
||||
in_area = r_viewpoint.Pos.Z <= r_viewpoint.sector->heightsec->floorplane.ZatPoint(r_viewpoint.Pos) ? area_below :
|
||||
(r_viewpoint.Pos.Z > r_viewpoint.sector->heightsec->ceilingplane.ZatPoint(r_viewpoint.Pos) &&
|
||||
!(r_viewpoint.sector->heightsec->MoreFlags&SECMF_FAKEFLOORONLY)) ? area_above : area_normal;
|
||||
}
|
||||
else
|
||||
{
|
||||
in_area = level.HasHeightSecs ? area_default : area_normal; // depends on exposed lower sectors, if map contains heightsecs.
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int HWDrawInfo::SetFullbrightFlags(player_t *player)
|
||||
{
|
||||
FullbrightFlags = 0;
|
||||
|
||||
// check for special colormaps
|
||||
player_t * cplayer = player? player->camera->player : nullptr;
|
||||
if (cplayer)
|
||||
{
|
||||
int cm = CM_DEFAULT;
|
||||
if (cplayer->extralight == INT_MIN)
|
||||
{
|
||||
cm = CM_FIRSTSPECIALCOLORMAP + INVERSECOLORMAP;
|
||||
r_viewpoint.extralight = 0;
|
||||
FullbrightFlags = Fullbright;
|
||||
// This does never set stealth vision.
|
||||
}
|
||||
else if (cplayer->fixedcolormap != NOFIXEDCOLORMAP)
|
||||
{
|
||||
cm = CM_FIRSTSPECIALCOLORMAP + cplayer->fixedcolormap;
|
||||
FullbrightFlags = Fullbright;
|
||||
if (gl_enhanced_nv_stealth > 2) FullbrightFlags |= StealthVision;
|
||||
}
|
||||
else if (cplayer->fixedlightlevel != -1)
|
||||
{
|
||||
auto torchtype = PClass::FindActor(NAME_PowerTorch);
|
||||
auto litetype = PClass::FindActor(NAME_PowerLightAmp);
|
||||
for (AInventory * in = cplayer->mo->Inventory; in; in = in->Inventory)
|
||||
{
|
||||
//PalEntry color = in->CallGetBlend();
|
||||
|
||||
// Need special handling for light amplifiers
|
||||
if (in->IsKindOf(torchtype))
|
||||
{
|
||||
FullbrightFlags = Fullbright;
|
||||
if (gl_enhanced_nv_stealth > 1) FullbrightFlags |= StealthVision;
|
||||
}
|
||||
else if (in->IsKindOf(litetype))
|
||||
{
|
||||
FullbrightFlags = Fullbright;
|
||||
if (gl_enhanced_nightvision) FullbrightFlags |= Nightvision;
|
||||
if (gl_enhanced_nv_stealth > 0) FullbrightFlags |= StealthVision;
|
||||
}
|
||||
}
|
||||
}
|
||||
return cm;
|
||||
}
|
||||
else
|
||||
{
|
||||
return CM_DEFAULT;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ enum area_t : int
|
|||
};
|
||||
|
||||
|
||||
// Global functions. Make them members of GLRenderer later?
|
||||
// Global functions.
|
||||
bool hw_CheckClip(side_t * sidedef, sector_t * frontsector, sector_t * backsector);
|
||||
sector_t * hw_FakeFlat(sector_t * sec, sector_t * dest, area_t in_area, bool back);
|
||||
area_t hw_CheckViewArea(vertex_t *v1, vertex_t *v2, sector_t *frontsector, sector_t *backsector);
|
||||
|
|
|
|||
|
|
@ -306,6 +306,7 @@ void GLFlat::ProcessSector(HWDrawInfo *di, sector_t * frontsector)
|
|||
dynlightindex = -1;
|
||||
|
||||
uint8_t &srf = di->sectorrenderflags[sector->sectornum];
|
||||
const auto &vp = di->Viewpoint;
|
||||
|
||||
//
|
||||
//
|
||||
|
|
@ -314,7 +315,7 @@ void GLFlat::ProcessSector(HWDrawInfo *di, sector_t * frontsector)
|
|||
//
|
||||
//
|
||||
//
|
||||
if (frontsector->floorplane.ZatPoint(r_viewpoint.Pos) <= r_viewpoint.Pos.Z)
|
||||
if (frontsector->floorplane.ZatPoint(vp.Pos) <= vp.Pos.Z)
|
||||
{
|
||||
// process the original floor first.
|
||||
|
||||
|
|
@ -374,7 +375,7 @@ void GLFlat::ProcessSector(HWDrawInfo *di, sector_t * frontsector)
|
|||
//
|
||||
//
|
||||
//
|
||||
if (frontsector->ceilingplane.ZatPoint(r_viewpoint.Pos) >= r_viewpoint.Pos.Z)
|
||||
if (frontsector->ceilingplane.ZatPoint(vp.Pos) >= vp.Pos.Z)
|
||||
{
|
||||
// process the original ceiling first.
|
||||
|
||||
|
|
@ -465,7 +466,7 @@ void GLFlat::ProcessSector(HWDrawInfo *di, sector_t * frontsector)
|
|||
double ff_top = rover->top.plane->ZatPoint(sector->centerspot);
|
||||
if (ff_top < lastceilingheight)
|
||||
{
|
||||
if (r_viewpoint.Pos.Z <= rover->top.plane->ZatPoint(r_viewpoint.Pos))
|
||||
if (vp.Pos.Z <= rover->top.plane->ZatPoint(vp.Pos))
|
||||
{
|
||||
SetFrom3DFloor(rover, true, !!(rover->flags&FF_FOG));
|
||||
Colormap.FadeColor = frontsector->Colormap.FadeColor;
|
||||
|
|
@ -479,7 +480,7 @@ void GLFlat::ProcessSector(HWDrawInfo *di, sector_t * frontsector)
|
|||
double ff_bottom = rover->bottom.plane->ZatPoint(sector->centerspot);
|
||||
if (ff_bottom < lastceilingheight)
|
||||
{
|
||||
if (r_viewpoint.Pos.Z <= rover->bottom.plane->ZatPoint(r_viewpoint.Pos))
|
||||
if (vp.Pos.Z <= rover->bottom.plane->ZatPoint(vp.Pos))
|
||||
{
|
||||
SetFrom3DFloor(rover, false, !(rover->flags&FF_FOG));
|
||||
Colormap.FadeColor = frontsector->Colormap.FadeColor;
|
||||
|
|
@ -505,7 +506,7 @@ void GLFlat::ProcessSector(HWDrawInfo *di, sector_t * frontsector)
|
|||
double ff_bottom = rover->bottom.plane->ZatPoint(sector->centerspot);
|
||||
if (ff_bottom > lastfloorheight || (rover->flags&FF_FIX))
|
||||
{
|
||||
if (r_viewpoint.Pos.Z >= rover->bottom.plane->ZatPoint(r_viewpoint.Pos))
|
||||
if (vp.Pos.Z >= rover->bottom.plane->ZatPoint(vp.Pos))
|
||||
{
|
||||
SetFrom3DFloor(rover, false, !(rover->flags&FF_FOG));
|
||||
Colormap.FadeColor = frontsector->Colormap.FadeColor;
|
||||
|
|
@ -526,7 +527,7 @@ void GLFlat::ProcessSector(HWDrawInfo *di, sector_t * frontsector)
|
|||
double ff_top = rover->top.plane->ZatPoint(sector->centerspot);
|
||||
if (ff_top > lastfloorheight)
|
||||
{
|
||||
if (r_viewpoint.Pos.Z >= rover->top.plane->ZatPoint(r_viewpoint.Pos))
|
||||
if (vp.Pos.Z >= rover->top.plane->ZatPoint(vp.Pos))
|
||||
{
|
||||
SetFrom3DFloor(rover, true, !!(rover->flags&FF_FOG));
|
||||
Colormap.FadeColor = frontsector->Colormap.FadeColor;
|
||||
|
|
|
|||
628
src/hwrenderer/scene/hw_portal.cpp
Normal file
628
src/hwrenderer/scene/hw_portal.cpp
Normal file
|
|
@ -0,0 +1,628 @@
|
|||
//
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// Copyright(C) 2004-2018 Christoph Oelckers
|
||||
// All rights reserved.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with this program. If not, see http://www.gnu.org/licenses/
|
||||
//
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
/*
|
||||
** hw_portal.cpp
|
||||
** portal maintenance classes for skyboxes, horizons etc. (API independent parts)
|
||||
**
|
||||
*/
|
||||
|
||||
#include "c_dispatch.h"
|
||||
#include "portal.h"
|
||||
#include "p_maputl.h"
|
||||
#include "hw_portal.h"
|
||||
#include "hw_clipper.h"
|
||||
#include "actor.h"
|
||||
#include "g_levellocals.h"
|
||||
|
||||
EXTERN_CVAR(Int, r_mirror_recursions)
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// StartFrame
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void FPortalSceneState::StartFrame()
|
||||
{
|
||||
if (renderdepth == 0)
|
||||
{
|
||||
inskybox = false;
|
||||
screen->instack[sector_t::floor] = screen->instack[sector_t::ceiling] = 0;
|
||||
}
|
||||
renderdepth++;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// printing portal info
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
static bool gl_portalinfo;
|
||||
|
||||
CCMD(gl_portalinfo)
|
||||
{
|
||||
gl_portalinfo = true;
|
||||
}
|
||||
|
||||
static FString indent;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// EndFrame
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void FPortalSceneState::EndFrame(HWDrawInfo *di)
|
||||
{
|
||||
IPortal * p;
|
||||
|
||||
if (gl_portalinfo)
|
||||
{
|
||||
Printf("%s%d portals, depth = %d\n%s{\n", indent.GetChars(), di->Portals.Size(), renderdepth, indent.GetChars());
|
||||
indent += " ";
|
||||
}
|
||||
|
||||
// Only use occlusion query if there are more than 2 portals.
|
||||
// Otherwise there's too much overhead.
|
||||
// (And don't forget to consider the separating null pointers!)
|
||||
bool usequery = di->Portals.Size() > 2 + (unsigned)renderdepth;
|
||||
|
||||
while (di->Portals.Pop(p) && p)
|
||||
{
|
||||
if (gl_portalinfo)
|
||||
{
|
||||
Printf("%sProcessing %s, depth = %d, query = %d\n", indent.GetChars(), p->GetName(), renderdepth, usequery);
|
||||
}
|
||||
if (p->lines.Size() > 0)
|
||||
{
|
||||
p->RenderPortal(true, usequery, di);
|
||||
}
|
||||
delete p;
|
||||
}
|
||||
renderdepth--;
|
||||
|
||||
if (gl_portalinfo)
|
||||
{
|
||||
indent.Truncate(long(indent.Len()-2));
|
||||
Printf("%s}\n", indent.GetChars());
|
||||
if (indent.Len() == 0) gl_portalinfo = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Renders one sky portal without a stencil.
|
||||
// In more complex scenes using a stencil for skies can severely stall
|
||||
// the GPU and there's rarely more than one sky visible at a time.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
bool FPortalSceneState::RenderFirstSkyPortal(int recursion, HWDrawInfo *outer_di)
|
||||
{
|
||||
IPortal * p;
|
||||
IPortal * best = nullptr;
|
||||
unsigned bestindex = 0;
|
||||
|
||||
// Find the one with the highest amount of lines.
|
||||
// Normally this is also the one that saves the largest amount
|
||||
// of time by drawing it before the scene itself.
|
||||
auto &portals = outer_di->Portals;
|
||||
for (int i = portals.Size() - 1; i >= 0; --i)
|
||||
{
|
||||
p = portals[i];
|
||||
if (p->lines.Size() > 0 && p->IsSky())
|
||||
{
|
||||
// Cannot clear the depth buffer inside a portal recursion
|
||||
if (recursion && p->NeedDepthBuffer()) continue;
|
||||
|
||||
if (!best || p->lines.Size() > best->lines.Size())
|
||||
{
|
||||
best = p;
|
||||
bestindex = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (best)
|
||||
{
|
||||
portals.Delete(bestindex);
|
||||
best->RenderPortal(false, false, outer_di);
|
||||
delete best;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void HWScenePortalBase::ClearClipper(HWDrawInfo *di, Clipper *clipper)
|
||||
{
|
||||
auto outer_di = di->outer;
|
||||
DAngle angleOffset = deltaangle(outer_di->Viewpoint.Angles.Yaw, di->Viewpoint.Angles.Yaw);
|
||||
|
||||
clipper->Clear();
|
||||
|
||||
auto &lines = mOwner->lines;
|
||||
// Set the clipper to the minimal visible area
|
||||
clipper->SafeAddClipRange(0, 0xffffffff);
|
||||
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;
|
||||
|
||||
if (deltaangle(endAngle, startAngle) < 0)
|
||||
{
|
||||
clipper->SafeRemoveClipRangeRealAngles(startAngle.BAMs(), endAngle.BAMs());
|
||||
}
|
||||
}
|
||||
|
||||
// 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);
|
||||
|
||||
// lock the parts that have just been clipped out.
|
||||
clipper->SetSilhouette();
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
// Common code for line to line and mirror portals
|
||||
//
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
int HWLinePortal::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(), viewpos) ? PClip_InFront : PClip_Inside;
|
||||
}
|
||||
|
||||
int HWLinePortal::ClipSubsector(subsector_t *sub)
|
||||
{
|
||||
// this seg is completely behind the mirror
|
||||
for (unsigned int i = 0; i<sub->numlines; i++)
|
||||
{
|
||||
if (P_PointOnLineSidePrecise(sub->firstline[i].v1->fPos(), line()) == 0) return PClip_Inside;
|
||||
}
|
||||
return PClip_InFront;
|
||||
}
|
||||
|
||||
int HWLinePortal::ClipPoint(const DVector2 &pos)
|
||||
{
|
||||
if (P_PointOnLineSidePrecise(pos, line()))
|
||||
{
|
||||
return PClip_InFront;
|
||||
}
|
||||
return PClip_Inside;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
// Mirror Portal
|
||||
//
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
bool HWMirrorPortal::Setup(HWDrawInfo *di, Clipper *clipper)
|
||||
{
|
||||
auto state = mOwner->mState;
|
||||
if (state->renderdepth > r_mirror_recursions)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
auto &vp = di->Viewpoint;
|
||||
di->UpdateCurrentMapSection();
|
||||
|
||||
di->mClipPortal = this;
|
||||
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.
|
||||
vp.showviewer = true;
|
||||
// Reflect the current view behind the mirror.
|
||||
if (linedef->Delta().X == 0)
|
||||
{
|
||||
// vertical mirror
|
||||
vp.Pos.X = 2 * v1->fX() - StartPos.X;
|
||||
|
||||
// Compensation for reendering inaccuracies
|
||||
if (StartPos.X < v1->fX()) vp.Pos.X -= 0.1;
|
||||
else vp.Pos.X += 0.1;
|
||||
}
|
||||
else if (linedef->Delta().Y == 0)
|
||||
{
|
||||
// horizontal mirror
|
||||
vp.Pos.Y = 2 * v1->fY() - StartPos.Y;
|
||||
|
||||
// Compensation for reendering inaccuracies
|
||||
if (StartPos.Y < v1->fY()) vp.Pos.Y -= 0.1;
|
||||
else vp.Pos.Y += 0.1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// any mirror--use floats to avoid integer overflow.
|
||||
// Use doubles to avoid losing precision which is very important here.
|
||||
|
||||
double dx = v2->fX() - v1->fX();
|
||||
double dy = v2->fY() - v1->fY();
|
||||
double x1 = v1->fX();
|
||||
double y1 = v1->fY();
|
||||
double x = StartPos.X;
|
||||
double y = StartPos.Y;
|
||||
|
||||
// the above two cases catch len == 0
|
||||
double r = ((x - x1)*dx + (y - y1)*dy) / (dx*dx + dy * dy);
|
||||
|
||||
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();
|
||||
|
||||
vp.Pos.X += v[1] * state->renderdepth / 2;
|
||||
vp.Pos.Y += v[0] * state->renderdepth / 2;
|
||||
}
|
||||
vp.Angles.Yaw = linedef->Delta().Angle() * 2. - StartAngle;
|
||||
|
||||
vp.ViewActor = nullptr;
|
||||
|
||||
state->MirrorFlag++;
|
||||
di->SetClipLine(linedef);
|
||||
di->SetupView(vp.Pos.X, vp.Pos.Y, vp.Pos.Z, !!(state->MirrorFlag & 1), !!(state->PlaneMirrorFlag & 1));
|
||||
|
||||
clipper->Clear();
|
||||
|
||||
angle_t af = di->FrustumAngle();
|
||||
if (af < ANGLE_180) clipper->SafeAddClipRangeRealAngles(vp.Angles.Yaw.BAMs() + af, vp.Angles.Yaw.BAMs() - af);
|
||||
|
||||
clipper->SafeAddClipRange(linedef->v1, linedef->v2);
|
||||
return true;
|
||||
}
|
||||
|
||||
void HWMirrorPortal::Shutdown(HWDrawInfo *di)
|
||||
{
|
||||
mOwner->mState->MirrorFlag--;
|
||||
}
|
||||
|
||||
const char *HWMirrorPortal::GetName() { return "Mirror"; }
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
// Line to line Portal
|
||||
//
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
bool HWLineToLinePortal::Setup(HWDrawInfo *di, Clipper *clipper)
|
||||
{
|
||||
// TODO: Handle recursion more intelligently
|
||||
auto &state = mOwner->mState;
|
||||
if (state->renderdepth>r_mirror_recursions)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
auto &vp = di->Viewpoint;
|
||||
di->mClipPortal = this;
|
||||
|
||||
line_t *origin = glport->lines[0]->mOrigin;
|
||||
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 = (vp.Path[0] - vp.Path[1]).Length();
|
||||
if (distp > EQUAL_EPSILON)
|
||||
{
|
||||
double dist1 = (vp.Pos - vp.Path[0]).Length();
|
||||
double dist2 = (vp.Pos - vp.Path[1]).Length();
|
||||
|
||||
if (dist1 + dist2 < distp + 1)
|
||||
{
|
||||
vp.camera->renderflags |= RF_MAYBEINVISIBLE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto &lines = mOwner->lines;
|
||||
|
||||
for (unsigned i = 0; i < lines.Size(); i++)
|
||||
{
|
||||
line_t *line = lines[i].seg->linedef->getPortalDestination();
|
||||
subsector_t *sub;
|
||||
if (line->sidedef[0]->Flags & WALLF_POLYOBJ)
|
||||
sub = R_PointInSubsector(line->v1->fixX(), line->v1->fixY());
|
||||
else sub = line->frontsector->subsectors[0];
|
||||
di->CurrentMapSections.Set(sub->mapsection);
|
||||
}
|
||||
|
||||
vp.ViewActor = nullptr;
|
||||
di->SetClipLine(glport->lines[0]->mDestination);
|
||||
di->SetupView(vp.Pos.X, vp.Pos.Y, vp.Pos.Z, !!(state->MirrorFlag & 1), !!(state->PlaneMirrorFlag & 1));
|
||||
|
||||
ClearClipper(di, clipper);
|
||||
return true;
|
||||
}
|
||||
|
||||
void HWLineToLinePortal::RenderAttached(HWDrawInfo *di)
|
||||
{
|
||||
di->ProcessActorsInPortal(glport, di->in_area);
|
||||
}
|
||||
|
||||
const char *HWLineToLinePortal::GetName() { return "LineToLine"; }
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
// Skybox Portal
|
||||
//
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// GLSkyboxPortal::DrawContents
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
bool HWSkyboxPortal::Setup(HWDrawInfo *di, Clipper *clipper)
|
||||
{
|
||||
auto state = mOwner->mState;
|
||||
old_pm = state->PlaneMirrorMode;
|
||||
|
||||
if (mOwner->mState->skyboxrecursion >= 3)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
auto &vp = di->Viewpoint;
|
||||
|
||||
state->skyboxrecursion++;
|
||||
state->PlaneMirrorMode = 0;
|
||||
state->inskybox = true;
|
||||
|
||||
AActor *origin = portal->mSkybox;
|
||||
portal->mFlags |= PORTSF_INSKYBOX;
|
||||
vp.extralight = 0;
|
||||
|
||||
|
||||
oldclamp = di->SetDepthClamp(false);
|
||||
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 (vp.Pos.Z < floorh + 4) vp.Pos.Z = floorh + 4;
|
||||
if (vp.Pos.Z > ceilh - 4) vp.Pos.Z = ceilh - 4;
|
||||
|
||||
vp.ViewActor = origin;
|
||||
|
||||
di->SetupView(vp.Pos.X, vp.Pos.Y, vp.Pos.Z, !!(state->MirrorFlag & 1), !!(state->PlaneMirrorFlag & 1));
|
||||
di->SetViewArea();
|
||||
ClearClipper(di, clipper);
|
||||
di->UpdateCurrentMapSection();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void HWSkyboxPortal::Shutdown(HWDrawInfo *di)
|
||||
{
|
||||
auto state = mOwner->mState;
|
||||
portal->mFlags &= ~PORTSF_INSKYBOX;
|
||||
di->SetDepthClamp(oldclamp);
|
||||
state->inskybox = false;
|
||||
state->skyboxrecursion--;
|
||||
state->PlaneMirrorMode = old_pm;
|
||||
}
|
||||
|
||||
const char *HWSkyboxPortal::GetName() { return "Skybox"; }
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
// Sector stack Portal
|
||||
//
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// GLSectorStackPortal::SetupCoverage
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
static uint8_t SetCoverage(HWDrawInfo *di, void *node)
|
||||
{
|
||||
if (level.nodes.Size() == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
if (!((size_t)node & 1)) // Keep going until found a subsector
|
||||
{
|
||||
node_t *bsp = (node_t *)node;
|
||||
uint8_t coverage = SetCoverage(di, bsp->children[0]) | SetCoverage(di, bsp->children[1]);
|
||||
di->no_renderflags[bsp->Index()] = coverage;
|
||||
return coverage;
|
||||
}
|
||||
else
|
||||
{
|
||||
subsector_t *sub = (subsector_t *)((uint8_t *)node - 1);
|
||||
return di->ss_renderflags[sub->Index()] & SSRF_SEEN;
|
||||
}
|
||||
}
|
||||
|
||||
void HWSectorStackPortal::SetupCoverage(HWDrawInfo *di)
|
||||
{
|
||||
for (unsigned i = 0; i<subsectors.Size(); i++)
|
||||
{
|
||||
subsector_t *sub = subsectors[i];
|
||||
int plane = origin->plane;
|
||||
for (int j = 0; j<sub->portalcoverage[plane].sscount; j++)
|
||||
{
|
||||
subsector_t *dsub = &::level.subsectors[sub->portalcoverage[plane].subsectors[j]];
|
||||
di->CurrentMapSections.Set(dsub->mapsection);
|
||||
di->ss_renderflags[dsub->Index()] |= SSRF_SEEN;
|
||||
}
|
||||
}
|
||||
SetCoverage(di, ::level.HeadNode());
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// GLSectorStackPortal::DrawContents
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
bool HWSectorStackPortal::Setup(HWDrawInfo *di, Clipper *clipper)
|
||||
{
|
||||
auto state = mOwner->mState;
|
||||
FSectorPortalGroup *portal = origin;
|
||||
auto &vp = di->Viewpoint;
|
||||
|
||||
vp.Pos += origin->mDisplacement;
|
||||
vp.ActorPos += origin->mDisplacement;
|
||||
vp.ViewActor = nullptr;
|
||||
|
||||
// avoid recursions!
|
||||
if (origin->plane != -1) screen->instack[origin->plane]++;
|
||||
|
||||
di->SetupView(vp.Pos.X, vp.Pos.Y, vp.Pos.Z, !!(state->MirrorFlag & 1), !!(state->PlaneMirrorFlag & 1));
|
||||
SetupCoverage(di);
|
||||
ClearClipper(di, clipper);
|
||||
|
||||
// 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(vp.Pos);
|
||||
if (!(di->ss_renderflags[sub->Index()] & SSRF_SEEN))
|
||||
{
|
||||
clipper->SafeAddClipRange(0, ANGLE_MAX);
|
||||
clipper->SetBlocked(true);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void HWSectorStackPortal::Shutdown(HWDrawInfo *di)
|
||||
{
|
||||
if (origin->plane != -1) screen->instack[origin->plane]--;
|
||||
}
|
||||
|
||||
const char *HWSectorStackPortal::GetName() { return "Sectorstack"; }
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
// Plane Mirror Portal
|
||||
//
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// GLPlaneMirrorPortal::DrawContents
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
bool HWPlaneMirrorPortal::Setup(HWDrawInfo *di, Clipper *clipper)
|
||||
{
|
||||
auto state = mOwner->mState;
|
||||
if (state->renderdepth > r_mirror_recursions)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
// 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;
|
||||
old_pm = state->PlaneMirrorMode;
|
||||
|
||||
// the player is always visible in a mirror.
|
||||
vp.showviewer = true;
|
||||
|
||||
double planez = origin->ZatPoint(vp.Pos);
|
||||
vp.Pos.Z = 2 * planez - vp.Pos.Z;
|
||||
vp.ViewActor = nullptr;
|
||||
state->PlaneMirrorMode = origin->fC() < 0 ? -1 : 1;
|
||||
|
||||
state->PlaneMirrorFlag++;
|
||||
di->SetClipHeight(planez, state->PlaneMirrorMode < 0 ? -1.f : 1.f);
|
||||
di->SetupView(vp.Pos.X, vp.Pos.Y, vp.Pos.Z, !!(state->MirrorFlag & 1), !!(state->PlaneMirrorFlag & 1));
|
||||
ClearClipper(di, clipper);
|
||||
|
||||
di->UpdateCurrentMapSection();
|
||||
return true;
|
||||
}
|
||||
|
||||
void HWPlaneMirrorPortal::Shutdown(HWDrawInfo *di)
|
||||
{
|
||||
auto state = mOwner->mState;
|
||||
state->PlaneMirrorFlag--;
|
||||
state->PlaneMirrorMode = old_pm;
|
||||
std::swap(screen->instack[sector_t::floor], screen->instack[sector_t::ceiling]);
|
||||
}
|
||||
|
||||
const char *HWPlaneMirrorPortal::GetName() { return origin->fC() < 0? "Planemirror ceiling" : "Planemirror floor"; }
|
||||
|
|
@ -1,6 +1,8 @@
|
|||
#pragma once
|
||||
|
||||
#include "portal.h"
|
||||
#include "hw_drawinfo.h"
|
||||
#include "hw_drawstructs.h"
|
||||
#include "hwrenderer/textures/hw_material.h"
|
||||
|
||||
struct GLSkyInfo
|
||||
|
|
@ -33,12 +35,278 @@ struct GLHorizonInfo
|
|||
PalEntry specialcolor;
|
||||
};
|
||||
|
||||
struct FPortalSceneState;
|
||||
|
||||
class IPortal
|
||||
{
|
||||
friend struct FPortalSceneState;
|
||||
public:
|
||||
FPortalSceneState * mState;
|
||||
TArray<GLWall> lines;
|
||||
|
||||
IPortal(FPortalSceneState *s, bool local);
|
||||
virtual ~IPortal() {}
|
||||
virtual int ClipSeg(seg_t *seg) { return PClip_Inside; }
|
||||
virtual void * GetSource() const = 0; // GetSource MUST be implemented!
|
||||
virtual const char *GetName() = 0;
|
||||
virtual bool IsSky() { return false; }
|
||||
virtual bool NeedCap() { return true; }
|
||||
virtual bool NeedDepthBuffer() { return true; }
|
||||
virtual void DrawContents(HWDrawInfo *di) = 0;
|
||||
virtual void RenderAttached(HWDrawInfo *di) {}
|
||||
virtual bool Start(bool usestencil, bool doquery, HWDrawInfo *outer_di, HWDrawInfo **pDi) = 0;
|
||||
virtual void End(HWDrawInfo *di, bool usestencil) = 0;
|
||||
|
||||
void AddLine(GLWall * l)
|
||||
{
|
||||
lines.Push(*l);
|
||||
}
|
||||
|
||||
void RenderPortal(bool usestencil, bool doquery, HWDrawInfo *outer_di)
|
||||
{
|
||||
// Start may perform an occlusion query. If that returns 0 there
|
||||
// is no need to draw the stencil's contents and there's also no
|
||||
// need to restore the affected area becasue there is none!
|
||||
HWDrawInfo *di;
|
||||
if (Start(usestencil, doquery, outer_di, &di))
|
||||
{
|
||||
DrawContents(di);
|
||||
End(di, usestencil);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
struct FPortalSceneState
|
||||
{
|
||||
int recursion = 0;
|
||||
|
||||
int MirrorFlag = 0;
|
||||
int PlaneMirrorFlag = 0;
|
||||
int renderdepth = 0;
|
||||
|
||||
int PlaneMirrorMode = 0;
|
||||
bool inskybox = 0;
|
||||
|
||||
UniqueList<GLSkyInfo> UniqueSkies;
|
||||
UniqueList<GLHorizonInfo> UniqueHorizons;
|
||||
UniqueList<secplane_t> UniquePlaneMirrors;
|
||||
|
||||
int skyboxrecursion = 0;
|
||||
|
||||
void BeginScene()
|
||||
{
|
||||
UniqueSkies.Clear();
|
||||
UniqueHorizons.Clear();
|
||||
UniquePlaneMirrors.Clear();
|
||||
}
|
||||
|
||||
int GetRecursion() const
|
||||
{
|
||||
return recursion;
|
||||
}
|
||||
|
||||
bool isMirrored() const
|
||||
{
|
||||
return !!((MirrorFlag ^ PlaneMirrorFlag) & 1);
|
||||
}
|
||||
|
||||
void StartFrame();
|
||||
bool RenderFirstSkyPortal(int recursion, HWDrawInfo *outer_di);
|
||||
void EndFrame(HWDrawInfo *outer_di);
|
||||
|
||||
|
||||
};
|
||||
|
||||
inline IPortal::IPortal(FPortalSceneState *s, bool local) : mState(s)
|
||||
{
|
||||
//if (!local) s->portals.Push(this);
|
||||
}
|
||||
|
||||
|
||||
class HWScenePortalBase
|
||||
{
|
||||
protected:
|
||||
IPortal *mOwner;
|
||||
public:
|
||||
HWScenePortalBase() {}
|
||||
virtual ~HWScenePortalBase() {}
|
||||
void SetOwner(IPortal *p) { mOwner = p; }
|
||||
void ClearClipper(HWDrawInfo *di, Clipper *clipper);
|
||||
|
||||
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; }
|
||||
|
||||
virtual bool IsSky() { return false; }
|
||||
virtual bool NeedCap() { return false; }
|
||||
virtual bool NeedDepthBuffer() { return true; }
|
||||
virtual void * GetSource() const = 0; // GetSource MUST be implemented!
|
||||
virtual const char *GetName() = 0;
|
||||
|
||||
virtual bool Setup(HWDrawInfo *di, Clipper *clipper) = 0;
|
||||
virtual void Shutdown(HWDrawInfo *di) {}
|
||||
virtual void RenderAttached(HWDrawInfo *di) {}
|
||||
|
||||
};
|
||||
|
||||
struct HWLinePortal : public HWScenePortalBase
|
||||
{
|
||||
// this must be the same as at the start of line_t, so that we can pass in this structure directly to P_ClipLineToPortal.
|
||||
vertex_t *v1, *v2; // vertices, from v1 to v2
|
||||
DVector2 delta; // precalculated v2 - v1 for side checking
|
||||
|
||||
angle_t angv1, angv2; // for quick comparisons with a line or subsector
|
||||
|
||||
HWLinePortal(line_t *line)
|
||||
{
|
||||
v1 = line->v1;
|
||||
v2 = line->v2;
|
||||
CalcDelta();
|
||||
}
|
||||
|
||||
HWLinePortal(FLinePortalSpan *line)
|
||||
{
|
||||
if (line->lines[0]->mType != PORTT_LINKED || line->v1 == nullptr)
|
||||
{
|
||||
// For non-linked portals we must check the actual linedef.
|
||||
line_t *lline = line->lines[0]->mDestination;
|
||||
v1 = lline->v1;
|
||||
v2 = lline->v2;
|
||||
}
|
||||
else
|
||||
{
|
||||
// For linked portals we can check the merged span.
|
||||
v1 = line->v1;
|
||||
v2 = line->v2;
|
||||
}
|
||||
CalcDelta();
|
||||
}
|
||||
|
||||
void CalcDelta()
|
||||
{
|
||||
delta = v2->fPos() - v1->fPos();
|
||||
}
|
||||
|
||||
line_t *line()
|
||||
{
|
||||
vertex_t **pv = &v1;
|
||||
return reinterpret_cast<line_t*>(pv);
|
||||
}
|
||||
|
||||
int ClipSeg(seg_t *seg, const DVector3 &viewpos) override;
|
||||
int ClipSubsector(subsector_t *sub) override;
|
||||
int ClipPoint(const DVector2 &pos);
|
||||
bool NeedCap() override { return false; }
|
||||
};
|
||||
|
||||
struct HWMirrorPortal : public HWLinePortal
|
||||
{
|
||||
// mirror portals always consist of single linedefs!
|
||||
line_t * linedef;
|
||||
|
||||
protected:
|
||||
bool Setup(HWDrawInfo *di, Clipper *clipper) override;
|
||||
void Shutdown(HWDrawInfo *di) override;
|
||||
void * GetSource() const override { return linedef; }
|
||||
const char *GetName() override;
|
||||
|
||||
public:
|
||||
|
||||
HWMirrorPortal(line_t * line)
|
||||
: HWLinePortal(line)
|
||||
{
|
||||
linedef = line;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct HWLineToLinePortal : public HWLinePortal
|
||||
{
|
||||
FLinePortalSpan *glport;
|
||||
protected:
|
||||
bool Setup(HWDrawInfo *di, Clipper *clipper) override;
|
||||
virtual void * GetSource() const override { return glport; }
|
||||
virtual const char *GetName() override;
|
||||
virtual line_t *ClipLine() override { return line(); }
|
||||
virtual void RenderAttached(HWDrawInfo *di) override;
|
||||
|
||||
public:
|
||||
|
||||
HWLineToLinePortal(FLinePortalSpan *ll)
|
||||
: HWLinePortal(ll)
|
||||
{
|
||||
glport = ll;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct HWSkyboxPortal : public HWScenePortalBase
|
||||
{
|
||||
bool oldclamp;
|
||||
int old_pm;
|
||||
FSectorPortal * portal;
|
||||
|
||||
protected:
|
||||
bool Setup(HWDrawInfo *di, Clipper *clipper) override;
|
||||
void Shutdown(HWDrawInfo *di) override;
|
||||
virtual void * GetSource() const { return portal; }
|
||||
virtual bool IsSky() { return true; }
|
||||
virtual const char *GetName();
|
||||
|
||||
public:
|
||||
|
||||
|
||||
HWSkyboxPortal(FSectorPortal * pt)
|
||||
{
|
||||
portal = pt;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
struct HWSectorStackPortal : public HWScenePortalBase
|
||||
{
|
||||
TArray<subsector_t *> subsectors;
|
||||
protected:
|
||||
bool Setup(HWDrawInfo *di, Clipper *clipper) override;
|
||||
void Shutdown(HWDrawInfo *di) 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.
|
||||
virtual const char *GetName();
|
||||
FSectorPortalGroup *origin;
|
||||
|
||||
public:
|
||||
|
||||
HWSectorStackPortal(FSectorPortalGroup *pt)
|
||||
{
|
||||
origin = pt;
|
||||
}
|
||||
void SetupCoverage(HWDrawInfo *di);
|
||||
void AddSubsector(subsector_t *sub)
|
||||
{
|
||||
subsectors.Push(sub);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
struct HWPlaneMirrorPortal : public HWScenePortalBase
|
||||
{
|
||||
int old_pm;
|
||||
protected:
|
||||
bool Setup(HWDrawInfo *di, Clipper *clipper) override;
|
||||
void Shutdown(HWDrawInfo *di) override;
|
||||
virtual void * GetSource() const { return origin; }
|
||||
virtual const char *GetName();
|
||||
secplane_t * origin;
|
||||
|
||||
public:
|
||||
|
||||
HWPlaneMirrorPortal(secplane_t * pt)
|
||||
{
|
||||
origin = pt;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -30,68 +30,12 @@
|
|||
#include "r_sky.h"
|
||||
#include "g_levellocals.h"
|
||||
|
||||
#include "hwrenderer/scene/hw_drawinfo.h"
|
||||
#include "hw_drawinfo.h"
|
||||
#include "hw_drawstructs.h"
|
||||
#include "hwrenderer/utility/hw_clock.h"
|
||||
|
||||
sector_t * hw_FakeFlat(sector_t * sec, sector_t * dest, area_t in_area, bool back);
|
||||
|
||||
void HWDrawInfo::ClearBuffers()
|
||||
{
|
||||
for(unsigned int i=0;i< otherfloorplanes.Size();i++)
|
||||
{
|
||||
gl_subsectorrendernode * node = otherfloorplanes[i];
|
||||
while (node)
|
||||
{
|
||||
gl_subsectorrendernode * n = node;
|
||||
node = node->next;
|
||||
delete n;
|
||||
}
|
||||
}
|
||||
otherfloorplanes.Clear();
|
||||
|
||||
for(unsigned int i=0;i< otherceilingplanes.Size();i++)
|
||||
{
|
||||
gl_subsectorrendernode * node = otherceilingplanes[i];
|
||||
while (node)
|
||||
{
|
||||
gl_subsectorrendernode * n = node;
|
||||
node = node->next;
|
||||
delete n;
|
||||
}
|
||||
}
|
||||
otherceilingplanes.Clear();
|
||||
|
||||
// clear all the lists that might not have been cleared already
|
||||
MissingUpperTextures.Clear();
|
||||
MissingLowerTextures.Clear();
|
||||
MissingUpperSegs.Clear();
|
||||
MissingLowerSegs.Clear();
|
||||
SubsectorHacks.Clear();
|
||||
CeilingStacks.Clear();
|
||||
FloorStacks.Clear();
|
||||
HandledSubsectors.Clear();
|
||||
spriteindex = 0;
|
||||
|
||||
CurrentMapSections.Resize(level.NumMapSections);
|
||||
CurrentMapSections.Zero();
|
||||
|
||||
sectorrenderflags.Resize(level.sectors.Size());
|
||||
ss_renderflags.Resize(level.subsectors.Size());
|
||||
no_renderflags.Resize(level.subsectors.Size());
|
||||
|
||||
memset(§orrenderflags[0], 0, level.sectors.Size() * sizeof(sectorrenderflags[0]));
|
||||
memset(&ss_renderflags[0], 0, level.subsectors.Size() * sizeof(ss_renderflags[0]));
|
||||
memset(&no_renderflags[0], 0, level.nodes.Size() * sizeof(no_renderflags[0]));
|
||||
|
||||
mClipPortal = nullptr;
|
||||
}
|
||||
|
||||
void HWDrawInfo::UpdateCurrentMapSection()
|
||||
{
|
||||
const int mapsection = R_PointInSubsector(r_viewpoint.Pos)->mapsection;
|
||||
CurrentMapSections.Set(mapsection);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// Adds a subsector plane to a sector's render list
|
||||
|
|
@ -484,7 +428,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 +500,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 +586,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 +608,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 +701,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);
|
||||
}
|
||||
}
|
||||
|
|
@ -901,9 +845,21 @@ bool HWDrawInfo::CollectSubsectorsCeiling(subsector_t * sub, sector_t * anchor)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
void HWDrawInfo::ProcessLowerMinisegs(TArray<seg_t *> &lowersegs)
|
||||
{
|
||||
for(unsigned int j=0;j<lowersegs.Size();j++)
|
||||
{
|
||||
seg_t * seg=lowersegs[j];
|
||||
GLWall wall;
|
||||
wall.ProcessLowerMiniseg(this, seg, seg->Subsector->render_sector, seg->PartnerSeg->Subsector->render_sector);
|
||||
rendered_lines++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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++;
|
||||
|
|
|
|||
|
|
@ -154,8 +154,9 @@ void GLWall::SkyPlane(HWDrawInfo *di, sector_t *sector, int plane, bool allowref
|
|||
}
|
||||
else if (allowreflect && sector->GetReflect(plane) > 0)
|
||||
{
|
||||
if ((plane == sector_t::ceiling && r_viewpoint.Pos.Z > sector->ceilingplane.fD()) ||
|
||||
(plane == sector_t::floor && r_viewpoint.Pos.Z < -sector->floorplane.fD())) return;
|
||||
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;
|
||||
planemirror = plane == sector_t::ceiling ? §or->ceilingplane : §or->floorplane;
|
||||
}
|
||||
|
|
@ -340,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;
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -68,8 +68,9 @@ EXTERN_CVAR(Float, transsouls)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
bool GLSprite::CalculateVertices(HWDrawInfo *di, FVector3 *v)
|
||||
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;
|
||||
|
|
@ -146,10 +147,10 @@ bool GLSprite::CalculateVertices(HWDrawInfo *di, FVector3 *v)
|
|||
{
|
||||
// [CMB] Rotate relative to camera XY position, not just camera direction,
|
||||
// which is nicer in VR
|
||||
float xrel = xcenter - r_viewpoint.Pos.X;
|
||||
float yrel = ycenter - r_viewpoint.Pos.Y;
|
||||
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)
|
|||
|
||||
// [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)
|
|||
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)
|
|||
// 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,8 @@ void GLSprite::Process(HWDrawInfo *di, AActor* thing, sector_t * sector, area_t
|
|||
return;
|
||||
}
|
||||
|
||||
AActor *camera = r_viewpoint.camera;
|
||||
const auto &vp = di->Viewpoint;
|
||||
AActor *camera = vp.camera;
|
||||
|
||||
if (thing->renderflags & RF_INVISIBLE || !thing->RenderStyle.IsVisible(thing->Alpha))
|
||||
{
|
||||
|
|
@ -425,26 +427,26 @@ void GLSprite::Process(HWDrawInfo *di, AActor* thing, sector_t * sector, area_t
|
|||
}
|
||||
|
||||
// [RH] Interpolate the sprite's position to make it look smooth
|
||||
DVector3 thingpos = thing->InterpolatedPosition(r_viewpoint.TicFrac);
|
||||
DVector3 thingpos = thing->InterpolatedPosition(vp.TicFrac);
|
||||
if (thruportal == 1) thingpos += level.Displacements.getOffset(thing->Sector->PortalGroup, sector->PortalGroup);
|
||||
|
||||
// Some added checks if the camera actor is not supposed to be seen. It can happen that some portal setup has this actor in view in which case it may not be skipped here
|
||||
if (thing == camera && !r_viewpoint.showviewer)
|
||||
if (thing == camera && !vp.showviewer)
|
||||
{
|
||||
DVector3 thingorigin = thing->Pos();
|
||||
if (thruportal == 1) thingorigin += level.Displacements.getOffset(thing->Sector->PortalGroup, sector->PortalGroup);
|
||||
if (fabs(thingorigin.X - r_viewpoint.ActorPos.X) < 2 && fabs(thingorigin.Y - r_viewpoint.ActorPos.Y) < 2) return;
|
||||
if (fabs(thingorigin.X - vp.ActorPos.X) < 2 && fabs(thingorigin.Y - vp.ActorPos.Y) < 2) return;
|
||||
}
|
||||
// Thing is invisible if close to the camera.
|
||||
if (thing->renderflags & RF_MAYBEINVISIBLE)
|
||||
{
|
||||
if (fabs(thingpos.X - r_viewpoint.Pos.X) < 32 && fabs(thingpos.Y - r_viewpoint.Pos.Y) < 32) return;
|
||||
if (fabs(thingpos.X - vp.Pos.X) < 32 && fabs(thingpos.Y - vp.Pos.Y) < 32) return;
|
||||
}
|
||||
|
||||
// Too close to the camera. This doesn't look good if it is a sprite.
|
||||
if (fabs(thingpos.X - r_viewpoint.Pos.X) < 2 && fabs(thingpos.Y - r_viewpoint.Pos.Y) < 2)
|
||||
if (fabs(thingpos.X - vp.Pos.X) < 2 && fabs(thingpos.Y - vp.Pos.Y) < 2)
|
||||
{
|
||||
if (r_viewpoint.Pos.Z >= thingpos.Z - 2 && r_viewpoint.Pos.Z <= thingpos.Z + thing->Height + 2)
|
||||
if (vp.Pos.Z >= thingpos.Z - 2 && vp.Pos.Z <= thingpos.Z + thing->Height + 2)
|
||||
{
|
||||
// exclude vertically moving objects from this check.
|
||||
if (!thing->Vel.isZero())
|
||||
|
|
@ -460,13 +462,13 @@ void GLSprite::Process(HWDrawInfo *di, AActor* thing, sector_t * sector, area_t
|
|||
// don't draw first frame of a player missile
|
||||
if (thing->flags&MF_MISSILE)
|
||||
{
|
||||
if (!(thing->flags7 & MF7_FLYCHEAT) && thing->target == di->mViewActor && di->mViewActor != nullptr)
|
||||
if (!(thing->flags7 & MF7_FLYCHEAT) && thing->target == vp.ViewActor && vp.ViewActor != nullptr)
|
||||
{
|
||||
double speed = thing->Vel.Length();
|
||||
if (speed >= thing->target->radius / 2)
|
||||
{
|
||||
double clipdist = clamp(thing->Speed, thing->target->radius, thing->target->radius * 2);
|
||||
if ((thingpos - r_viewpoint.Pos).LengthSquared() < clipdist * clipdist) return;
|
||||
if ((thingpos - vp.Pos).LengthSquared() < clipdist * clipdist) return;
|
||||
}
|
||||
}
|
||||
thing->flags7 |= MF7_FLYCHEAT; // do this only once for the very first frame, but not if it gets into range again.
|
||||
|
|
@ -479,7 +481,7 @@ void GLSprite::Process(HWDrawInfo *di, AActor* thing, sector_t * sector, area_t
|
|||
}
|
||||
// disabled because almost none of the actual game code is even remotely prepared for this. If desired, use the INTERPOLATE flag.
|
||||
if (thing->renderflags & RF_INTERPOLATEANGLES)
|
||||
Angles = thing->InterpolatedAngles(r_viewpoint.TicFrac);
|
||||
Angles = thing->InterpolatedAngles(vp.TicFrac);
|
||||
else
|
||||
Angles = thing->Angles;
|
||||
|
||||
|
|
@ -506,7 +508,7 @@ void GLSprite::Process(HWDrawInfo *di, AActor* thing, sector_t * sector, area_t
|
|||
// [RH] Make floatbobbing a renderer-only effect.
|
||||
if (thing->flags2 & MF2_FLOATBOB)
|
||||
{
|
||||
float fz = thing->GetBobOffset(r_viewpoint.TicFrac);
|
||||
float fz = thing->GetBobOffset(vp.TicFrac);
|
||||
z += fz;
|
||||
}
|
||||
|
||||
|
|
@ -514,7 +516,7 @@ void GLSprite::Process(HWDrawInfo *di, AActor* thing, sector_t * sector, area_t
|
|||
if (!modelframe)
|
||||
{
|
||||
bool mirror;
|
||||
DAngle ang = (thingpos - r_viewpoint.Pos).Angle();
|
||||
DAngle ang = (thingpos - vp.Pos).Angle();
|
||||
FTextureID patch;
|
||||
// [ZZ] add direct picnum override
|
||||
if (isPicnumOverride)
|
||||
|
|
@ -531,7 +533,7 @@ void GLSprite::Process(HWDrawInfo *di, AActor* thing, sector_t * sector, area_t
|
|||
int rot;
|
||||
if (!(thing->renderflags & RF_FLATSPRITE) || thing->flags7 & MF7_SPRITEANGLE)
|
||||
{
|
||||
sprangle = thing->GetSpriteAngle(ang, r_viewpoint.TicFrac);
|
||||
sprangle = thing->GetSpriteAngle(ang, vp.TicFrac);
|
||||
rot = -1;
|
||||
}
|
||||
else
|
||||
|
|
@ -596,8 +598,8 @@ void GLSprite::Process(HWDrawInfo *di, AActor* thing, sector_t * sector, area_t
|
|||
switch (spritetype)
|
||||
{
|
||||
case RF_FACESPRITE:
|
||||
viewvecX = di->mViewVector.X;
|
||||
viewvecY = di->mViewVector.Y;
|
||||
viewvecX = vp.ViewVector.X;
|
||||
viewvecY = vp.ViewVector.Y;
|
||||
|
||||
x1 = x - viewvecY*leftfac;
|
||||
x2 = x - viewvecY*rightfac;
|
||||
|
|
@ -632,7 +634,7 @@ void GLSprite::Process(HWDrawInfo *di, AActor* thing, sector_t * sector, area_t
|
|||
gltexture = nullptr;
|
||||
}
|
||||
|
||||
depth = FloatToFixed((x - r_viewpoint.Pos.X) * r_viewpoint.TanCos + (y - r_viewpoint.Pos.Y) * r_viewpoint.TanSin);
|
||||
depth = FloatToFixed((x - vp.Pos.X) * vp.TanCos + (y - vp.Pos.Y) * vp.TanSin);
|
||||
|
||||
// light calculation
|
||||
|
||||
|
|
@ -923,7 +925,8 @@ void GLSprite::ProcessParticle (HWDrawInfo *di, particle_t *particle, sector_t *
|
|||
}
|
||||
}
|
||||
|
||||
double timefrac = r_viewpoint.TicFrac;
|
||||
const auto &vp = di->Viewpoint;
|
||||
double timefrac = vp.TicFrac;
|
||||
if (paused || bglobal.freeze || (level.flags2 & LEVEL2_FROZEN))
|
||||
timefrac = 0.;
|
||||
float xvf = (particle->Vel.X) * timefrac;
|
||||
|
|
@ -940,8 +943,8 @@ void GLSprite::ProcessParticle (HWDrawInfo *di, particle_t *particle, sector_t *
|
|||
else factor = 1 / 7.f;
|
||||
float scalefac=particle->size * factor;
|
||||
|
||||
float viewvecX = di->mViewVector.X;
|
||||
float viewvecY = di->mViewVector.Y;
|
||||
float viewvecX = vp.ViewVector.X;
|
||||
float viewvecY = vp.ViewVector.Y;
|
||||
|
||||
x1=x+viewvecY*scalefac;
|
||||
x2=x-viewvecY*scalefac;
|
||||
|
|
@ -950,7 +953,7 @@ void GLSprite::ProcessParticle (HWDrawInfo *di, particle_t *particle, sector_t *
|
|||
z1=z-scalefac;
|
||||
z2=z+scalefac;
|
||||
|
||||
depth = FloatToFixed((x - r_viewpoint.Pos.X) * r_viewpoint.TanCos + (y - r_viewpoint.Pos.Y) * r_viewpoint.TanSin);
|
||||
depth = FloatToFixed((x - vp.Pos.X) * vp.TanCos + (y - vp.Pos.Y) * vp.TanSin);
|
||||
|
||||
actor=nullptr;
|
||||
this->particle=particle;
|
||||
|
|
@ -980,6 +983,7 @@ void HWDrawInfo::ProcessActorsInPortal(FLinePortalSpan *glport, area_t in_area)
|
|||
TMap<AActor*, bool> processcheck;
|
||||
if (glport->validcount == validcount) return; // only process once per frame
|
||||
glport->validcount = validcount;
|
||||
const auto &vp = Viewpoint;
|
||||
for (auto port : glport->lines)
|
||||
{
|
||||
line_t *line = port->mOrigin;
|
||||
|
|
@ -1003,9 +1007,9 @@ void HWDrawInfo::ProcessActorsInPortal(FLinePortalSpan *glport, area_t in_area)
|
|||
DVector3 newpos = savedpos;
|
||||
sector_t fakesector;
|
||||
|
||||
if (!r_viewpoint.showviewer && th == r_viewpoint.camera)
|
||||
if (!vp.showviewer && th == vp.camera)
|
||||
{
|
||||
if (fabs(savedpos.X - r_viewpoint.ActorPos.X) < 2 && fabs(savedpos.Y - r_viewpoint.ActorPos.Y) < 2)
|
||||
if (fabs(savedpos.X - vp.ActorPos.X) < 2 && fabs(savedpos.Y - vp.ActorPos.Y) < 2)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
|
|
|||
30
src/hwrenderer/scene/hw_viewpointuniforms.h
Normal file
30
src/hwrenderer/scene/hw_viewpointuniforms.h
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
#pragma once
|
||||
|
||||
#include "r_data/matrix.h"
|
||||
#include "r_utility.h"
|
||||
|
||||
struct HWViewpointUniforms
|
||||
{
|
||||
VSMatrix mProjectionMatrix;
|
||||
VSMatrix mViewMatrix;
|
||||
VSMatrix mNormalViewMatrix;
|
||||
FVector4 mCameraPos;
|
||||
FVector4 mClipLine;
|
||||
|
||||
float mGlobVis = 1.f;
|
||||
int mPalLightLevels = 0;
|
||||
int mViewHeight = 0;
|
||||
float mClipHeight = 0.f;
|
||||
float mClipHeightDirection = 0.f;
|
||||
|
||||
void CalcDependencies()
|
||||
{
|
||||
mNormalViewMatrix.computeNormalMatrix(mViewMatrix);
|
||||
}
|
||||
|
||||
void SetDefaults();
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
|
@ -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,10 +443,11 @@ 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);
|
||||
|
||||
if (r_viewpoint.Pos.Z < fs->GetPlaneTexZ(sector_t::ceiling))
|
||||
auto vpz = di->Viewpoint.Pos.Z;
|
||||
if (vpz < fs->GetPlaneTexZ(sector_t::ceiling))
|
||||
{
|
||||
if (r_viewpoint.Pos.Z > fs->GetPlaneTexZ(sector_t::floor))
|
||||
zbottom[1] = zbottom[0] = r_viewpoint.Pos.Z;
|
||||
if (vpz > fs->GetPlaneTexZ(sector_t::floor))
|
||||
zbottom[1] = zbottom[0] = vpz;
|
||||
|
||||
if (fs->GetTexture(sector_t::ceiling) == skyflatnum)
|
||||
{
|
||||
|
|
@ -474,7 +475,7 @@ bool GLWall::DoHorizon(HWDrawInfo *di, seg_t * seg,sector_t * fs, vertex_t * v1,
|
|||
ztop[1] = ztop[0] = zbottom[0];
|
||||
}
|
||||
|
||||
if (r_viewpoint.Pos.Z > fs->GetPlaneTexZ(sector_t::floor))
|
||||
if (vpz > fs->GetPlaneTexZ(sector_t::floor))
|
||||
{
|
||||
zbottom[1] = zbottom[0] = fs->GetPlaneTexZ(sector_t::floor);
|
||||
if (fs->GetTexture(sector_t::floor) == skyflatnum)
|
||||
|
|
@ -1457,7 +1458,7 @@ void GLWall::Process(HWDrawInfo *di, seg_t *seg, sector_t * frontsector, sector_
|
|||
sector_t * segback;
|
||||
|
||||
#ifdef _DEBUG
|
||||
if (seg->linedef->Index() == 10)
|
||||
if (seg->linedef->Index() == 3407)
|
||||
{
|
||||
int a = 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -76,10 +76,10 @@ static bool isBright(DPSprite *psp)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
static WeaponPosition GetWeaponPosition(player_t *player)
|
||||
static WeaponPosition GetWeaponPosition(player_t *player, double ticFrac)
|
||||
{
|
||||
WeaponPosition w;
|
||||
P_BobWeapon(player, &w.bobx, &w.boby, r_viewpoint.TicFrac);
|
||||
P_BobWeapon(player, &w.bobx, &w.boby, ticFrac);
|
||||
|
||||
// Interpolate the main weapon layer once so as to be able to add it to other layers.
|
||||
if ((w.weapon = player->FindPSprite(PSP_WEAPON)) != nullptr)
|
||||
|
|
@ -91,8 +91,8 @@ static WeaponPosition GetWeaponPosition(player_t *player)
|
|||
}
|
||||
else
|
||||
{
|
||||
w.wx = (float)(w.weapon->oldx + (w.weapon->x - w.weapon->oldx) * r_viewpoint.TicFrac);
|
||||
w.wy = (float)(w.weapon->oldy + (w.weapon->y - w.weapon->oldy) * r_viewpoint.TicFrac);
|
||||
w.wx = (float)(w.weapon->oldx + (w.weapon->x - w.weapon->oldx) * ticFrac);
|
||||
w.wy = (float)(w.weapon->oldy + (w.weapon->y - w.weapon->oldy) * ticFrac);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
@ -109,7 +109,7 @@ static WeaponPosition GetWeaponPosition(player_t *player)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
static FVector2 BobWeapon(WeaponPosition &weap, DPSprite *psp)
|
||||
static FVector2 BobWeapon(WeaponPosition &weap, DPSprite *psp, double ticFrac)
|
||||
{
|
||||
if (psp->firstTic)
|
||||
{ // Can't interpolate the first tic.
|
||||
|
|
@ -118,8 +118,8 @@ static FVector2 BobWeapon(WeaponPosition &weap, DPSprite *psp)
|
|||
psp->oldy = psp->y;
|
||||
}
|
||||
|
||||
float sx = float(psp->oldx + (psp->x - psp->oldx) * r_viewpoint.TicFrac);
|
||||
float sy = float(psp->oldy + (psp->y - psp->oldy) * r_viewpoint.TicFrac);
|
||||
float sx = float(psp->oldx + (psp->x - psp->oldx) * ticFrac);
|
||||
float sy = float(psp->oldy + (psp->y - psp->oldy) * ticFrac);
|
||||
|
||||
if (psp->Flags & PSPF_ADDBOB)
|
||||
{
|
||||
|
|
@ -169,14 +169,14 @@ static WeaponLighting GetWeaponLighting(sector_t *viewsector, const DVector3 &po
|
|||
|
||||
if (i<lightlist.Size() - 1)
|
||||
{
|
||||
lightbottom = lightlist[i + 1].plane.ZatPoint(r_viewpoint.Pos);
|
||||
lightbottom = lightlist[i + 1].plane.ZatPoint(pos);
|
||||
}
|
||||
else
|
||||
{
|
||||
lightbottom = viewsector->floorplane.ZatPoint(r_viewpoint.Pos);
|
||||
lightbottom = viewsector->floorplane.ZatPoint(pos);
|
||||
}
|
||||
|
||||
if (lightbottom<r_viewpoint.Pos.Z)
|
||||
if (lightbottom < pos.Z)
|
||||
{
|
||||
l.cm = lightlist[i].extra_colormap;
|
||||
l.lightlevel = hw_ClampLight(*lightlist[i].p_lightlevel);
|
||||
|
|
@ -426,8 +426,10 @@ void HWDrawInfo::PreparePlayerSprites(sector_t * viewsector, area_t in_area)
|
|||
AActor * playermo = players[consoleplayer].camera;
|
||||
player_t * player = playermo->player;
|
||||
const bool hudModelStep = IsHUDModelForPlayerAvailable(player);
|
||||
|
||||
const auto &vp = Viewpoint;
|
||||
|
||||
AActor *camera = r_viewpoint.camera;
|
||||
AActor *camera = vp.camera;
|
||||
|
||||
// this is the same as the software renderer
|
||||
if (!player ||
|
||||
|
|
@ -437,8 +439,8 @@ void HWDrawInfo::PreparePlayerSprites(sector_t * viewsector, area_t in_area)
|
|||
(r_deathcamera && camera->health <= 0))
|
||||
return;
|
||||
|
||||
WeaponPosition weap = GetWeaponPosition(camera->player);
|
||||
WeaponLighting light = GetWeaponLighting(viewsector, r_viewpoint.Pos, isFullbrightScene(), in_area, camera->Pos());
|
||||
WeaponPosition weap = GetWeaponPosition(camera->player, vp.TicFrac);
|
||||
WeaponLighting light = GetWeaponLighting(viewsector, vp.Pos, isFullbrightScene(), in_area, camera->Pos());
|
||||
|
||||
// hack alert! Rather than changing everything in the underlying lighting code let's just temporarily change
|
||||
// light mode here to draw the weapon sprite.
|
||||
|
|
@ -460,7 +462,7 @@ void HWDrawInfo::PreparePlayerSprites(sector_t * viewsector, area_t in_area)
|
|||
|
||||
if (!hudsprite.GetWeaponRenderStyle(psp, camera, viewsector, light)) continue;
|
||||
|
||||
FVector2 spos = BobWeapon(weap, psp);
|
||||
FVector2 spos = BobWeapon(weap, psp, vp.TicFrac);
|
||||
|
||||
hudsprite.dynrgb[0] = hudsprite.dynrgb[1] = hudsprite.dynrgb[2] = 0;
|
||||
hudsprite.lightindex = -1;
|
||||
|
|
@ -505,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 ||
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ class AActor;
|
|||
enum area_t : int;
|
||||
struct FSpriteModelFrame;
|
||||
struct HWDrawInfo;
|
||||
class FMaterial;
|
||||
|
||||
|
||||
struct WeaponPosition
|
||||
|
|
|
|||
|
|
@ -160,8 +160,9 @@ void CheckBench()
|
|||
|
||||
FString compose;
|
||||
|
||||
auto &vp = r_viewpoint;
|
||||
compose.Format("Map %s: \"%s\",\nx = %1.4f, y = %1.4f, z = %1.4f, angle = %1.4f, pitch = %1.4f\n",
|
||||
level.MapName.GetChars(), level.LevelName.GetChars(), r_viewpoint.Pos.X, r_viewpoint.Pos.Y, r_viewpoint.Pos.Z, r_viewpoint.Angles.Yaw.Degrees, r_viewpoint.Angles.Pitch.Degrees);
|
||||
level.MapName.GetChars(), level.LevelName.GetChars(), vp.Pos.X, vp.Pos.Y, vp.Pos.Z, vp.Angles.Yaw.Degrees, vp.Angles.Pitch.Degrees);
|
||||
|
||||
AppendRenderStats(compose);
|
||||
AppendRenderTimes(compose);
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@
|
|||
#include "c_dispatch.h"
|
||||
#include "v_video.h"
|
||||
#include "hw_cvars.h"
|
||||
#include "hwrenderer/textures/hw_material.h"
|
||||
#include "menu/menu.h"
|
||||
|
||||
|
||||
|
|
@ -91,7 +92,7 @@ CUSTOM_CVAR(Float,gl_texture_filter_anisotropic,8.0f,CVAR_ARCHIVE|CVAR_GLOBALCON
|
|||
|
||||
CCMD(gl_flush)
|
||||
{
|
||||
screen->FlushTextures();
|
||||
FMaterial::FlushAll();
|
||||
}
|
||||
|
||||
CUSTOM_CVAR(Int, gl_texture_filter, 4, CVAR_ARCHIVE|CVAR_GLOBALCONFIG|CVAR_NOINITCALL)
|
||||
|
|
@ -102,7 +103,7 @@ CUSTOM_CVAR(Int, gl_texture_filter, 4, CVAR_ARCHIVE|CVAR_GLOBALCONFIG|CVAR_NOINI
|
|||
|
||||
CUSTOM_CVAR(Bool, gl_texture_usehires, true, CVAR_ARCHIVE|CVAR_NOINITCALL)
|
||||
{
|
||||
screen->FlushTextures();
|
||||
FMaterial::FlushAll();
|
||||
}
|
||||
|
||||
CVAR(Bool, gl_precache, false, CVAR_ARCHIVE)
|
||||
|
|
|
|||
176
src/hwrenderer/utility/hw_vrmodes.cpp
Normal file
176
src/hwrenderer/utility/hw_vrmodes.cpp
Normal file
|
|
@ -0,0 +1,176 @@
|
|||
//
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// Copyright(C) 2015 Christopher Bruns
|
||||
// All rights reserved.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with this program. If not, see http://www.gnu.org/licenses/
|
||||
//
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
/*
|
||||
** gl_stereo_leftright.cpp
|
||||
** Offsets for left and right eye views
|
||||
**
|
||||
*/
|
||||
|
||||
#include "vectors.h" // RAD2DEG
|
||||
#include "doomtype.h" // M_PI
|
||||
#include "hwrenderer/utility/hw_cvars.h"
|
||||
#include "hw_vrmodes.h"
|
||||
#include "v_video.h"
|
||||
|
||||
// Set up 3D-specific console variables:
|
||||
CVAR(Int, vr_mode, 0, CVAR_GLOBALCONFIG)
|
||||
|
||||
// switch left and right eye views
|
||||
CVAR(Bool, vr_swap_eyes, false, CVAR_GLOBALCONFIG)
|
||||
|
||||
// intraocular distance in meters
|
||||
CVAR(Float, vr_ipd, 0.062f, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) // METERS
|
||||
|
||||
// distance between viewer and the display screen
|
||||
CVAR(Float, vr_screendist, 0.80f, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) // METERS
|
||||
|
||||
// default conversion between (vertical) DOOM units and meters
|
||||
CVAR(Float, vr_hunits_per_meter, 41.0f, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) // METERS
|
||||
|
||||
|
||||
#define isqrt2 0.7071067812f
|
||||
static VRMode vrmi_mono = { 1, 1.f, 1.f, 1.f,{ { 0.f, 1.f },{ 0.f, 0.f } } };
|
||||
static VRMode vrmi_stereo = { 2, 1.f, 1.f, 1.f,{ { -.5f, 1.f },{ .5f, 1.f } } };
|
||||
static VRMode vrmi_sbsfull = { 2, .5f, 1.f, 2.f,{ { -.5f, .5f },{ .5f, .5f } } };
|
||||
static VRMode vrmi_sbssquished = { 2, .5f, 1.f, 1.f,{ { -.5f, 1.f },{ .5f, 1.f } } };
|
||||
static VRMode vrmi_lefteye = { 1, 1.f, 1.f, 1.f, { { -.5f, 1.f },{ 0.f, 0.f } } };
|
||||
static VRMode vrmi_righteye = { 1, 1.f, 1.f, 1.f,{ { .5f, 1.f },{ 0.f, 0.f } } };
|
||||
static VRMode vrmi_topbottom = { 2, 1.f, .5f, 1.f,{ { -.5f, 1.f },{ .5f, 1.f } } };
|
||||
static VRMode vrmi_checker = { 2, isqrt2, isqrt2, 1.f,{ { -.5f, 1.f },{ .5f, 1.f } } };
|
||||
|
||||
const VRMode *VRMode::GetVRMode(bool toscreen)
|
||||
{
|
||||
switch (toscreen && vid_rendermode == 4 ? vr_mode : 0)
|
||||
{
|
||||
default:
|
||||
case VR_MONO:
|
||||
return &vrmi_mono;
|
||||
|
||||
case VR_GREENMAGENTA:
|
||||
case VR_REDCYAN:
|
||||
case VR_QUADSTEREO:
|
||||
case VR_AMBERBLUE:
|
||||
return &vrmi_stereo;
|
||||
|
||||
case VR_SIDEBYSIDESQUISHED:
|
||||
case VR_COLUMNINTERLEAVED:
|
||||
return &vrmi_sbssquished;
|
||||
|
||||
case VR_SIDEBYSIDEFULL:
|
||||
return &vrmi_sbsfull;
|
||||
|
||||
case VR_TOPBOTTOM:
|
||||
case VR_ROWINTERLEAVED:
|
||||
return &vrmi_topbottom;
|
||||
|
||||
case VR_LEFTEYEVIEW:
|
||||
return &vrmi_lefteye;
|
||||
|
||||
case VR_RIGHTEYEVIEW:
|
||||
return &vrmi_righteye;
|
||||
|
||||
case VR_CHECKERINTERLEAVED:
|
||||
return &vrmi_checker;
|
||||
}
|
||||
}
|
||||
|
||||
void VRMode::AdjustViewport(DFrameBuffer *screen) const
|
||||
{
|
||||
screen->mSceneViewport.height = (int)(screen->mSceneViewport.height * mVerticalViewportScale);
|
||||
screen->mSceneViewport.top = (int)(screen->mSceneViewport.top * mVerticalViewportScale);
|
||||
screen->mSceneViewport.width = (int)(screen->mSceneViewport.width * mHorizontalViewportScale);
|
||||
screen->mSceneViewport.left = (int)(screen->mSceneViewport.left * mHorizontalViewportScale);
|
||||
|
||||
screen->mScreenViewport.height = (int)(screen->mScreenViewport.height * mVerticalViewportScale);
|
||||
screen->mScreenViewport.top = (int)(screen->mScreenViewport.top * mVerticalViewportScale);
|
||||
screen->mScreenViewport.width = (int)(screen->mScreenViewport.width * mHorizontalViewportScale);
|
||||
screen->mScreenViewport.left = (int)(screen->mScreenViewport.left * mHorizontalViewportScale);
|
||||
}
|
||||
|
||||
VSMatrix VRMode::GetHUDSpriteProjection() const
|
||||
{
|
||||
VSMatrix mat;
|
||||
int w = screen->GetWidth();
|
||||
int h = screen->GetHeight();
|
||||
float scaled_w = w / mWeaponProjectionScale;
|
||||
float left_ofs = (w - scaled_w) / 2.f;
|
||||
mat.ortho(left_ofs, left_ofs + scaled_w, (float)h, 0, -1.0f, 1.0f);
|
||||
return mat;
|
||||
}
|
||||
|
||||
float VREyeInfo::getShift() const
|
||||
{
|
||||
auto res = mShiftFactor * vr_ipd;
|
||||
return vr_swap_eyes ? -res : res;
|
||||
}
|
||||
|
||||
VSMatrix VREyeInfo::GetProjection(float fov, float aspectRatio, float fovRatio) const
|
||||
{
|
||||
VSMatrix result;
|
||||
|
||||
if (mShiftFactor == 0)
|
||||
{
|
||||
float fovy = (float)(2 * RAD2DEG(atan(tan(DEG2RAD(fov) / 2) / fovRatio)));
|
||||
result.perspective(fovy, aspectRatio, screen->GetZNear(), screen->GetZFar());
|
||||
return result;
|
||||
}
|
||||
else
|
||||
{
|
||||
double zNear = screen->GetZNear();
|
||||
double zFar = screen->GetZFar();
|
||||
|
||||
// For stereo 3D, use asymmetric frustum shift in projection matrix
|
||||
// Q: shouldn't shift vary with roll angle, at least for desktop display?
|
||||
// A: No. (lab) roll is not measured on desktop display (yet)
|
||||
double frustumShift = zNear * getShift() / vr_screendist; // meters cancel, leaving doom units
|
||||
// double frustumShift = 0; // Turning off shift for debugging
|
||||
double fH = zNear * tan(DEG2RAD(fov) / 2) / fovRatio;
|
||||
double fW = fH * aspectRatio * mScaleFactor;
|
||||
double left = -fW - frustumShift;
|
||||
double right = fW - frustumShift;
|
||||
double bottom = -fH;
|
||||
double top = fH;
|
||||
|
||||
VSMatrix result(1);
|
||||
result.frustum((float)left, (float)right, (float)bottom, (float)top, (float)zNear, (float)zFar);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* virtual */
|
||||
DVector3 VREyeInfo::GetViewShift(float yaw) const
|
||||
{
|
||||
if (mShiftFactor == 0)
|
||||
{
|
||||
// pass-through for Mono view
|
||||
return { 0,0,0 };
|
||||
}
|
||||
else
|
||||
{
|
||||
double dx = -cos(DEG2RAD(yaw)) * vr_hunits_per_meter * getShift();
|
||||
double dy = sin(DEG2RAD(yaw)) * vr_hunits_per_meter * getShift();
|
||||
return { dx, dy, 0 };
|
||||
}
|
||||
}
|
||||
|
||||
47
src/hwrenderer/utility/hw_vrmodes.h
Normal file
47
src/hwrenderer/utility/hw_vrmodes.h
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
#pragma once
|
||||
|
||||
#include "r_data/matrix.h"
|
||||
|
||||
class DFrameBuffer;
|
||||
|
||||
enum
|
||||
{
|
||||
VR_MONO = 0,
|
||||
VR_GREENMAGENTA = 1,
|
||||
VR_REDCYAN = 2,
|
||||
VR_SIDEBYSIDEFULL = 3,
|
||||
VR_SIDEBYSIDESQUISHED = 4,
|
||||
VR_LEFTEYEVIEW = 5,
|
||||
VR_RIGHTEYEVIEW = 6,
|
||||
VR_QUADSTEREO = 7,
|
||||
VR_AMBERBLUE = 9,
|
||||
VR_TOPBOTTOM = 11,
|
||||
VR_ROWINTERLEAVED = 12,
|
||||
VR_COLUMNINTERLEAVED = 13,
|
||||
VR_CHECKERINTERLEAVED = 14
|
||||
};
|
||||
|
||||
struct VREyeInfo
|
||||
{
|
||||
float mShiftFactor;
|
||||
float mScaleFactor;
|
||||
|
||||
VSMatrix GetProjection(float fov, float aspectRatio, float fovRatio) const;
|
||||
DVector3 GetViewShift(float yaw) const;
|
||||
private:
|
||||
float getShift() const;
|
||||
|
||||
};
|
||||
|
||||
struct VRMode
|
||||
{
|
||||
int mEyeCount;
|
||||
float mHorizontalViewportScale;
|
||||
float mVerticalViewportScale;
|
||||
float mWeaponProjectionScale;
|
||||
VREyeInfo mEyes[2];
|
||||
|
||||
static const VRMode *GetVRMode(bool toscreen = true);
|
||||
void AdjustViewport(DFrameBuffer *fb) const;
|
||||
VSMatrix GetHUDSpriteProjection() const;
|
||||
};
|
||||
|
|
@ -1,62 +0,0 @@
|
|||
//
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// Copyright(C) 2015 Christopher Bruns
|
||||
// All rights reserved.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with this program. If not, see http://www.gnu.org/licenses/
|
||||
//
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
/*
|
||||
** scoped_view_shifter.h
|
||||
** Stack-scoped class for temporarily changing camera viewpoint
|
||||
** Used for stereoscopic 3D.
|
||||
**
|
||||
*/
|
||||
|
||||
#ifndef GL_STEREO3D_SCOPED_VIEW_SHIFTER_H_
|
||||
#define GL_STEREO3D_SCOPED_VIEW_SHIFTER_H_
|
||||
|
||||
#include "basictypes.h"
|
||||
#include "vectors.h"
|
||||
|
||||
/**
|
||||
* Temporarily shift
|
||||
*/
|
||||
class ScopedViewShifter
|
||||
{
|
||||
public:
|
||||
ScopedViewShifter(DVector3 &var, float dxyz[3]) // in meters
|
||||
{
|
||||
// save original values
|
||||
mVar = &var;
|
||||
cachedView = var;
|
||||
// modify values
|
||||
var += DVector3(dxyz[0], dxyz[1], dxyz[2]);
|
||||
}
|
||||
|
||||
~ScopedViewShifter()
|
||||
{
|
||||
// restore original values
|
||||
*mVar = cachedView;
|
||||
}
|
||||
|
||||
private:
|
||||
DVector3 *mVar;
|
||||
DVector3 cachedView;
|
||||
};
|
||||
|
||||
|
||||
#endif // GL_STEREO3D_SCOPED_VIEW_SHIFTER_H_
|
||||
Loading…
Add table
Add a link
Reference in a new issue