mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-11-25 13:31:37 +00:00
Feature-complete isometric mode fork.
This commit is contained in:
parent
29a2ca0b13
commit
6e7ae739e2
31 changed files with 711 additions and 72 deletions
|
@ -2808,7 +2808,7 @@ void DAutomap::drawPlayers ()
|
||||||
int numarrowlines;
|
int numarrowlines;
|
||||||
|
|
||||||
double vh = players[consoleplayer].viewheight;
|
double vh = players[consoleplayer].viewheight;
|
||||||
DVector2 pos = players[consoleplayer].camera->InterpolatedPosition(r_viewpoint.TicFrac).XY();
|
DVector2 pos = players[consoleplayer].mo->InterpolatedPosition(r_viewpoint.TicFrac).XY();
|
||||||
pt.x = pos.X;
|
pt.x = pos.X;
|
||||||
pt.y = pos.Y;
|
pt.y = pos.Y;
|
||||||
if (am_rotate == 1 || (am_rotate == 2 && viewactive))
|
if (am_rotate == 1 || (am_rotate == 2 && viewactive))
|
||||||
|
@ -2818,7 +2818,7 @@ void DAutomap::drawPlayers ()
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
angle = players[consoleplayer].camera->InterpolatedAngles(r_viewpoint.TicFrac).Yaw;
|
angle = players[consoleplayer].mo->InterpolatedAngles(r_viewpoint.TicFrac).Yaw;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (am_cheat != 0 && CheatMapArrow.Size() > 0)
|
if (am_cheat != 0 && CheatMapArrow.Size() > 0)
|
||||||
|
|
|
@ -54,3 +54,6 @@ EXTERN_CVAR(Int, gl_shadowmap_filter)
|
||||||
EXTERN_CVAR(Bool, gl_brightfog)
|
EXTERN_CVAR(Bool, gl_brightfog)
|
||||||
EXTERN_CVAR(Bool, gl_lightadditivesurfaces)
|
EXTERN_CVAR(Bool, gl_lightadditivesurfaces)
|
||||||
EXTERN_CVAR(Bool, gl_notexturefill)
|
EXTERN_CVAR(Bool, gl_notexturefill)
|
||||||
|
|
||||||
|
EXTERN_CVAR(Bool, r_radarclipper)
|
||||||
|
EXTERN_CVAR(Bool, r_dithertransparency)
|
||||||
|
|
|
@ -25,7 +25,7 @@ enum ERenderEffect
|
||||||
EFF_SPHEREMAP,
|
EFF_SPHEREMAP,
|
||||||
EFF_BURN,
|
EFF_BURN,
|
||||||
EFF_STENCIL,
|
EFF_STENCIL,
|
||||||
|
EFF_DITHERTRANS,
|
||||||
MAX_EFFECTS
|
MAX_EFFECTS
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -299,6 +299,7 @@ const FEffectShader effectshaders[] =
|
||||||
{ "spheremap", "shaders/glsl/main.vp", "shaders/glsl/main.fp", "shaders/glsl/func_normal.fp", "shaders/glsl/material_normal.fp", "#define SPHEREMAP\n#define NO_ALPHATEST\n" },
|
{ "spheremap", "shaders/glsl/main.vp", "shaders/glsl/main.fp", "shaders/glsl/func_normal.fp", "shaders/glsl/material_normal.fp", "#define SPHEREMAP\n#define NO_ALPHATEST\n" },
|
||||||
{ "burn", "shaders/glsl/main.vp", "shaders/glsl/burn.fp", nullptr, nullptr, "#define SIMPLE\n#define NO_ALPHATEST\n" },
|
{ "burn", "shaders/glsl/main.vp", "shaders/glsl/burn.fp", nullptr, nullptr, "#define SIMPLE\n#define NO_ALPHATEST\n" },
|
||||||
{ "stencil", "shaders/glsl/main.vp", "shaders/glsl/stencil.fp", nullptr, nullptr, "#define SIMPLE\n#define NO_ALPHATEST\n" },
|
{ "stencil", "shaders/glsl/main.vp", "shaders/glsl/stencil.fp", nullptr, nullptr, "#define SIMPLE\n#define NO_ALPHATEST\n" },
|
||||||
|
{ "dithertrans", "shaders/glsl/main.vp", "shaders/glsl/main.fp", "shaders/glsl/func_normal.fp", "shaders/glsl/material_normal.fp", "#define NO_ALPHATEST\n#define DITHERTRANS\n" },
|
||||||
};
|
};
|
||||||
|
|
||||||
int DFrameBuffer::GetShaderCount()
|
int DFrameBuffer::GetShaderCount()
|
||||||
|
|
|
@ -146,11 +146,27 @@ float VREyeInfo::getShift() const
|
||||||
return vr_swap_eyes ? -res : res;
|
return vr_swap_eyes ? -res : res;
|
||||||
}
|
}
|
||||||
|
|
||||||
VSMatrix VREyeInfo::GetProjection(float fov, float aspectRatio, float fovRatio) const
|
VSMatrix VREyeInfo::GetProjection(float fov, float aspectRatio, float fovRatio, bool iso_ortho) const
|
||||||
{
|
{
|
||||||
VSMatrix result;
|
VSMatrix result;
|
||||||
|
|
||||||
if (mShiftFactor == 0)
|
if (iso_ortho) // Orthographic projection for isometric viewpoint
|
||||||
|
{
|
||||||
|
double zNear = -3.0/fovRatio; // screen->GetZNear();
|
||||||
|
double zFar = screen->GetZFar();
|
||||||
|
|
||||||
|
double fH = tan(DEG2RAD(fov) / 2) / fovRatio;
|
||||||
|
double fW = fH * aspectRatio * mScaleFactor;
|
||||||
|
double left = -fW;
|
||||||
|
double right = fW;
|
||||||
|
double bottom = -fH;
|
||||||
|
double top = fH;
|
||||||
|
|
||||||
|
VSMatrix fmat(1);
|
||||||
|
fmat.ortho((float)left, (float)right, (float)bottom, (float)top, (float)zNear, (float)zFar);
|
||||||
|
return fmat;
|
||||||
|
}
|
||||||
|
else if (mShiftFactor == 0)
|
||||||
{
|
{
|
||||||
float fovy = (float)(2 * RAD2DEG(atan(tan(DEG2RAD(fov) / 2) / fovRatio)));
|
float fovy = (float)(2 * RAD2DEG(atan(tan(DEG2RAD(fov) / 2) / fovRatio)));
|
||||||
result.perspective(fovy, aspectRatio, screen->GetZNear(), screen->GetZFar());
|
result.perspective(fovy, aspectRatio, screen->GetZNear(), screen->GetZFar());
|
||||||
|
|
|
@ -27,7 +27,7 @@ struct VREyeInfo
|
||||||
float mShiftFactor;
|
float mShiftFactor;
|
||||||
float mScaleFactor;
|
float mScaleFactor;
|
||||||
|
|
||||||
VSMatrix GetProjection(float fov, float aspectRatio, float fovRatio) const;
|
VSMatrix GetProjection(float fov, float aspectRatio, float fovRatio, bool iso_ortho) const;
|
||||||
DVector3 GetViewShift(float yaw) const;
|
DVector3 GetViewShift(float yaw) const;
|
||||||
private:
|
private:
|
||||||
float getShift() const;
|
float getShift() const;
|
||||||
|
|
|
@ -1819,6 +1819,7 @@ MapFlagHandlers[] =
|
||||||
{ "disableskyboxao", MITYPE_CLRFLAG3, LEVEL3_SKYBOXAO, 0 },
|
{ "disableskyboxao", MITYPE_CLRFLAG3, LEVEL3_SKYBOXAO, 0 },
|
||||||
{ "avoidmelee", MITYPE_SETFLAG3, LEVEL3_AVOIDMELEE, 0 },
|
{ "avoidmelee", MITYPE_SETFLAG3, LEVEL3_AVOIDMELEE, 0 },
|
||||||
{ "attenuatelights", MITYPE_SETFLAG3, LEVEL3_ATTENUATE, 0 },
|
{ "attenuatelights", MITYPE_SETFLAG3, LEVEL3_ATTENUATE, 0 },
|
||||||
|
{ "nofogofwar", MITYPE_SETFLAG3, LEVEL3_NOFOGOFWAR, 0 },
|
||||||
{ "nobotnodes", MITYPE_IGNORE, 0, 0 }, // Skulltag option: nobotnodes
|
{ "nobotnodes", MITYPE_IGNORE, 0, 0 }, // Skulltag option: nobotnodes
|
||||||
{ "nopassover", MITYPE_COMPATFLAG, COMPATF_NO_PASSMOBJ, 0 },
|
{ "nopassover", MITYPE_COMPATFLAG, COMPATF_NO_PASSMOBJ, 0 },
|
||||||
{ "passover", MITYPE_CLRCOMPATFLAG, COMPATF_NO_PASSMOBJ, 0 },
|
{ "passover", MITYPE_CLRCOMPATFLAG, COMPATF_NO_PASSMOBJ, 0 },
|
||||||
|
|
|
@ -270,6 +270,7 @@ enum ELevelFlags : unsigned int
|
||||||
LEVEL3_AVOIDMELEE = 0x00020000, // global flag needed for proper MBF support.
|
LEVEL3_AVOIDMELEE = 0x00020000, // global flag needed for proper MBF support.
|
||||||
LEVEL3_NOJUMPDOWN = 0x00040000, // only for MBF21. Inverse of MBF's dog_jumping flag.
|
LEVEL3_NOJUMPDOWN = 0x00040000, // only for MBF21. Inverse of MBF's dog_jumping flag.
|
||||||
LEVEL3_LIGHTCREATED = 0x00080000, // a light had been created in the last frame
|
LEVEL3_LIGHTCREATED = 0x00080000, // a light had been created in the last frame
|
||||||
|
LEVEL3_NOFOGOFWAR = 0x00100000, // disables effect of r_radarclipper CVAR on this map
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -303,6 +303,7 @@ struct secplane_t
|
||||||
DVector3 normal;
|
DVector3 normal;
|
||||||
double D, negiC; // negative iC because that also saves a negation in all methods using this.
|
double D, negiC; // negative iC because that also saves a negation in all methods using this.
|
||||||
public:
|
public:
|
||||||
|
bool dithertransflag; // Render plane with dithering transparency shader (gets reset every frame)
|
||||||
friend FSerializer &Serialize(FSerializer &arc, const char *key, secplane_t &p, secplane_t *def);
|
friend FSerializer &Serialize(FSerializer &arc, const char *key, secplane_t &p, secplane_t *def);
|
||||||
|
|
||||||
void set(double aa, double bb, double cc, double dd)
|
void set(double aa, double bb, double cc, double dd)
|
||||||
|
@ -1179,6 +1180,8 @@ enum
|
||||||
WALLF_ABSLIGHTING_TOP = WALLF_ABSLIGHTING_TIER << 0, // Top tier light is absolute instead of relative
|
WALLF_ABSLIGHTING_TOP = WALLF_ABSLIGHTING_TIER << 0, // Top tier light is absolute instead of relative
|
||||||
WALLF_ABSLIGHTING_MID = WALLF_ABSLIGHTING_TIER << 1, // Mid tier light is absolute instead of relative
|
WALLF_ABSLIGHTING_MID = WALLF_ABSLIGHTING_TIER << 1, // Mid tier light is absolute instead of relative
|
||||||
WALLF_ABSLIGHTING_BOTTOM = WALLF_ABSLIGHTING_TIER << 2, // Bottom tier light is absolute instead of relative
|
WALLF_ABSLIGHTING_BOTTOM = WALLF_ABSLIGHTING_TIER << 2, // Bottom tier light is absolute instead of relative
|
||||||
|
|
||||||
|
WALLF_DITHERTRANS = 8192, // Render with dithering transparency shader (gets reset every frame)
|
||||||
};
|
};
|
||||||
|
|
||||||
struct side_t
|
struct side_t
|
||||||
|
|
|
@ -501,6 +501,7 @@ enum ActorRenderFlag2
|
||||||
RF2_FLIPSPRITEOFFSETX = 0x0010,
|
RF2_FLIPSPRITEOFFSETX = 0x0010,
|
||||||
RF2_FLIPSPRITEOFFSETY = 0x0020,
|
RF2_FLIPSPRITEOFFSETY = 0x0020,
|
||||||
RF2_CAMFOLLOWSPLAYER = 0x0040, // Matches the cam's base position and angles to the main viewpoint.
|
RF2_CAMFOLLOWSPLAYER = 0x0040, // Matches the cam's base position and angles to the main viewpoint.
|
||||||
|
RF2_ISOMETRICSPRITES = 0x0080,
|
||||||
};
|
};
|
||||||
|
|
||||||
// This translucency value produces the closest match to Heretic's TINTTAB.
|
// This translucency value produces the closest match to Heretic's TINTTAB.
|
||||||
|
@ -693,6 +694,8 @@ enum EViewPosFlags // [MC] Flags for SetViewPos.
|
||||||
{
|
{
|
||||||
VPSF_ABSOLUTEOFFSET = 1 << 1, // Don't include angles.
|
VPSF_ABSOLUTEOFFSET = 1 << 1, // Don't include angles.
|
||||||
VPSF_ABSOLUTEPOS = 1 << 2, // Use absolute position.
|
VPSF_ABSOLUTEPOS = 1 << 2, // Use absolute position.
|
||||||
|
VPSF_ALLOWOUTOFBOUNDS = 1 << 3, // Allow viewpoint to go out of bounds (hardware renderer only).
|
||||||
|
VPSF_ORTHOGRAPHIC = 1 << 4, // Use orthographic projection (hardware renderer only).
|
||||||
};
|
};
|
||||||
|
|
||||||
enum EAnimOverrideFlags
|
enum EAnimOverrideFlags
|
||||||
|
@ -1119,6 +1122,8 @@ public:
|
||||||
DAngle SpriteAngle;
|
DAngle SpriteAngle;
|
||||||
DAngle SpriteRotation;
|
DAngle SpriteRotation;
|
||||||
DVector2 AutomapOffsets; // Offset the actors' sprite view on the automap by these coordinates.
|
DVector2 AutomapOffsets; // Offset the actors' sprite view on the automap by these coordinates.
|
||||||
|
float isoscaleY; // Y-scale to compensate for Y-billboarding for isometric sprites
|
||||||
|
float isotheta; // Rotation angle to compensate for Y-billboarding for isometric sprites
|
||||||
DRotator Angles;
|
DRotator Angles;
|
||||||
DRotator ViewAngles; // Angle offsets for cameras
|
DRotator ViewAngles; // Angle offsets for cameras
|
||||||
TObjPtr<DViewPosition*> ViewPos; // Position offsets for cameras
|
TObjPtr<DViewPosition*> ViewPos; // Position offsets for cameras
|
||||||
|
|
|
@ -82,6 +82,7 @@
|
||||||
#include "p_blockmap.h"
|
#include "p_blockmap.h"
|
||||||
#include "p_3dmidtex.h"
|
#include "p_3dmidtex.h"
|
||||||
#include "vm.h"
|
#include "vm.h"
|
||||||
|
#include "d_main.h"
|
||||||
|
|
||||||
#include "decallib.h"
|
#include "decallib.h"
|
||||||
|
|
||||||
|
@ -5577,33 +5578,42 @@ void R_OffsetView(FRenderViewpoint& viewPoint, const DVector3& dir, const double
|
||||||
{
|
{
|
||||||
const DAngle baseYaw = dir.Angle();
|
const DAngle baseYaw = dir.Angle();
|
||||||
FTraceResults trace = {};
|
FTraceResults trace = {};
|
||||||
if (Trace(viewPoint.Pos, viewPoint.sector, dir, distance, 0u, 0u, nullptr, trace))
|
if (viewPoint.camera->ViewPos && (viewPoint.camera->ViewPos->Flags & VPSF_ALLOWOUTOFBOUNDS) && V_IsHardwareRenderer())
|
||||||
|
{
|
||||||
|
viewPoint.Pos += dir * distance;
|
||||||
|
viewPoint.sector = viewPoint.ViewLevel->PointInRenderSubsector(viewPoint.Pos)->sector;
|
||||||
|
}
|
||||||
|
else if (Trace(viewPoint.Pos, viewPoint.sector, dir, distance, 0u, 0u, nullptr, trace))
|
||||||
{
|
{
|
||||||
viewPoint.Pos = trace.HitPos - trace.HitVector * min<double>(5.0, trace.Distance);
|
viewPoint.Pos = trace.HitPos - trace.HitVector * min<double>(5.0, trace.Distance);
|
||||||
viewPoint.sector = viewPoint.ViewLevel->PointInRenderSubsector(viewPoint.Pos)->sector;
|
viewPoint.sector = viewPoint.ViewLevel->PointInRenderSubsector(viewPoint.Pos)->sector;
|
||||||
|
viewPoint.Angles.Yaw += deltaangle(baseYaw, trace.SrcAngleFromTarget);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
viewPoint.Pos = trace.HitPos;
|
viewPoint.Pos = trace.HitPos;
|
||||||
viewPoint.sector = trace.Sector;
|
viewPoint.sector = trace.Sector;
|
||||||
|
viewPoint.Angles.Yaw += deltaangle(baseYaw, trace.SrcAngleFromTarget);
|
||||||
}
|
}
|
||||||
|
|
||||||
viewPoint.Angles.Yaw += deltaangle(baseYaw, trace.SrcAngleFromTarget);
|
|
||||||
// TODO: Why does this even need to be done? Please fix tracers already.
|
// TODO: Why does this even need to be done? Please fix tracers already.
|
||||||
if (dir.Z < 0.0)
|
if (!viewPoint.camera->ViewPos || !(viewPoint.camera->ViewPos->Flags & VPSF_ALLOWOUTOFBOUNDS) || !V_IsHardwareRenderer())
|
||||||
{
|
{
|
||||||
while (!viewPoint.sector->PortalBlocksMovement(sector_t::floor) && viewPoint.Pos.Z < viewPoint.sector->GetPortalPlaneZ(sector_t::floor))
|
if (dir.Z < 0.0)
|
||||||
{
|
{
|
||||||
viewPoint.Pos += viewPoint.sector->GetPortalDisplacement(sector_t::floor);
|
while (!viewPoint.sector->PortalBlocksMovement(sector_t::floor) && viewPoint.Pos.Z < viewPoint.sector->GetPortalPlaneZ(sector_t::floor))
|
||||||
viewPoint.sector = viewPoint.sector->GetPortal(sector_t::floor)->mDestination;
|
{
|
||||||
|
viewPoint.Pos += viewPoint.sector->GetPortalDisplacement(sector_t::floor);
|
||||||
|
viewPoint.sector = viewPoint.sector->GetPortal(sector_t::floor)->mDestination;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
else if (dir.Z > 0.0)
|
||||||
else if (dir.Z > 0.0)
|
|
||||||
{
|
|
||||||
while (!viewPoint.sector->PortalBlocksMovement(sector_t::ceiling) && viewPoint.Pos.Z > viewPoint.sector->GetPortalPlaneZ(sector_t::ceiling))
|
|
||||||
{
|
{
|
||||||
viewPoint.Pos += viewPoint.sector->GetPortalDisplacement(sector_t::ceiling);
|
while (!viewPoint.sector->PortalBlocksMovement(sector_t::ceiling) && viewPoint.Pos.Z > viewPoint.sector->GetPortalPlaneZ(sector_t::ceiling))
|
||||||
viewPoint.sector = viewPoint.sector->GetPortal(sector_t::ceiling)->mDestination;
|
{
|
||||||
|
viewPoint.Pos += viewPoint.sector->GetPortalDisplacement(sector_t::ceiling);
|
||||||
|
viewPoint.sector = viewPoint.sector->GetPortal(sector_t::ceiling)->mDestination;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -633,6 +633,9 @@ cont:
|
||||||
case TRACE_Stop:
|
case TRACE_Stop:
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
case TRACE_ContinueOutOfBounds:
|
||||||
|
return true;
|
||||||
|
|
||||||
case TRACE_Abort:
|
case TRACE_Abort:
|
||||||
Results->HitType = TRACE_HitNone;
|
Results->HitType = TRACE_HitNone;
|
||||||
return false;
|
return false;
|
||||||
|
@ -732,6 +735,7 @@ bool FTraceInfo::ThingCheck(intercept_t *in, double dist, DVector3 hit)
|
||||||
switch (TraceCallback(*Results, TraceCallbackData))
|
switch (TraceCallback(*Results, TraceCallbackData))
|
||||||
{
|
{
|
||||||
case TRACE_Continue: return true;
|
case TRACE_Continue: return true;
|
||||||
|
case TRACE_ContinueOutOfBounds: return true;
|
||||||
case TRACE_Stop: return false;
|
case TRACE_Stop: return false;
|
||||||
case TRACE_Abort: Results->HitType = TRACE_HitNone; return false;
|
case TRACE_Abort: Results->HitType = TRACE_HitNone; return false;
|
||||||
case TRACE_Skip: Results->HitType = TRACE_HitNone; return true;
|
case TRACE_Skip: Results->HitType = TRACE_HitNone; return true;
|
||||||
|
|
|
@ -109,6 +109,7 @@ enum ETraceStatus
|
||||||
TRACE_Continue, // continue the trace, returning this hit if there are none further along
|
TRACE_Continue, // continue the trace, returning this hit if there are none further along
|
||||||
TRACE_Skip, // continue the trace; do not return this hit
|
TRACE_Skip, // continue the trace; do not return this hit
|
||||||
TRACE_Abort, // stop the trace, returning no hits
|
TRACE_Abort, // stop the trace, returning no hits
|
||||||
|
TRACE_ContinueOutOfBounds, // continue the trace through walls; don't use this for railguns
|
||||||
};
|
};
|
||||||
|
|
||||||
bool Trace(const DVector3 &start, sector_t *sector, const DVector3 &direction, double maxDist,
|
bool Trace(const DVector3 &start, sector_t *sector, const DVector3 &direction, double maxDist,
|
||||||
|
|
|
@ -163,7 +163,11 @@ sector_t* RenderViewpoint(FRenderViewpoint& mainvp, AActor* camera, IntRect* bou
|
||||||
di->Viewpoint.FieldOfView = DAngle::fromDeg(fov); // Set the real FOV for the current scene (it's not necessarily the same as the global setting in r_viewpoint)
|
di->Viewpoint.FieldOfView = DAngle::fromDeg(fov); // Set the real FOV for the current scene (it's not necessarily the same as the global setting in r_viewpoint)
|
||||||
|
|
||||||
// Stereo mode specific perspective projection
|
// Stereo mode specific perspective projection
|
||||||
di->VPUniforms.mProjectionMatrix = eye.GetProjection(fov, ratio, fovratio);
|
float inv_iso_dist = 1.0f;
|
||||||
|
bool iso_ortho = (camera->ViewPos != NULL) && (camera->ViewPos->Flags & VPSF_ORTHOGRAPHIC);
|
||||||
|
if (iso_ortho && (camera->ViewPos->Offset.Length() > 0)) inv_iso_dist = 1.0/camera->ViewPos->Offset.Length();
|
||||||
|
di->VPUniforms.mProjectionMatrix = eye.GetProjection(fov, ratio, fovratio * inv_iso_dist, iso_ortho);
|
||||||
|
|
||||||
// Stereo mode specific viewpoint adjustment
|
// Stereo mode specific viewpoint adjustment
|
||||||
vp.Pos += eye.GetViewShift(vp.HWAngles.Yaw.Degrees());
|
vp.Pos += eye.GetViewShift(vp.HWAngles.Yaw.Degrees());
|
||||||
di->SetupView(RenderState, vp.Pos.X, vp.Pos.Y, vp.Pos.Z, false, false);
|
di->SetupView(RenderState, vp.Pos.X, vp.Pos.Y, vp.Pos.Z, false, false);
|
||||||
|
|
|
@ -51,6 +51,8 @@
|
||||||
CVAR(Bool, gl_multithread, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
|
CVAR(Bool, gl_multithread, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
|
||||||
|
|
||||||
EXTERN_CVAR(Float, r_actorspriteshadowdist)
|
EXTERN_CVAR(Float, r_actorspriteshadowdist)
|
||||||
|
EXTERN_CVAR(Bool, r_radarclipper)
|
||||||
|
EXTERN_CVAR(Bool, r_dithertransparency)
|
||||||
|
|
||||||
thread_local bool isWorkerThread;
|
thread_local bool isWorkerThread;
|
||||||
ctpl::thread_pool renderPool(1);
|
ctpl::thread_pool renderPool(1);
|
||||||
|
@ -269,6 +271,20 @@ void HWDrawInfo::AddLine (seg_t *seg, bool portalclip)
|
||||||
auto &clipper = *mClipper;
|
auto &clipper = *mClipper;
|
||||||
angle_t startAngle = clipper.GetClipAngle(seg->v2);
|
angle_t startAngle = clipper.GetClipAngle(seg->v2);
|
||||||
angle_t endAngle = clipper.GetClipAngle(seg->v1);
|
angle_t endAngle = clipper.GetClipAngle(seg->v1);
|
||||||
|
auto &clipperr = *rClipper;
|
||||||
|
angle_t startAngleR = clipperr.PointToPseudoAngle(seg->v2->fX(), seg->v2->fY());
|
||||||
|
angle_t endAngleR = clipperr.PointToPseudoAngle(seg->v1->fX(), seg->v1->fY());
|
||||||
|
|
||||||
|
if(r_radarclipper && !(Level->flags3 & LEVEL3_NOFOGOFWAR) && (startAngleR - endAngleR >= ANGLE_180))
|
||||||
|
{
|
||||||
|
if (!seg->backsector) clipperr.SafeAddClipRange(startAngleR, endAngleR);
|
||||||
|
else if((seg->sidedef != nullptr) && !uint8_t(seg->sidedef->Flags & WALLF_POLYOBJ) && (currentsector->sectornum != seg->backsector->sectornum))
|
||||||
|
{
|
||||||
|
if (in_area == area_default) in_area = hw_CheckViewArea(seg->v2, seg->v1, seg->frontsector, seg->backsector);
|
||||||
|
backsector = hw_FakeFlat(seg->backsector, in_area, true);
|
||||||
|
if (hw_CheckClip(seg->sidedef, currentsector, backsector)) clipperr.SafeAddClipRange(startAngleR, endAngleR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Back side, i.e. backface culling - read: endAngle >= startAngle!
|
// Back side, i.e. backface culling - read: endAngle >= startAngle!
|
||||||
if (startAngle-endAngle<ANGLE_180)
|
if (startAngle-endAngle<ANGLE_180)
|
||||||
|
@ -280,25 +296,53 @@ void HWDrawInfo::AddLine (seg_t *seg, bool portalclip)
|
||||||
{
|
{
|
||||||
if (!(currentsubsector->flags & SSECMF_DRAWN))
|
if (!(currentsubsector->flags & SSECMF_DRAWN))
|
||||||
{
|
{
|
||||||
if (clipper.SafeCheckRange(startAngle, endAngle))
|
if (clipper.SafeCheckRange(startAngle, endAngle) && (!r_radarclipper || (Level->flags3 & LEVEL3_NOFOGOFWAR)))
|
||||||
{
|
{
|
||||||
currentsubsector->flags |= SSECMF_DRAWN;
|
currentsubsector->flags |= SSECMF_DRAWN;
|
||||||
|
}
|
||||||
|
if ((r_radarclipper || !(Level->flags3 & LEVEL3_NOFOGOFWAR)) && clipperr.SafeCheckRange(startAngleR, endAngleR))
|
||||||
|
{
|
||||||
|
currentsubsector->flags |= SSECMF_DRAWN;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!clipper.SafeCheckRange(startAngle, endAngle))
|
if (!clipper.SafeCheckRange(startAngle, endAngle))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
currentsubsector->flags |= SSECMF_DRAWN;
|
|
||||||
|
auto &clipperv = *vClipper;
|
||||||
|
angle_t startPitch = clipperv.PointToPseudoPitch(seg->v1->fX(), seg->v1->fY(), currentsector->floorplane.ZatPoint(seg->v1));
|
||||||
|
angle_t endPitch = clipperv.PointToPseudoPitch(seg->v1->fX(), seg->v1->fY(), currentsector->ceilingplane.ZatPoint(seg->v1));
|
||||||
|
angle_t startPitch2 = clipperv.PointToPseudoPitch(seg->v2->fX(), seg->v2->fY(), currentsector->floorplane.ZatPoint(seg->v2));
|
||||||
|
angle_t endPitch2 = clipperv.PointToPseudoPitch(seg->v2->fX(), seg->v2->fY(), currentsector->ceilingplane.ZatPoint(seg->v2));
|
||||||
|
angle_t temp;
|
||||||
|
// Wall can be tilted from viewpoint perspective. Find vertical extent on screen in psuedopitch units (0 to 2, bottom to top)
|
||||||
|
if(int(startPitch) > int(startPitch2)) // Handle zero crossing
|
||||||
|
{
|
||||||
|
temp = startPitch; startPitch = startPitch2; startPitch2 = temp; // exchange
|
||||||
|
}
|
||||||
|
if(int(endPitch) > int(endPitch2)) // Handle zero crossing
|
||||||
|
{
|
||||||
|
temp = endPitch; endPitch = endPitch2; endPitch2 = temp; // exchange
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!clipperv.SafeCheckRange(startPitch, endPitch2))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!r_radarclipper || (Level->flags3 & LEVEL3_NOFOGOFWAR) || clipperr.SafeCheckRange(startAngleR, endAngleR))
|
||||||
|
currentsubsector->flags |= SSECMF_DRAWN;
|
||||||
|
|
||||||
uint8_t ispoly = uint8_t(seg->sidedef->Flags & WALLF_POLYOBJ);
|
uint8_t ispoly = uint8_t(seg->sidedef->Flags & WALLF_POLYOBJ);
|
||||||
|
|
||||||
if (!seg->backsector)
|
if (!seg->backsector)
|
||||||
{
|
{
|
||||||
clipper.SafeAddClipRange(startAngle, endAngle);
|
if(!((Viewpoint.camera->ViewPos != NULL) && (Viewpoint.camera->ViewPos->Flags & VPSF_ALLOWOUTOFBOUNDS)))
|
||||||
|
if (!(seg->sidedef->Flags & WALLF_DITHERTRANS)) clipper.SafeAddClipRange(startAngle, endAngle);
|
||||||
}
|
}
|
||||||
else if (!ispoly) // Two-sided polyobjects never obstruct the view
|
else if (!ispoly) // Two-sided polyobjects never obstruct the view
|
||||||
{
|
{
|
||||||
|
@ -325,7 +369,8 @@ void HWDrawInfo::AddLine (seg_t *seg, bool portalclip)
|
||||||
|
|
||||||
if (hw_CheckClip(seg->sidedef, currentsector, backsector))
|
if (hw_CheckClip(seg->sidedef, currentsector, backsector))
|
||||||
{
|
{
|
||||||
clipper.SafeAddClipRange(startAngle, endAngle);
|
if(!((Viewpoint.camera->ViewPos != NULL) && (Viewpoint.camera->ViewPos->Flags & VPSF_ALLOWOUTOFBOUNDS)))
|
||||||
|
if (!(seg->sidedef->Flags & WALLF_DITHERTRANS)) clipper.SafeAddClipRange(startAngle, endAngle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -533,6 +578,7 @@ void HWDrawInfo::RenderThings(subsector_t * sub, sector_t * sector)
|
||||||
if (thing->validcount == validcount) continue;
|
if (thing->validcount == validcount) continue;
|
||||||
thing->validcount = validcount;
|
thing->validcount = validcount;
|
||||||
|
|
||||||
|
if((Viewpoint.camera->ViewPos != NULL) && (Viewpoint.camera->ViewPos->Flags & VPSF_ALLOWOUTOFBOUNDS) && thing->Sector->isSecret() && thing->Sector->wasSecret() && !r_radarclipper) continue; // This covers things that are touching non-secret sectors
|
||||||
FIntCVar *cvar = thing->GetInfo()->distancecheck;
|
FIntCVar *cvar = thing->GetInfo()->distancecheck;
|
||||||
if (cvar != nullptr && *cvar >= 0)
|
if (cvar != nullptr && *cvar >= 0)
|
||||||
{
|
{
|
||||||
|
@ -666,6 +712,51 @@ void HWDrawInfo::DoSubsector(subsector_t * sub)
|
||||||
|
|
||||||
fakesector=hw_FakeFlat(sector, in_area, false);
|
fakesector=hw_FakeFlat(sector, in_area, false);
|
||||||
|
|
||||||
|
if((Viewpoint.camera->ViewPos != NULL) && (Viewpoint.camera->ViewPos->Flags & VPSF_ALLOWOUTOFBOUNDS) && sector->isSecret() && sector->wasSecret() && !r_radarclipper) return;
|
||||||
|
|
||||||
|
// cull everything if subsector outside vertical clipper
|
||||||
|
if (sub->polys == nullptr)
|
||||||
|
{
|
||||||
|
auto &clipper = *mClipper;
|
||||||
|
auto &clipperv = *vClipper;
|
||||||
|
auto &clipperr = *rClipper;
|
||||||
|
int count = sub->numlines;
|
||||||
|
seg_t * seg = sub->firstline;
|
||||||
|
bool anglevisible = false;
|
||||||
|
bool pitchvisible = false;
|
||||||
|
bool radarvisible = false;
|
||||||
|
angle_t pitchtemp;
|
||||||
|
angle_t pitchmin = ANGLE_90;
|
||||||
|
angle_t pitchmax = 0;
|
||||||
|
|
||||||
|
while (count--)
|
||||||
|
{
|
||||||
|
if((seg->v1 != nullptr) && (seg->v2 != nullptr))
|
||||||
|
{
|
||||||
|
angle_t startAngle = clipper.GetClipAngle(seg->v2);
|
||||||
|
angle_t endAngle = clipper.GetClipAngle(seg->v1);
|
||||||
|
if (startAngle-endAngle >= ANGLE_180) anglevisible |= clipper.SafeCheckRange(startAngle, endAngle);
|
||||||
|
angle_t startAngleR = clipperr.PointToPseudoAngle(seg->v2->fX(), seg->v2->fY());
|
||||||
|
angle_t endAngleR = clipperr.PointToPseudoAngle(seg->v1->fX(), seg->v1->fY());
|
||||||
|
if (startAngleR-endAngleR >= ANGLE_180)
|
||||||
|
radarvisible |= (clipperr.SafeCheckRange(startAngleR, endAngleR) || (Level->flags3 & LEVEL3_NOFOGOFWAR) || ((sub->flags & SSECMF_DRAWN) && !deathmatch));
|
||||||
|
pitchmin = clipperv.PointToPseudoPitch(seg->v1->fX(), seg->v1->fY(), sector->floorplane.ZatPoint(seg->v1));
|
||||||
|
pitchmax = clipperv.PointToPseudoPitch(seg->v1->fX(), seg->v1->fY(), sector->ceilingplane.ZatPoint(seg->v1));
|
||||||
|
pitchvisible |= clipperv.SafeCheckRange(pitchmin, pitchmax);
|
||||||
|
if (pitchvisible && anglevisible && radarvisible) break;
|
||||||
|
pitchtemp = clipperv.PointToPseudoPitch(seg->v2->fX(), seg->v2->fY(), sector->floorplane.ZatPoint(seg->v2));
|
||||||
|
if (int(pitchmin) > int(pitchtemp)) pitchmin = pitchtemp;
|
||||||
|
pitchtemp = clipperv.PointToPseudoPitch(seg->v2->fX(), seg->v2->fY(), sector->ceilingplane.ZatPoint(seg->v2));
|
||||||
|
if (int(pitchmax) < int(pitchtemp)) pitchmax = pitchtemp;
|
||||||
|
pitchvisible |= clipperv.SafeCheckRange(pitchmin, pitchmax);
|
||||||
|
if (pitchvisible && anglevisible && radarvisible) break;
|
||||||
|
}
|
||||||
|
seg++;
|
||||||
|
}
|
||||||
|
// Skip subsector if outside vertical or horizontal clippers or is in unexplored territory (fog of war)
|
||||||
|
if(!pitchvisible || !anglevisible || (!radarvisible && r_radarclipper)) return;
|
||||||
|
}
|
||||||
|
|
||||||
if (mClipPortal)
|
if (mClipPortal)
|
||||||
{
|
{
|
||||||
int clipres = mClipPortal->ClipSubsector(sub);
|
int clipres = mClipPortal->ClipSubsector(sub);
|
||||||
|
@ -712,7 +803,7 @@ void HWDrawInfo::DoSubsector(subsector_t * sub)
|
||||||
|
|
||||||
if (gl_render_things && (sector->touching_renderthings || sector->sectorportal_thinglist))
|
if (gl_render_things && (sector->touching_renderthings || sector->sectorportal_thinglist))
|
||||||
{
|
{
|
||||||
if (multithread)
|
if (multithread)
|
||||||
{
|
{
|
||||||
jobQueue.AddJob(RenderJob::SpriteJob, sub, nullptr);
|
jobQueue.AddJob(RenderJob::SpriteJob, sub, nullptr);
|
||||||
}
|
}
|
||||||
|
@ -723,6 +814,23 @@ void HWDrawInfo::DoSubsector(subsector_t * sub)
|
||||||
SetupSprite.Unclock();
|
SetupSprite.Unclock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (r_dithertransparency)
|
||||||
|
{
|
||||||
|
// [DVR] Not parallelizable due to line->validcount race coundition
|
||||||
|
for (auto p = sector->touching_renderthings; p != nullptr; p = p->m_snext)
|
||||||
|
{
|
||||||
|
auto thing = p->m_thing;
|
||||||
|
if (((thing->flags & MF_SHOOTABLE) && (thing->health > 0)) || (thing->flags & MF_MISSILE))
|
||||||
|
{
|
||||||
|
if ( P_CheckSight(players[consoleplayer].mo, thing, 0) )
|
||||||
|
{
|
||||||
|
SetDitherTransFlags(thing);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
validcount++; // [DVR] Need this since Trace() and P_CheckSight() get called
|
||||||
|
// and they set line->validcount = validcount, preventing lines from being processed.
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gl_render_flats)
|
if (gl_render_flats)
|
||||||
|
@ -843,6 +951,14 @@ void HWDrawInfo::RenderBSPNode (void *node)
|
||||||
if (!(no_renderflags[bsp->Index()] & SSRF_SEEN))
|
if (!(no_renderflags[bsp->Index()] & SSRF_SEEN))
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if ((Viewpoint.camera->ViewPos != NULL) && (Viewpoint.camera->ViewPos->Flags & VPSF_ORTHOGRAPHIC))
|
||||||
|
{
|
||||||
|
if (!vClipper->CheckBoxOrthoPitch(bsp->bbox[side]))
|
||||||
|
{
|
||||||
|
if (!(no_renderflags[bsp->Index()] & SSRF_SEEN))
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
node = bsp->children[side];
|
node = bsp->children[side];
|
||||||
}
|
}
|
||||||
|
@ -856,6 +972,19 @@ void HWDrawInfo::RenderBSP(void *node, bool drawpsprites)
|
||||||
// Give the DrawInfo the viewpoint in fixed point because that's what the nodes are.
|
// Give the DrawInfo the viewpoint in fixed point because that's what the nodes are.
|
||||||
viewx = FLOAT2FIXED(Viewpoint.Pos.X);
|
viewx = FLOAT2FIXED(Viewpoint.Pos.X);
|
||||||
viewy = FLOAT2FIXED(Viewpoint.Pos.Y);
|
viewy = FLOAT2FIXED(Viewpoint.Pos.Y);
|
||||||
|
if (r_radarclipper && !(Level->flags3 & LEVEL3_NOFOGOFWAR) && (Viewpoint.camera->ViewPos != NULL) && (Viewpoint.camera->ViewPos->Flags & (VPSF_ABSOLUTEOFFSET | VPSF_ALLOWOUTOFBOUNDS)))
|
||||||
|
{
|
||||||
|
if (Viewpoint.camera->tracer != NULL)
|
||||||
|
{
|
||||||
|
viewx = FLOAT2FIXED(Viewpoint.camera->tracer->X());
|
||||||
|
viewy = FLOAT2FIXED(Viewpoint.camera->tracer->Y());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
viewx = FLOAT2FIXED(Viewpoint.camera->X());
|
||||||
|
viewy = FLOAT2FIXED(Viewpoint.camera->Y());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
validcount++; // used for processing sidedefs only once by the renderer.
|
validcount++; // used for processing sidedefs only once by the renderer.
|
||||||
|
|
||||||
|
|
|
@ -193,7 +193,7 @@ void Clipper::AddClipRange(angle_t start, angle_t end)
|
||||||
|
|
||||||
if (node->end < end)
|
if (node->end < end)
|
||||||
{
|
{
|
||||||
node->end = end;
|
node->end = end; // [DVR] This never triggers because of previous while loop. Remove?
|
||||||
}
|
}
|
||||||
|
|
||||||
ClipNode *node2 = node->next;
|
ClipNode *node2 = node->next;
|
||||||
|
@ -361,6 +361,17 @@ angle_t Clipper::AngleToPseudo(angle_t ang)
|
||||||
return xs_Fix<30>::ToFix(result);
|
return xs_Fix<30>::ToFix(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
angle_t Clipper::PitchToPseudo(double ang)
|
||||||
|
{
|
||||||
|
return AngleToPseudo(DAngle::fromDeg(90.0-ang).BAMs()); // Pitch is positive when looking down
|
||||||
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
// ! Returns the pseudoangle between the line p1 to (infinity, p1.y) and the
|
// ! Returns the pseudoangle between the line p1 to (infinity, p1.y) and the
|
||||||
|
@ -378,11 +389,28 @@ angle_t Clipper::PointToPseudoAngle(double x, double y)
|
||||||
{
|
{
|
||||||
double vecx = x - viewpoint->Pos.X;
|
double vecx = x - viewpoint->Pos.X;
|
||||||
double vecy = y - viewpoint->Pos.Y;
|
double vecy = y - viewpoint->Pos.Y;
|
||||||
|
if ((viewpoint->camera != NULL) && amRadar)
|
||||||
|
{
|
||||||
|
if (viewpoint->camera->tracer != NULL)
|
||||||
|
{
|
||||||
|
vecx = x - viewpoint->camera->tracer->X();
|
||||||
|
vecy = y - viewpoint->camera->tracer->Y();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
vecx = x - viewpoint->camera->X();
|
||||||
|
vecy = y - viewpoint->camera->Y();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (vecx == 0 && vecy == 0)
|
if (vecx == 0 && vecy == 0)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
else if (!amRadar && (viewpoint->camera->ViewPos != NULL) && (viewpoint->camera->ViewPos->Flags & VPSF_ORTHOGRAPHIC))
|
||||||
|
{
|
||||||
|
return PointToPseudoOrthoAngle(x, y);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
double result = vecy / (fabs(vecx) + fabs(vecy));
|
double result = vecy / (fabs(vecx) + fabs(vecy));
|
||||||
|
@ -395,6 +423,78 @@ angle_t Clipper::PointToPseudoAngle(double x, double y)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
angle_t Clipper::PointToPseudoPitch(double x, double y, double z)
|
||||||
|
{
|
||||||
|
double vecx = x - viewpoint->Pos.X;
|
||||||
|
double vecy = y - viewpoint->Pos.Y;
|
||||||
|
double vecz = z - viewpoint->Pos.Z;
|
||||||
|
double result = 0;
|
||||||
|
|
||||||
|
if (vecx == 0 && vecy == 0 && vecz == 0)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else if ((viewpoint->camera->ViewPos != NULL) && (viewpoint->camera->ViewPos->Flags & VPSF_ORTHOGRAPHIC))
|
||||||
|
{
|
||||||
|
return PointToPseudoOrthoPitch(x, y, z);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
double result = vecz / (g_sqrt(vecx*vecx + vecy*vecy) + fabs(vecz)); // -ffast-math compile flag applies to this file, yes?
|
||||||
|
if ((vecx * viewpoint->TanCos + vecy * viewpoint->TanSin) <= 0.0) // Point is behind viewpoint
|
||||||
|
{
|
||||||
|
result = 2.0 - result;
|
||||||
|
}
|
||||||
|
return xs_Fix<30>::ToFix(result + 1.0); // range to 0 to 2 to 4 (bottom to top to suplex)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
angle_t Clipper::PointToPseudoOrthoAngle(double x, double y)
|
||||||
|
{
|
||||||
|
DVector3 disp = DVector3( x, y, 0 ) - viewpoint->camera->Pos();
|
||||||
|
if (viewpoint->camera->ViewPos->Offset.XY().Length() == 0)
|
||||||
|
{
|
||||||
|
return AngleToPseudo( viewpoint->Angles.Yaw.BAMs() );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
angle_t af = viewpoint->FrustAngle;
|
||||||
|
double xproj = disp.XY().Length() * deltaangle(disp.Angle(), viewpoint->Angles.Yaw).Sin();
|
||||||
|
xproj *= viewpoint->ScreenProj;
|
||||||
|
if (fabs(xproj) < 2.0)
|
||||||
|
{
|
||||||
|
return AngleToPseudo( viewpoint->Angles.Yaw.BAMs() - xproj * 0.5 * af );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return (xproj > 0.0 ? AngleToPseudo( viewpoint->Angles.Yaw.BAMs() - af ) : AngleToPseudo( viewpoint->Angles.Yaw.BAMs() + af ));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
angle_t Clipper::PointToPseudoOrthoPitch(double x, double y, double z)
|
||||||
|
{
|
||||||
|
DVector3 disp = DVector3( x, y, z ) - viewpoint->camera->Pos();
|
||||||
|
if (viewpoint->camera->ViewPos->Offset.XY().Length() > 0)
|
||||||
|
{
|
||||||
|
double yproj = viewpoint->PitchSin * disp.XY().Length() * deltaangle(disp.Angle(), viewpoint->Angles.Yaw).Cos();
|
||||||
|
yproj += viewpoint->PitchCos * disp.Z;
|
||||||
|
yproj *= viewpoint->ScreenProj;
|
||||||
|
if (fabs(yproj) <= 1.5)
|
||||||
|
{
|
||||||
|
return PitchToPseudo(viewpoint->Angles.Pitch.Degrees() - yproj * 0.5 * viewpoint->FieldOfView.Degrees() );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
double a2 = 0.75*viewpoint->FieldOfView.Degrees();
|
||||||
|
a2 *= ( yproj > 0.0 ? -1.0 : 1.0 );
|
||||||
|
return PitchToPseudo(viewpoint->Angles.Pitch.Degrees() + a2 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else return PitchToPseudo(viewpoint->Angles.Pitch.Degrees());
|
||||||
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
|
@ -421,7 +521,7 @@ angle_t Clipper::PointToPseudoAngle(double x, double y)
|
||||||
|
|
||||||
bool Clipper::CheckBox(const float *bspcoord)
|
bool Clipper::CheckBox(const float *bspcoord)
|
||||||
{
|
{
|
||||||
angle_t angle1, angle2;
|
angle_t angle1, angle2;
|
||||||
|
|
||||||
int boxpos;
|
int boxpos;
|
||||||
const uint8_t* check;
|
const uint8_t* check;
|
||||||
|
@ -437,7 +537,47 @@ bool Clipper::CheckBox(const float *bspcoord)
|
||||||
check = checkcoord[boxpos];
|
check = checkcoord[boxpos];
|
||||||
angle1 = PointToPseudoAngle (bspcoord[check[0]], bspcoord[check[1]]);
|
angle1 = PointToPseudoAngle (bspcoord[check[0]], bspcoord[check[1]]);
|
||||||
angle2 = PointToPseudoAngle (bspcoord[check[2]], bspcoord[check[3]]);
|
angle2 = PointToPseudoAngle (bspcoord[check[2]], bspcoord[check[3]]);
|
||||||
|
|
||||||
|
if ((vp->camera->ViewPos != NULL) && (vp->camera->ViewPos->Flags & VPSF_ORTHOGRAPHIC))
|
||||||
|
{
|
||||||
|
if (angle2 != angle1) return true;
|
||||||
|
switch (boxpos) // Check if the closer corner is poking into the view area
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
case 10:
|
||||||
|
if ( angle1 != PointToPseudoAngle (bspcoord[check[2]], bspcoord[check[1]]) ) return true;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
case 8:
|
||||||
|
if ( angle1 != PointToPseudoAngle (bspcoord[check[0]], bspcoord[check[3]]) ) return true;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return SafeCheckRange(angle2, angle1);
|
return SafeCheckRange(angle2, angle1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Clipper::CheckBoxOrthoPitch(const float *bspcoord)
|
||||||
|
{
|
||||||
|
angle_t pitchmin, pitchmax;
|
||||||
|
auto &vp = viewpoint;
|
||||||
|
if (!((vp->camera->ViewPos != NULL) && (vp->camera->ViewPos->Flags & VPSF_ORTHOGRAPHIC))) return true;
|
||||||
|
|
||||||
|
angle_t pitchtemp;
|
||||||
|
double padding = 1.0/viewpoint->ScreenProj/viewpoint->PitchCos;
|
||||||
|
double camz = vp->camera->Pos().Z - padding;
|
||||||
|
pitchmin = PointToPseudoPitch (bspcoord[BOXLEFT], bspcoord[BOXTOP], camz);
|
||||||
|
pitchmax = PointToPseudoPitch (bspcoord[BOXLEFT], bspcoord[BOXTOP], camz + 2.0*padding);
|
||||||
|
for (int yi = BOXTOP; yi <= BOXBOTTOM; yi++)
|
||||||
|
for (int xi = BOXLEFT; xi <= BOXRIGHT; xi++)
|
||||||
|
{
|
||||||
|
pitchtemp = PointToPseudoPitch (bspcoord[xi], bspcoord[yi], camz);
|
||||||
|
if (pitchmin - pitchtemp < ANGLE_180) pitchmin = pitchtemp;
|
||||||
|
pitchtemp = PointToPseudoPitch (bspcoord[xi], bspcoord[yi], camz + 2.0*padding);
|
||||||
|
if (pitchtemp - pitchmax < ANGLE_180) pitchmax = pitchtemp;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (pitchmax != pitchmin); // SafeCheckRange(pitchmin, pitchmax);
|
||||||
|
}
|
||||||
|
|
|
@ -33,6 +33,7 @@ class Clipper
|
||||||
bool blocked = false;
|
bool blocked = false;
|
||||||
|
|
||||||
static angle_t AngleToPseudo(angle_t ang);
|
static angle_t AngleToPseudo(angle_t ang);
|
||||||
|
static angle_t PitchToPseudo(double ang);
|
||||||
bool IsRangeVisible(angle_t startangle, angle_t endangle);
|
bool IsRangeVisible(angle_t startangle, angle_t endangle);
|
||||||
void RemoveRange(ClipNode * cn);
|
void RemoveRange(ClipNode * cn);
|
||||||
void AddClipRange(angle_t startangle, angle_t endangle);
|
void AddClipRange(angle_t startangle, angle_t endangle);
|
||||||
|
@ -41,6 +42,7 @@ class Clipper
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
bool amRadar = false;
|
||||||
Clipper();
|
Clipper();
|
||||||
|
|
||||||
void Clear();
|
void Clear();
|
||||||
|
@ -116,6 +118,10 @@ public:
|
||||||
SafeAddClipRange(AngleToPseudo(startangle), AngleToPseudo(endangle));
|
SafeAddClipRange(AngleToPseudo(startangle), AngleToPseudo(endangle));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SafeAddClipRangeDegPitches(double startpitch, double endpitch)
|
||||||
|
{
|
||||||
|
SafeAddClipRange(PitchToPseudo(startpitch), PitchToPseudo(endpitch));
|
||||||
|
}
|
||||||
|
|
||||||
void SafeRemoveClipRange(angle_t startangle, angle_t endangle)
|
void SafeRemoveClipRange(angle_t startangle, angle_t endangle)
|
||||||
{
|
{
|
||||||
|
@ -148,8 +154,12 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
angle_t PointToPseudoAngle(double x, double y);
|
angle_t PointToPseudoAngle(double x, double y);
|
||||||
|
angle_t PointToPseudoPitch(double x, double y, double z);
|
||||||
|
angle_t PointToPseudoOrthoAngle(double x, double y);
|
||||||
|
angle_t PointToPseudoOrthoPitch(double x, double y, double z);
|
||||||
|
|
||||||
bool CheckBox(const float *bspcoord);
|
bool CheckBox(const float *bspcoord);
|
||||||
|
bool CheckBoxOrthoPitch(const float *bspcoord);
|
||||||
|
|
||||||
// Used to speed up angle calculations during clipping
|
// Used to speed up angle calculations during clipping
|
||||||
inline angle_t GetClipAngle(vertex_t *v)
|
inline angle_t GetClipAngle(vertex_t *v)
|
||||||
|
|
|
@ -131,12 +131,19 @@ HWDrawInfo *HWDrawInfo::StartDrawInfo(FLevelLocals *lev, HWDrawInfo *parent, FRe
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
static Clipper staticClipper; // Since all scenes are processed sequentially we only need one clipper.
|
static Clipper staticClipper; // Since all scenes are processed sequentially we only need one clipper.
|
||||||
|
static Clipper staticVClipper; // Another clipper to clip vertically (used if (VPSF_ALLOWOUTOFBOUNDS & camera->viewpos->Flags)).
|
||||||
|
static Clipper staticRClipper; // Another clipper for radar (doesn't actually clip. Changes SSECMF_DRAWN setting).
|
||||||
static HWDrawInfo * gl_drawinfo; // This is a linked list of all active DrawInfos and needed to free the memory arena after the last one goes out of scope.
|
static HWDrawInfo * gl_drawinfo; // This is a linked list of all active DrawInfos and needed to free the memory arena after the last one goes out of scope.
|
||||||
|
|
||||||
void HWDrawInfo::StartScene(FRenderViewpoint &parentvp, HWViewpointUniforms *uniforms)
|
void HWDrawInfo::StartScene(FRenderViewpoint &parentvp, HWViewpointUniforms *uniforms)
|
||||||
{
|
{
|
||||||
staticClipper.Clear();
|
staticClipper.Clear();
|
||||||
|
staticVClipper.Clear();
|
||||||
|
staticRClipper.Clear();
|
||||||
mClipper = &staticClipper;
|
mClipper = &staticClipper;
|
||||||
|
vClipper = &staticVClipper;
|
||||||
|
rClipper = &staticRClipper;
|
||||||
|
rClipper->amRadar = true;
|
||||||
|
|
||||||
Viewpoint = parentvp;
|
Viewpoint = parentvp;
|
||||||
lightmode = getRealLightmode(Level, true);
|
lightmode = getRealLightmode(Level, true);
|
||||||
|
@ -169,6 +176,8 @@ void HWDrawInfo::StartScene(FRenderViewpoint &parentvp, HWViewpointUniforms *uni
|
||||||
VPUniforms.mLightBlendMode = (level.info ? (int)level.info->lightblendmode : 0);
|
VPUniforms.mLightBlendMode = (level.info ? (int)level.info->lightblendmode : 0);
|
||||||
}
|
}
|
||||||
mClipper->SetViewpoint(Viewpoint);
|
mClipper->SetViewpoint(Viewpoint);
|
||||||
|
vClipper->SetViewpoint(Viewpoint);
|
||||||
|
rClipper->SetViewpoint(Viewpoint);
|
||||||
|
|
||||||
ClearBuffers();
|
ClearBuffers();
|
||||||
|
|
||||||
|
@ -257,7 +266,9 @@ void HWDrawInfo::ClearBuffers()
|
||||||
|
|
||||||
void HWDrawInfo::UpdateCurrentMapSection()
|
void HWDrawInfo::UpdateCurrentMapSection()
|
||||||
{
|
{
|
||||||
const int mapsection = Level->PointInRenderSubsector(Viewpoint.Pos)->mapsection;
|
int mapsection = Level->PointInRenderSubsector(Viewpoint.Pos)->mapsection;
|
||||||
|
if ((Viewpoint.camera->ViewPos != NULL) && (Viewpoint.camera->ViewPos->Flags & VPSF_ALLOWOUTOFBOUNDS))
|
||||||
|
mapsection = Level->PointInRenderSubsector(Viewpoint.camera->Pos())->mapsection;
|
||||||
CurrentMapSections.Set(mapsection);
|
CurrentMapSections.Set(mapsection);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -273,6 +284,8 @@ void HWDrawInfo::SetViewArea()
|
||||||
auto &vp = Viewpoint;
|
auto &vp = Viewpoint;
|
||||||
// The render_sector is better suited to represent the current position in GL
|
// The render_sector is better suited to represent the current position in GL
|
||||||
vp.sector = Level->PointInRenderSubsector(vp.Pos)->render_sector;
|
vp.sector = Level->PointInRenderSubsector(vp.Pos)->render_sector;
|
||||||
|
if ((vp.camera->ViewPos != NULL) && (vp.camera->ViewPos->Flags & VPSF_ALLOWOUTOFBOUNDS))
|
||||||
|
vp.sector = Level->PointInRenderSubsector(vp.camera->Pos())->render_sector;
|
||||||
|
|
||||||
// Get the heightsec state from the render sector, not the current one!
|
// Get the heightsec state from the render sector, not the current one!
|
||||||
if (vp.sector->GetHeightSec())
|
if (vp.sector->GetHeightSec())
|
||||||
|
@ -351,16 +364,14 @@ int HWDrawInfo::SetFullbrightFlags(player_t *player)
|
||||||
|
|
||||||
angle_t HWDrawInfo::FrustumAngle()
|
angle_t HWDrawInfo::FrustumAngle()
|
||||||
{
|
{
|
||||||
float tilt = fabs(Viewpoint.HWAngles.Pitch.Degrees());
|
// If pitch is larger than this you can look all around at an FOV of 90 degrees
|
||||||
|
if (fabs(Viewpoint.HWAngles.Pitch.Degrees()) > 89.0) return 0xffffffff;
|
||||||
|
|
||||||
// If the pitch is larger than this you can look all around at a FOV of 90°
|
double xratio = r_viewwindow.FocalTangent / Viewpoint.PitchCos;
|
||||||
if (tilt > 46.0f) return 0xffffffff;
|
double floatangle = 0.035 + atan ( xratio ) * 48.0 / AspectMultiplier(r_viewwindow.WidescreenRatio); // this is radians
|
||||||
|
angle_t a1 = DAngle::fromRad(floatangle).BAMs();
|
||||||
|
|
||||||
// ok, this is a gross hack that barely works...
|
if (a1 >= ANGLE_90) return 0xffffffff;
|
||||||
// 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::fromDeg(floatangle).BAMs();
|
|
||||||
if (a1 >= ANGLE_180) return 0xffffffff;
|
|
||||||
return a1;
|
return a1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -438,8 +449,12 @@ HWDecal *HWDrawInfo::AddDecal(bool onmirror)
|
||||||
void HWDrawInfo::CreateScene(bool drawpsprites)
|
void HWDrawInfo::CreateScene(bool drawpsprites)
|
||||||
{
|
{
|
||||||
const auto &vp = Viewpoint;
|
const auto &vp = Viewpoint;
|
||||||
angle_t a1 = FrustumAngle();
|
angle_t a1 = FrustumAngle(); // horizontally clip the back of the viewport
|
||||||
mClipper->SafeAddClipRangeRealAngles(vp.Angles.Yaw.BAMs() + a1, vp.Angles.Yaw.BAMs() - a1);
|
mClipper->SafeAddClipRangeRealAngles(vp.Angles.Yaw.BAMs() + a1, vp.Angles.Yaw.BAMs() - a1);
|
||||||
|
Viewpoint.FrustAngle = a1;
|
||||||
|
double a2 = 20.0 + 0.5*Viewpoint.FieldOfView.Degrees(); // FrustumPitch for vertical clipping
|
||||||
|
if (a2 > 179.0) a2 = 179.0;
|
||||||
|
vClipper->SafeAddClipRangeDegPitches(vp.HWAngles.Pitch.Degrees() - a2, vp.HWAngles.Pitch.Degrees() + a2); // clip the suplex range
|
||||||
|
|
||||||
// reset the portal manager
|
// reset the portal manager
|
||||||
portalState.StartFrame();
|
portalState.StartFrame();
|
||||||
|
@ -648,6 +663,79 @@ void HWDrawInfo::DrawCorona(FRenderState& state, ACorona* corona, double dist)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// TraceCallbackForDitherTransparency
|
||||||
|
// Toggles dither flag on anything that occludes the actor's
|
||||||
|
// position from viewpoint.
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
static ETraceStatus TraceCallbackForDitherTransparency(FTraceResults& res, void* userdata)
|
||||||
|
{
|
||||||
|
int* count = (int*)userdata;
|
||||||
|
double bf, bc;
|
||||||
|
(*count)++;
|
||||||
|
switch(res.HitType)
|
||||||
|
{
|
||||||
|
case TRACE_HitWall:
|
||||||
|
if (!(res.Line->sidedef[res.Side]->Flags & WALLF_DITHERTRANS))
|
||||||
|
{
|
||||||
|
bf = res.Line->sidedef[res.Side]->sector->floorplane.ZatPoint(res.HitPos.XY());
|
||||||
|
bc = res.Line->sidedef[res.Side]->sector->ceilingplane.ZatPoint(res.HitPos.XY());
|
||||||
|
if ((res.HitPos.Z <= bc) && (res.HitPos.Z >= bf)) res.Line->sidedef[res.Side]->Flags |= WALLF_DITHERTRANS;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case TRACE_HitFloor:
|
||||||
|
res.Sector->floorplane.dithertransflag = true;
|
||||||
|
break;
|
||||||
|
case TRACE_HitCeiling:
|
||||||
|
res.Sector->ceilingplane.dithertransflag = true;
|
||||||
|
break;
|
||||||
|
case TRACE_HitActor:
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRACE_ContinueOutOfBounds;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void HWDrawInfo::SetDitherTransFlags(AActor* actor)
|
||||||
|
{
|
||||||
|
if (actor && actor->Sector)
|
||||||
|
{
|
||||||
|
FTraceResults results;
|
||||||
|
double horix = Viewpoint.Sin * actor->radius;
|
||||||
|
double horiy = Viewpoint.Cos * actor->radius;
|
||||||
|
DVector3 actorpos = actor->Pos();
|
||||||
|
DVector3 vvec = actorpos - Viewpoint.Pos;
|
||||||
|
if (Viewpoint.camera->ViewPos && (Viewpoint.camera->ViewPos->Flags & VPSF_ORTHOGRAPHIC))
|
||||||
|
{
|
||||||
|
vvec += Viewpoint.camera->Pos() - actorpos;
|
||||||
|
vvec *= 5.0; // Should be 4.0? (since zNear is behind screen by 3*dist in VREyeInfo::GetProjection())
|
||||||
|
}
|
||||||
|
double distance = vvec.Length() - actor->radius;
|
||||||
|
DVector3 campos = actorpos - vvec;
|
||||||
|
sector_t* startsec;
|
||||||
|
int count = 0;
|
||||||
|
|
||||||
|
vvec = vvec.Unit();
|
||||||
|
campos.X -= horix; campos.Y += horiy; campos.Z += actor->Height * 0.25;
|
||||||
|
for (int iter = 0; iter < 3; iter++)
|
||||||
|
{
|
||||||
|
startsec = Level->PointInRenderSubsector(campos)->sector;
|
||||||
|
Trace(campos, startsec, vvec, distance,
|
||||||
|
MF_SOLID, ML_BLOCKEVERYTHING, actor, results, 0, TraceCallbackForDitherTransparency, &count);
|
||||||
|
campos.Z += actor->Height * 0.5;
|
||||||
|
Trace(campos, startsec, vvec, distance,
|
||||||
|
MF_SOLID, ML_BLOCKEVERYTHING, actor, results, 0, TraceCallbackForDitherTransparency, &count);
|
||||||
|
campos.Z -= actor->Height * 0.5;
|
||||||
|
campos.X += horix; campos.Y -= horiy;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static ETraceStatus CheckForViewpointActor(FTraceResults& res, void* userdata)
|
static ETraceStatus CheckForViewpointActor(FTraceResults& res, void* userdata)
|
||||||
{
|
{
|
||||||
FRenderViewpoint* data = (FRenderViewpoint*)userdata;
|
FRenderViewpoint* data = (FRenderViewpoint*)userdata;
|
||||||
|
@ -810,6 +898,10 @@ void HWDrawInfo::DrawScene(int drawmode)
|
||||||
{
|
{
|
||||||
ssao_portals_available = gl_ssao_portals;
|
ssao_portals_available = gl_ssao_portals;
|
||||||
applySSAO = true;
|
applySSAO = true;
|
||||||
|
if (r_dithertransparency)
|
||||||
|
{
|
||||||
|
vp.camera->tracer ? SetDitherTransFlags(vp.camera->tracer) : SetDitherTransFlags(players[consoleplayer].mo);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (drawmode == DM_OFFSCREEN)
|
else if (drawmode == DM_OFFSCREEN)
|
||||||
{
|
{
|
||||||
|
@ -864,6 +956,8 @@ void HWDrawInfo::ProcessScene(bool toscreen)
|
||||||
portalState.BeginScene();
|
portalState.BeginScene();
|
||||||
|
|
||||||
int mapsection = Level->PointInRenderSubsector(Viewpoint.Pos)->mapsection;
|
int mapsection = Level->PointInRenderSubsector(Viewpoint.Pos)->mapsection;
|
||||||
|
if ((Viewpoint.camera->ViewPos != NULL) && (Viewpoint.camera->ViewPos->Flags & VPSF_ALLOWOUTOFBOUNDS))
|
||||||
|
mapsection = Level->PointInRenderSubsector(Viewpoint.camera->Pos())->mapsection;
|
||||||
CurrentMapSections.Set(mapsection);
|
CurrentMapSections.Set(mapsection);
|
||||||
DrawScene(toscreen ? DM_MAINVIEW : DM_OFFSCREEN);
|
DrawScene(toscreen ? DM_MAINVIEW : DM_OFFSCREEN);
|
||||||
|
|
||||||
|
|
|
@ -146,6 +146,8 @@ struct HWDrawInfo
|
||||||
HWPortal *mCurrentPortal;
|
HWPortal *mCurrentPortal;
|
||||||
//FRotator mAngles;
|
//FRotator mAngles;
|
||||||
Clipper *mClipper;
|
Clipper *mClipper;
|
||||||
|
Clipper *vClipper; // Vertical clipper
|
||||||
|
Clipper *rClipper; // Radar clipper
|
||||||
FRenderViewpoint Viewpoint;
|
FRenderViewpoint Viewpoint;
|
||||||
HWViewpointUniforms VPUniforms; // per-viewpoint uniform state
|
HWViewpointUniforms VPUniforms; // per-viewpoint uniform state
|
||||||
TArray<HWPortal *> Portals;
|
TArray<HWPortal *> Portals;
|
||||||
|
@ -302,6 +304,8 @@ public:
|
||||||
void DrawCoronas(FRenderState& state);
|
void DrawCoronas(FRenderState& state);
|
||||||
void DrawCorona(FRenderState& state, ACorona* corona, double dist);
|
void DrawCorona(FRenderState& state, ACorona* corona, double dist);
|
||||||
|
|
||||||
|
void SetDitherTransFlags(AActor* actor);
|
||||||
|
|
||||||
void ProcessLowerMinisegs(TArray<seg_t *> &lowersegs);
|
void ProcessLowerMinisegs(TArray<seg_t *> &lowersegs);
|
||||||
void AddSubsectorToPortal(FSectorPortalGroup *portal, subsector_t *sub);
|
void AddSubsectorToPortal(FSectorPortalGroup *portal, subsector_t *sub);
|
||||||
|
|
||||||
|
|
|
@ -320,7 +320,7 @@ void HWFlat::DrawFlat(HWDrawInfo *di, FRenderState &state, bool translucent)
|
||||||
state.SetObjectColor(FlatColor | 0xff000000);
|
state.SetObjectColor(FlatColor | 0xff000000);
|
||||||
state.SetAddColor(AddColor | 0xff000000);
|
state.SetAddColor(AddColor | 0xff000000);
|
||||||
state.ApplyTextureManipulation(TextureFx);
|
state.ApplyTextureManipulation(TextureFx);
|
||||||
|
if (plane.plane.dithertransflag) state.SetEffect(EFF_DITHERTRANS);
|
||||||
|
|
||||||
if (hacktype & SSRF_PLANEHACK)
|
if (hacktype & SSRF_PLANEHACK)
|
||||||
{
|
{
|
||||||
|
@ -372,6 +372,7 @@ void HWFlat::DrawFlat(HWDrawInfo *di, FRenderState &state, bool translucent)
|
||||||
state.SetObjectColor(0xffffffff);
|
state.SetObjectColor(0xffffffff);
|
||||||
state.SetAddColor(0);
|
state.SetAddColor(0);
|
||||||
state.ApplyTextureManipulation(nullptr);
|
state.ApplyTextureManipulation(nullptr);
|
||||||
|
if (plane.plane.dithertransflag) state.SetEffect(EFF_NONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -408,6 +409,8 @@ inline void HWFlat::PutFlat(HWDrawInfo *di, bool fog)
|
||||||
void HWFlat::Process(HWDrawInfo *di, sector_t * model, int whichplane, bool fog)
|
void HWFlat::Process(HWDrawInfo *di, sector_t * model, int whichplane, bool fog)
|
||||||
{
|
{
|
||||||
plane.GetFromSector(model, whichplane);
|
plane.GetFromSector(model, whichplane);
|
||||||
|
model->ceilingplane.dithertransflag = false; // Resetting this every frame
|
||||||
|
model->floorplane.dithertransflag = false; // Resetting this every frame
|
||||||
if (whichplane != int(ceiling))
|
if (whichplane != int(ceiling))
|
||||||
{
|
{
|
||||||
// Flip the normal if the source plane has a different orientation than what we are about to render.
|
// Flip the normal if the source plane has a different orientation than what we are about to render.
|
||||||
|
@ -515,7 +518,7 @@ void HWFlat::ProcessSector(HWDrawInfo *di, sector_t * frontsector, int which)
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
if ((which & SSRF_RENDERFLOOR) && frontsector->floorplane.ZatPoint(vp.Pos) <= vp.Pos.Z && (!section || !(section->flags & FSection::DONTRENDERFLOOR)))
|
if (((which & SSRF_RENDERFLOOR) && frontsector->floorplane.ZatPoint(vp.Pos) <= vp.Pos.Z && (!section || !(section->flags & FSection::DONTRENDERFLOOR)))&& !((vp.camera->ViewPos != NULL) && (vp.camera->ViewPos->Flags & VPSF_ORTHOGRAPHIC) && (vp.PitchSin < 0.0)))
|
||||||
{
|
{
|
||||||
// process the original floor first.
|
// process the original floor first.
|
||||||
|
|
||||||
|
@ -573,7 +576,7 @@ void HWFlat::ProcessSector(HWDrawInfo *di, sector_t * frontsector, int which)
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
if ((which & SSRF_RENDERCEILING) && frontsector->ceilingplane.ZatPoint(vp.Pos) >= vp.Pos.Z && (!section || !(section->flags & FSection::DONTRENDERCEILING)))
|
if (((which & SSRF_RENDERCEILING) && frontsector->ceilingplane.ZatPoint(vp.Pos) >= vp.Pos.Z && (!section || !(section->flags & FSection::DONTRENDERCEILING))) && !((vp.camera->ViewPos != NULL) && (vp.camera->ViewPos->Flags & VPSF_ORTHOGRAPHIC) && (vp.PitchSin > 0.0)))
|
||||||
{
|
{
|
||||||
// process the original ceiling first.
|
// process the original ceiling first.
|
||||||
|
|
||||||
|
|
|
@ -563,7 +563,8 @@ bool HWMirrorPortal::Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *clippe
|
||||||
angle_t af = di->FrustumAngle();
|
angle_t af = di->FrustumAngle();
|
||||||
if (af < ANGLE_180) clipper->SafeAddClipRangeRealAngles(vp.Angles.Yaw.BAMs() + af, vp.Angles.Yaw.BAMs() - af);
|
if (af < ANGLE_180) clipper->SafeAddClipRangeRealAngles(vp.Angles.Yaw.BAMs() + af, vp.Angles.Yaw.BAMs() - af);
|
||||||
|
|
||||||
clipper->SafeAddClipRange(linedef->v1, linedef->v2);
|
if(!((di->Viewpoint.camera->ViewPos != NULL) && (di->Viewpoint.camera->ViewPos->Flags & VPSF_ALLOWOUTOFBOUNDS)))
|
||||||
|
clipper->SafeAddClipRange(linedef->v1, linedef->v2);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -130,6 +130,10 @@ void HWSkyInfo::init(HWDrawInfo *di, sector_t* sec, int skypos, int sky1, PalEnt
|
||||||
void HWWall::SkyPlane(HWWallDispatcher *di, sector_t *sector, int plane, bool allowreflect)
|
void HWWall::SkyPlane(HWWallDispatcher *di, sector_t *sector, int plane, bool allowreflect)
|
||||||
{
|
{
|
||||||
int ptype = -1;
|
int ptype = -1;
|
||||||
|
if(di->di->Viewpoint.camera != NULL && di->di->Viewpoint.camera->ViewPos != NULL)
|
||||||
|
{
|
||||||
|
if(di->di->Viewpoint.camera->ViewPos->Flags & VPSF_ALLOWOUTOFBOUNDS) return;
|
||||||
|
}
|
||||||
|
|
||||||
FSectorPortal *sportal = sector->ValidatePortal(plane);
|
FSectorPortal *sportal = sector->ValidatePortal(plane);
|
||||||
if (sportal != nullptr && sportal->mFlags & PORTSF_INSKYBOX) sportal = nullptr; // no recursions, delete it here to simplify the following code
|
if (sportal != nullptr && sportal->mFlags & PORTSF_INSKYBOX) sportal = nullptr; // no recursions, delete it here to simplify the following code
|
||||||
|
|
|
@ -489,7 +489,7 @@ bool HWSprite::CalculateVertices(HWDrawInfo* di, FVector3* v, DVector3* vp)
|
||||||
}
|
}
|
||||||
else // traditional "Y" billboard mode
|
else // traditional "Y" billboard mode
|
||||||
{
|
{
|
||||||
if (doRoll || !offset.isZero())
|
if (doRoll || !offset.isZero() || (actor && (actor->renderflags2 & RF2_ISOMETRICSPRITES)))
|
||||||
{
|
{
|
||||||
mat.MakeIdentity();
|
mat.MakeIdentity();
|
||||||
|
|
||||||
|
@ -509,6 +509,16 @@ bool HWSprite::CalculateVertices(HWDrawInfo* di, FVector3* v, DVector3* vp)
|
||||||
mat.Translate(-center.X, -center.Z, -center.Y);
|
mat.Translate(-center.X, -center.Z, -center.Y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (actor && (actor->renderflags2 & RF2_ISOMETRICSPRITES) && (di->Viewpoint.camera->ViewPos != NULL) && (di->Viewpoint.camera->ViewPos->Flags & VPSF_ORTHOGRAPHIC))
|
||||||
|
{
|
||||||
|
float angleRad = (FAngle::fromDeg(270.) - HWAngles.Yaw).Radians();
|
||||||
|
mat.Translate(center.X, center.Z, center.Y);
|
||||||
|
mat.Translate(0.0, z2 - center.Z, 0.0);
|
||||||
|
mat.Rotate(-sin(angleRad), 0, cos(angleRad), -actor->isotheta);
|
||||||
|
mat.Translate(0.0, center.Z - z2, 0.0);
|
||||||
|
mat.Translate(-center.X, -center.Z, -center.Y);
|
||||||
|
}
|
||||||
|
|
||||||
v[0] = mat * FVector3(x1, z1, y1);
|
v[0] = mat * FVector3(x1, z1, y1);
|
||||||
v[1] = mat * FVector3(x2, z1, y2);
|
v[1] = mat * FVector3(x2, z1, y2);
|
||||||
v[2] = mat * FVector3(x1, z2, y1);
|
v[2] = mat * FVector3(x1, z2, y1);
|
||||||
|
@ -902,6 +912,7 @@ void HWSprite::Process(HWDrawInfo *di, AActor* thing, sector_t * sector, area_t
|
||||||
{
|
{
|
||||||
bool mirror = false;
|
bool mirror = false;
|
||||||
DAngle ang = (thingpos - vp.Pos).Angle();
|
DAngle ang = (thingpos - vp.Pos).Angle();
|
||||||
|
if (thing->renderflags2 & RF2_ISOMETRICSPRITES) ang = vp.Angles.Yaw;
|
||||||
FTextureID patch;
|
FTextureID patch;
|
||||||
// [ZZ] add direct picnum override
|
// [ZZ] add direct picnum override
|
||||||
if (isPicnumOverride)
|
if (isPicnumOverride)
|
||||||
|
@ -995,14 +1006,32 @@ void HWSprite::Process(HWDrawInfo *di, AActor* thing, sector_t * sector, area_t
|
||||||
if (thing->renderflags & RF_SPRITEFLIP) // [SP] Flip back
|
if (thing->renderflags & RF_SPRITEFLIP) // [SP] Flip back
|
||||||
thing->renderflags ^= RF_XFLIP;
|
thing->renderflags ^= RF_XFLIP;
|
||||||
|
|
||||||
r.Scale(sprscale.X, isSpriteShadow ? sprscale.Y * 0.15 : sprscale.Y);
|
// If sprite is isometric, do both vertical scaling and partial rotation to face the camera to compensate for Y-billboarding.
|
||||||
|
// Using just rotation (about z=0) might cause tall+slender (high aspect ratio) sprites to clip out of collision box
|
||||||
|
// at the top and clip into whatever is behind them from the viewpoint's perspective. - [DVR]
|
||||||
|
thing->isoscaleY = 1.0;
|
||||||
|
thing->isotheta = vp.HWAngles.Pitch.Degrees();
|
||||||
|
if (thing->renderflags2 & RF2_ISOMETRICSPRITES)
|
||||||
|
{
|
||||||
|
float floordist = thing->radius * vp.floordistfact;
|
||||||
|
floordist -= 0.5 * r.width * vp.cotfloor;
|
||||||
|
float sineisotheta = floordist / r.height;
|
||||||
|
double scl = g_sqrt( 1.0 + sineisotheta * sineisotheta - 2.0 * vp.PitchSin * sineisotheta );
|
||||||
|
if ((thing->radius > 0.0) && (scl > fabs(vp.PitchCos)))
|
||||||
|
{
|
||||||
|
thing->isoscaleY = scl / ( fabs(vp.PitchCos) > 0.01 ? fabs(vp.PitchCos) : 0.01 );
|
||||||
|
thing->isotheta = 180.0 * asin( sineisotheta / thing->isoscaleY ) / M_PI;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
r.Scale(sprscale.X, isSpriteShadow ? sprscale.Y * 0.15 * thing->isoscaleY : sprscale.Y * thing->isoscaleY);
|
||||||
|
|
||||||
float rightfac = -r.left;
|
float rightfac = -r.left;
|
||||||
float leftfac = rightfac - r.width;
|
float leftfac = rightfac - r.width;
|
||||||
z1 = z - r.top;
|
z1 = z - r.top;
|
||||||
z2 = z1 - r.height;
|
z2 = z1 - r.height;
|
||||||
|
|
||||||
float spriteheight = sprscale.Y * r.height;
|
float spriteheight = sprscale.Y * r.height * thing->isoscaleY;
|
||||||
|
|
||||||
// Tests show that this doesn't look good for many decorations and corpses
|
// Tests show that this doesn't look good for many decorations and corpses
|
||||||
if (spriteheight > 0 && gl_spriteclip > 0 && (thing->renderflags & RF_SPRITETYPEMASK) == RF_FACESPRITE)
|
if (spriteheight > 0 && gl_spriteclip > 0 && (thing->renderflags & RF_SPRITETYPEMASK) == RF_FACESPRITE)
|
||||||
|
@ -1021,6 +1050,13 @@ void HWSprite::Process(HWDrawInfo *di, AActor* thing, sector_t * sector, area_t
|
||||||
x2 = x - viewvecY*rightfac;
|
x2 = x - viewvecY*rightfac;
|
||||||
y1 = y + viewvecX*leftfac;
|
y1 = y + viewvecX*leftfac;
|
||||||
y2 = y + viewvecX*rightfac;
|
y2 = y + viewvecX*rightfac;
|
||||||
|
if (thing->renderflags2 & RF2_ISOMETRICSPRITES) // If sprites are drawn from an isometric perspective
|
||||||
|
{
|
||||||
|
x1 -= viewvecX * thing->radius * M_SQRT2;
|
||||||
|
x2 -= viewvecX * thing->radius * M_SQRT2;
|
||||||
|
y1 -= viewvecY * thing->radius * M_SQRT2;
|
||||||
|
y2 -= viewvecY * thing->radius * M_SQRT2;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case RF_FLATSPRITE:
|
case RF_FLATSPRITE:
|
||||||
|
@ -1061,6 +1097,7 @@ void HWSprite::Process(HWDrawInfo *di, AActor* thing, sector_t * sector, area_t
|
||||||
}
|
}
|
||||||
|
|
||||||
depth = (float)((x - vp.Pos.X) * vp.TanCos + (y - vp.Pos.Y) * vp.TanSin);
|
depth = (float)((x - vp.Pos.X) * vp.TanCos + (y - vp.Pos.Y) * vp.TanSin);
|
||||||
|
if(thing->renderflags2 & RF2_ISOMETRICSPRITES) depth = depth * vp.PitchCos - vp.PitchSin * z2; // Helps with stacking actors with small xy offsets
|
||||||
if (isSpriteShadow) depth += 1.f/65536.f; // always sort shadows behind the sprite.
|
if (isSpriteShadow) depth += 1.f/65536.f; // always sort shadows behind the sprite.
|
||||||
|
|
||||||
// light calculation
|
// light calculation
|
||||||
|
|
|
@ -83,10 +83,16 @@ void SetSplitPlanes(FRenderState& state, const secplane_t& top, const secplane_t
|
||||||
|
|
||||||
void HWWall::RenderWall(FRenderState &state, int textured)
|
void HWWall::RenderWall(FRenderState &state, int textured)
|
||||||
{
|
{
|
||||||
|
if (seg->sidedef->Flags & WALLF_DITHERTRANS) state.SetEffect(EFF_DITHERTRANS);
|
||||||
assert(vertcount > 0);
|
assert(vertcount > 0);
|
||||||
state.SetLightIndex(dynlightindex);
|
state.SetLightIndex(dynlightindex);
|
||||||
state.Draw(DT_TriangleFan, vertindex, vertcount);
|
state.Draw(DT_TriangleFan, vertindex, vertcount);
|
||||||
vertexcount += vertcount;
|
vertexcount += vertcount;
|
||||||
|
if (seg->sidedef->Flags & WALLF_DITHERTRANS)
|
||||||
|
{
|
||||||
|
state.SetEffect(EFF_NONE);
|
||||||
|
seg->sidedef->Flags &= ~WALLF_DITHERTRANS; // reset this every frame
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -2175,6 +2181,8 @@ void HWWall::Process(HWWallDispatcher *di, seg_t *seg, sector_t * frontsector, s
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isportal = seg->linedef->isVisualPortal() && seg->sidedef == seg->linedef->sidedef[0];
|
bool isportal = seg->linedef->isVisualPortal() && seg->sidedef == seg->linedef->sidedef[0];
|
||||||
|
// Don't render portal insides if in orthographic mode
|
||||||
|
isportal &= !(di->di->Viewpoint.camera->ViewPos && (di->di->Viewpoint.camera->ViewPos->Flags & VPSF_ORTHOGRAPHIC));
|
||||||
|
|
||||||
//return;
|
//return;
|
||||||
// [GZ] 3D middle textures are necessarily two-sided, even if they lack the explicit two-sided flag
|
// [GZ] 3D middle textures are necessarily two-sided, even if they lack the explicit two-sided flag
|
||||||
|
|
|
@ -66,6 +66,7 @@
|
||||||
#include "i_system.h"
|
#include "i_system.h"
|
||||||
#include "v_draw.h"
|
#include "v_draw.h"
|
||||||
#include "i_interface.h"
|
#include "i_interface.h"
|
||||||
|
#include "d_main.h"
|
||||||
|
|
||||||
// EXTERNAL DATA DECLARATIONS ----------------------------------------------
|
// EXTERNAL DATA DECLARATIONS ----------------------------------------------
|
||||||
|
|
||||||
|
@ -103,6 +104,8 @@ CVAR (Bool, r_deathcamera, false, CVAR_ARCHIVE)
|
||||||
CVAR (Int, r_clearbuffer, 0, 0)
|
CVAR (Int, r_clearbuffer, 0, 0)
|
||||||
CVAR (Bool, r_drawvoxels, true, 0)
|
CVAR (Bool, r_drawvoxels, true, 0)
|
||||||
CVAR (Bool, r_drawplayersprites, true, 0) // [RH] Draw player sprites?
|
CVAR (Bool, r_drawplayersprites, true, 0) // [RH] Draw player sprites?
|
||||||
|
CVARD (Bool, r_radarclipper, false, CVAR_ARCHIVE | CVAR_SERVERINFO | CVAR_CHEAT, "Use the horizontal clipper from camera->tracer's perspective")
|
||||||
|
CVARD (Bool, r_dithertransparency, false, CVAR_ARCHIVE | CVAR_SERVERINFO | CVAR_CHEAT, "Use dithered-transparency shading for actor-occluding level geometry")
|
||||||
CUSTOM_CVAR(Float, r_quakeintensity, 1.0f, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
|
CUSTOM_CVAR(Float, r_quakeintensity, 1.0f, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
|
||||||
{
|
{
|
||||||
if (self < 0.f) self = 0.f;
|
if (self < 0.f) self = 0.f;
|
||||||
|
@ -155,9 +158,14 @@ FRenderViewpoint::FRenderViewpoint()
|
||||||
Sin = 0.0;
|
Sin = 0.0;
|
||||||
TanCos = 0.0;
|
TanCos = 0.0;
|
||||||
TanSin = 0.0;
|
TanSin = 0.0;
|
||||||
|
PitchCos = 0.0;
|
||||||
|
PitchSin = 0.0;
|
||||||
|
floordistfact = 0.0;
|
||||||
|
cotfloor = 0.0;
|
||||||
camera = nullptr;
|
camera = nullptr;
|
||||||
sector = nullptr;
|
sector = nullptr;
|
||||||
FieldOfView = DAngle::fromDeg(90.); // Angles in the SCREENWIDTH wide window
|
FieldOfView = DAngle::fromDeg(90.); // Angles in the SCREENWIDTH wide window
|
||||||
|
ScreenProj = 0.0;
|
||||||
TicFrac = 0.0;
|
TicFrac = 0.0;
|
||||||
FrameTime = 0;
|
FrameTime = 0;
|
||||||
extralight = 0;
|
extralight = 0;
|
||||||
|
@ -554,37 +562,40 @@ void R_InterpolateView(FRenderViewpoint& viewPoint, const player_t* const player
|
||||||
|
|
||||||
// Due to interpolation this is not necessarily the same as the sector the camera is in.
|
// Due to interpolation this is not necessarily the same as the sector the camera is in.
|
||||||
viewPoint.sector = viewLvl->PointInRenderSubsector(viewPoint.Pos)->sector;
|
viewPoint.sector = viewLvl->PointInRenderSubsector(viewPoint.Pos)->sector;
|
||||||
bool moved = false;
|
if (!viewPoint.camera->ViewPos || !(viewPoint.camera->ViewPos->Flags & VPSF_ALLOWOUTOFBOUNDS) || !V_IsHardwareRenderer())
|
||||||
while (!viewPoint.sector->PortalBlocksMovement(sector_t::ceiling))
|
|
||||||
{
|
{
|
||||||
if (viewPoint.Pos.Z > viewPoint.sector->GetPortalPlaneZ(sector_t::ceiling))
|
bool moved = false;
|
||||||
|
while (!viewPoint.sector->PortalBlocksMovement(sector_t::ceiling))
|
||||||
{
|
{
|
||||||
const DVector2 offset = viewPoint.sector->GetPortalDisplacement(sector_t::ceiling);
|
if (viewPoint.Pos.Z > viewPoint.sector->GetPortalPlaneZ(sector_t::ceiling))
|
||||||
viewPoint.Pos += offset;
|
|
||||||
viewPoint.ActorPos += offset;
|
|
||||||
viewPoint.sector = viewPoint.sector->GetPortal(sector_t::ceiling)->mDestination;
|
|
||||||
moved = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!moved)
|
|
||||||
{
|
|
||||||
while (!viewPoint.sector->PortalBlocksMovement(sector_t::floor))
|
|
||||||
{
|
|
||||||
if (viewPoint.Pos.Z < viewPoint.sector->GetPortalPlaneZ(sector_t::floor))
|
|
||||||
{
|
{
|
||||||
const DVector2 offset = viewPoint.sector->GetPortalDisplacement(sector_t::floor);
|
const DVector2 offset = viewPoint.sector->GetPortalDisplacement(sector_t::ceiling);
|
||||||
viewPoint.Pos += offset;
|
viewPoint.Pos += offset;
|
||||||
viewPoint.ActorPos += offset;
|
viewPoint.ActorPos += offset;
|
||||||
viewPoint.sector = viewPoint.sector->GetPortal(sector_t::floor)->mDestination;
|
viewPoint.sector = viewPoint.sector->GetPortal(sector_t::ceiling)->mDestination;
|
||||||
|
moved = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!moved)
|
||||||
|
{
|
||||||
|
while (!viewPoint.sector->PortalBlocksMovement(sector_t::floor))
|
||||||
|
{
|
||||||
|
if (viewPoint.Pos.Z < viewPoint.sector->GetPortalPlaneZ(sector_t::floor))
|
||||||
|
{
|
||||||
|
const DVector2 offset = viewPoint.sector->GetPortalDisplacement(sector_t::floor);
|
||||||
|
viewPoint.Pos += offset;
|
||||||
|
viewPoint.ActorPos += offset;
|
||||||
|
viewPoint.sector = viewPoint.sector->GetPortal(sector_t::floor)->mDestination;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -628,7 +639,7 @@ void R_InterpolateView(FRenderViewpoint& viewPoint, const player_t* const player
|
||||||
// Now that we have the current interpolated position, offset from that directly (for view offset + chase cam).
|
// Now that we have the current interpolated position, offset from that directly (for view offset + chase cam).
|
||||||
if (!posOfs.isZero())
|
if (!posOfs.isZero())
|
||||||
{
|
{
|
||||||
const double distance = posOfs.Length();
|
const double distance = posOfs.Length();
|
||||||
posOfs /= distance;
|
posOfs /= distance;
|
||||||
R_OffsetView(viewPoint, posOfs, distance);
|
R_OffsetView(viewPoint, posOfs, distance);
|
||||||
}
|
}
|
||||||
|
@ -682,10 +693,20 @@ void FRenderViewpoint::SetViewAngle(const FViewWindow& viewWindow)
|
||||||
TanSin = viewWindow.FocalTangent * Sin;
|
TanSin = viewWindow.FocalTangent * Sin;
|
||||||
TanCos = viewWindow.FocalTangent * Cos;
|
TanCos = viewWindow.FocalTangent * Cos;
|
||||||
|
|
||||||
|
PitchSin = Angles.Pitch.Sin();
|
||||||
|
PitchCos = Angles.Pitch.Cos();
|
||||||
|
|
||||||
|
floordistfact = M_SQRT2 + ( fabs(Cos) > fabs(Sin) ? 1.0/fabs(Cos) : 1.0/fabs(Sin) );
|
||||||
|
cotfloor = ( fabs(Cos) > fabs(Sin) ? fabs(Sin/Cos) : fabs(Cos/Sin) );
|
||||||
|
|
||||||
const DVector2 v = Angles.Yaw.ToVector();
|
const DVector2 v = Angles.Yaw.ToVector();
|
||||||
ViewVector.X = v.X;
|
ViewVector.X = v.X;
|
||||||
ViewVector.Y = v.Y;
|
ViewVector.Y = v.Y;
|
||||||
HWAngles.Yaw = FAngle::fromDeg(270.0 - Angles.Yaw.Degrees());
|
HWAngles.Yaw = FAngle::fromDeg(270.0 - Angles.Yaw.Degrees());
|
||||||
|
|
||||||
|
if ((camera->ViewPos != NULL) && (camera->ViewPos->Flags & VPSF_ORTHOGRAPHIC) && (camera->ViewPos->Offset.XY().Length() > 0.0))
|
||||||
|
ScreenProj = 1.34396 / camera->ViewPos->Offset.Length(); // [DVR] Estimated. +/-1 should be top/bottom of screen.
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -1019,14 +1040,17 @@ void R_SetupFrame(FRenderViewpoint& viewPoint, const FViewWindow& viewWindow, AA
|
||||||
viewPoint.SetViewAngle(viewWindow);
|
viewPoint.SetViewAngle(viewWindow);
|
||||||
|
|
||||||
// Keep the view within the sector's floor and ceiling
|
// Keep the view within the sector's floor and ceiling
|
||||||
if (viewPoint.sector->PortalBlocksMovement(sector_t::ceiling))
|
// But allow VPSF_ALLOWOUTOFBOUNDS camera viewpoints to go out of bounds when using hardware renderer
|
||||||
|
bool disembodied = false;
|
||||||
|
if (viewPoint.camera->ViewPos != NULL) disembodied = viewPoint.camera->ViewPos->Flags & VPSF_ALLOWOUTOFBOUNDS;
|
||||||
|
if (viewPoint.sector->PortalBlocksMovement(sector_t::ceiling) && (!disembodied || !V_IsHardwareRenderer()))
|
||||||
{
|
{
|
||||||
const double z = viewPoint.sector->ceilingplane.ZatPoint(viewPoint.Pos) - 4.0;
|
const double z = viewPoint.sector->ceilingplane.ZatPoint(viewPoint.Pos) - 4.0;
|
||||||
if (viewPoint.Pos.Z > z)
|
if (viewPoint.Pos.Z > z)
|
||||||
viewPoint.Pos.Z = z;
|
viewPoint.Pos.Z = z;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (viewPoint.sector->PortalBlocksMovement(sector_t::floor))
|
if (viewPoint.sector->PortalBlocksMovement(sector_t::floor) && (!disembodied || !V_IsHardwareRenderer()))
|
||||||
{
|
{
|
||||||
const double z = viewPoint.sector->floorplane.ZatPoint(viewPoint.Pos) + 4.0;
|
const double z = viewPoint.sector->floorplane.ZatPoint(viewPoint.Pos) + 4.0;
|
||||||
if (viewPoint.Pos.Z < z)
|
if (viewPoint.Pos.Z < z)
|
||||||
|
|
|
@ -33,10 +33,16 @@ struct FRenderViewpoint
|
||||||
double Sin; // sin(Angles.Yaw)
|
double Sin; // sin(Angles.Yaw)
|
||||||
double TanCos; // FocalTangent * cos(Angles.Yaw)
|
double TanCos; // FocalTangent * cos(Angles.Yaw)
|
||||||
double TanSin; // FocalTangent * sin(Angles.Yaw)
|
double TanSin; // FocalTangent * sin(Angles.Yaw)
|
||||||
|
double PitchCos; // cos(Angles.Pitch)
|
||||||
|
double PitchSin; // sin(Angles.Pitch)
|
||||||
|
double floordistfact; // used for isometric sprites Y-billboarding compensation in hw_sprites.cpp
|
||||||
|
double cotfloor; // used for isometric sprites Y-billboarding compensation in hw_sprites.cpp
|
||||||
|
angle_t FrustAngle; // FrustumAngle() result
|
||||||
|
|
||||||
AActor *camera; // camera actor
|
AActor *camera; // camera actor
|
||||||
sector_t *sector; // [RH] keep track of sector viewing from
|
sector_t *sector; // [RH] keep track of sector viewing from
|
||||||
DAngle FieldOfView; // current field of view
|
DAngle FieldOfView; // current field of view
|
||||||
|
double ScreenProj; // Screen projection factor for orthographic projection
|
||||||
|
|
||||||
double TicFrac; // fraction of tic for interpolation
|
double TicFrac; // fraction of tic for interpolation
|
||||||
uint32_t FrameTime; // current frame's time in tics.
|
uint32_t FrameTime; // current frame's time in tics.
|
||||||
|
|
|
@ -384,6 +384,7 @@ static FFlagDef ActorFlagDefs[]=
|
||||||
DEFINE_FLAG(RF2, FLIPSPRITEOFFSETX, AActor, renderflags2),
|
DEFINE_FLAG(RF2, FLIPSPRITEOFFSETX, AActor, renderflags2),
|
||||||
DEFINE_FLAG(RF2, FLIPSPRITEOFFSETY, AActor, renderflags2),
|
DEFINE_FLAG(RF2, FLIPSPRITEOFFSETY, AActor, renderflags2),
|
||||||
DEFINE_FLAG(RF2, CAMFOLLOWSPLAYER, AActor, renderflags2),
|
DEFINE_FLAG(RF2, CAMFOLLOWSPLAYER, AActor, renderflags2),
|
||||||
|
DEFINE_FLAG(RF2, ISOMETRICSPRITES, AActor, renderflags2),
|
||||||
|
|
||||||
// Bounce flags
|
// Bounce flags
|
||||||
DEFINE_FLAG2(BOUNCE_Walls, BOUNCEONWALLS, AActor, BounceFlags),
|
DEFINE_FLAG2(BOUNCE_Walls, BOUNCEONWALLS, AActor, BounceFlags),
|
||||||
|
|
|
@ -48,6 +48,23 @@ const int TEXF_Detailmap = 0x20000;
|
||||||
const int TEXF_Glowmap = 0x40000;
|
const int TEXF_Glowmap = 0x40000;
|
||||||
const int TEXF_ClampY = 0x80000;
|
const int TEXF_ClampY = 0x80000;
|
||||||
|
|
||||||
|
//===========================================================================
|
||||||
|
//
|
||||||
|
// RGB to HSV
|
||||||
|
//
|
||||||
|
//===========================================================================
|
||||||
|
|
||||||
|
vec3 rgb2hsv(vec3 c)
|
||||||
|
{
|
||||||
|
vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
|
||||||
|
vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));
|
||||||
|
vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));
|
||||||
|
|
||||||
|
float d = q.x - min(q.w, q.y);
|
||||||
|
float e = 1.0e-10;
|
||||||
|
return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);
|
||||||
|
}
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
//
|
//
|
||||||
// Color to grayscale
|
// Color to grayscale
|
||||||
|
@ -870,6 +887,27 @@ void main()
|
||||||
frag.rgb = frag.rgb + uFogColor.rgb;
|
frag.rgb = frag.rgb + uFogColor.rgb;
|
||||||
}
|
}
|
||||||
FragColor = frag;
|
FragColor = frag;
|
||||||
|
|
||||||
|
#ifdef DITHERTRANS
|
||||||
|
int index = (int(pixelpos.x) % 8) * 8 + int(pixelpos.y) % 8;
|
||||||
|
const float DITHER_THRESHOLDS[64] =
|
||||||
|
{
|
||||||
|
1.0 / 65.0, 33.0 / 65.0, 9.0 / 65.0, 41.0 / 65.0, 3.0 / 65.0, 35.0 / 65.0, 11.0 / 65.0, 43.0 / 65.0,
|
||||||
|
49.0 / 65.0, 17.0 / 65.0, 57.0 / 65.0, 25.0 / 65.0, 51.0 / 65.0, 19.0 / 65.0, 59.0 / 65.0, 27.0 / 65.0,
|
||||||
|
13.0 / 65.0, 45.0 / 65.0, 5.0 / 65.0, 37.0 / 65.0, 15.0 / 65.0, 47.0 / 65.0, 7.0 / 65.0, 39.0 / 65.0,
|
||||||
|
61.0 / 65.0, 29.0 / 65.0, 53.0 / 65.0, 21.0 / 65.0, 63.0 / 65.0, 31.0 / 65.0, 55.0 / 65.0, 23.0 / 65.0,
|
||||||
|
4.0 / 65.0, 36.0 / 65.0, 12.0 / 65.0, 44.0 / 65.0, 2.0 / 65.0, 34.0 / 65.0, 10.0 / 65.0, 42.0 / 65.0,
|
||||||
|
52.0 / 65.0, 20.0 / 65.0, 60.0 / 65.0, 28.0 / 65.0, 50.0 / 65.0, 18.0 / 65.0, 58.0 / 65.0, 26.0 / 65.0,
|
||||||
|
16.0 / 65.0, 48.0 / 65.0, 8.0 / 65.0, 40.0 / 65.0, 14.0 / 65.0, 46.0 / 65.0, 6.0 / 65.0, 38.0 / 65.0,
|
||||||
|
64.0 / 65.0, 32.0 / 65.0, 56.0 / 65.0, 24.0 / 65.0, 62.0 / 65.0, 30.0 / 65.0, 54.0 / 65.0, 22.0 /65.0
|
||||||
|
};
|
||||||
|
|
||||||
|
vec3 fragHSV = rgb2hsv(FragColor.rgb);
|
||||||
|
float brightness = clamp(1.5*fragHSV.z, 0.1, 1.0);
|
||||||
|
if (DITHER_THRESHOLDS[index] < brightness) discard;
|
||||||
|
else FragColor *= 0.5;
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef GBUFFER_PASS
|
#ifdef GBUFFER_PASS
|
||||||
FragFog = vec4(AmbientOcclusionColor(), 1.0);
|
FragFog = vec4(AmbientOcclusionColor(), 1.0);
|
||||||
FragNormal = vec4(vEyeNormal.xyz * 0.5 + 0.5, 1.0);
|
FragNormal = vec4(vEyeNormal.xyz * 0.5 + 0.5, 1.0);
|
||||||
|
|
|
@ -493,6 +493,11 @@ void main()
|
||||||
if (frag.a <= uAlphaThreshold) discard;
|
if (frag.a <= uAlphaThreshold) discard;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef DITHERTRANS
|
||||||
|
int index = (int(pixelpos.x) % 2) * 2 + int(pixelpos.y) % 2;
|
||||||
|
if (index != 2) discard;
|
||||||
|
#endif
|
||||||
|
|
||||||
#if (DEF_FOG_2D == 0) // check for special 2D 'fog' mode.
|
#if (DEF_FOG_2D == 0) // check for special 2D 'fog' mode.
|
||||||
{
|
{
|
||||||
float fogdist = 0.0;
|
float fogdist = 0.0;
|
||||||
|
|
|
@ -128,3 +128,87 @@ class AimingCamera : SecurityCamera
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class SpectatorCamera : Actor
|
||||||
|
{
|
||||||
|
|
||||||
|
bool chasingtracer;
|
||||||
|
double lagdistance; // camera gives chase (lazy follow) if tracer gets > lagdistance away from camera.pos
|
||||||
|
int chasemode; // 0: chase until tracer centered, 1: same but only when tracer is moving, 2: stop chase if tracer within lagdistance
|
||||||
|
property lagdistance : lagdistance;
|
||||||
|
property chasingtracer : chasingtracer;
|
||||||
|
property chasemode : chasemode;
|
||||||
|
|
||||||
|
default
|
||||||
|
{
|
||||||
|
+NOBLOCKMAP
|
||||||
|
+NOGRAVITY
|
||||||
|
+NOINTERACTION
|
||||||
|
RenderStyle "None";
|
||||||
|
CameraHeight 0;
|
||||||
|
SpectatorCamera.chasingtracer false;
|
||||||
|
SpectatorCamera.lagdistance 0.0;
|
||||||
|
SpectatorCamera.chasemode 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Init(double dist, double yaw, double inpitch, int inflags)
|
||||||
|
{
|
||||||
|
|
||||||
|
double zshift = 0.0;
|
||||||
|
if(tracer != NULL)
|
||||||
|
{
|
||||||
|
if(player != NULL) zshift = -0.5*tracer.height;
|
||||||
|
else zshift = 0.5*tracer.height;
|
||||||
|
}
|
||||||
|
else if (player != NULL && player.mo != NULL) zshift = -0.5*player.mo.height;
|
||||||
|
|
||||||
|
SetViewPos((-dist*Cos(yaw)*Cos(inpitch), -dist*Sin(yaw)*Cos(inpitch), dist*Sin(inpitch)+zshift), inflags);
|
||||||
|
LookAtSelf(inpitch);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LookAtSelf(double inpitch)
|
||||||
|
{
|
||||||
|
if(ViewPos.Offset != (0., 0., 0.))
|
||||||
|
{
|
||||||
|
Vector3 negviewpos = (-1.0) * ViewPos.Offset;
|
||||||
|
angle = negviewpos.Angle();
|
||||||
|
pitch = inpitch;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override void Tick()
|
||||||
|
{
|
||||||
|
if(tracer != NULL)
|
||||||
|
{
|
||||||
|
Vector3 distvec = tracer.pos - pos;
|
||||||
|
double dist = distvec.length();
|
||||||
|
if((dist <= 4 && chasingtracer) || lagdistance <= 0.0) // Keep tracer centered on screen
|
||||||
|
{
|
||||||
|
SetOrigin(tracer.pos, true);
|
||||||
|
chasingtracer = false;
|
||||||
|
}
|
||||||
|
else // Lazy follow tracer
|
||||||
|
{
|
||||||
|
if(dist >= 2*lagdistance)
|
||||||
|
{
|
||||||
|
SetOrigin(tracer.pos, true);
|
||||||
|
chasingtracer = false;
|
||||||
|
}
|
||||||
|
else if(dist > lagdistance && !chasingtracer) chasingtracer = true;
|
||||||
|
|
||||||
|
if(chasingtracer)
|
||||||
|
{
|
||||||
|
speed = tracer.vel.xy.length()/dist;
|
||||||
|
if((speed == 0.0) && (chasemode == 0)) speed = tracer.speed/dist;
|
||||||
|
SetOrigin(pos + 2*distvec*speed, true);
|
||||||
|
if(chasemode > 1) chasingtracer = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(player != NULL && player.mo != NULL)
|
||||||
|
{
|
||||||
|
cameraFOV = player.FOV;
|
||||||
|
SetOrigin(player.mo.pos, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -422,6 +422,8 @@ enum EViewPosFlags
|
||||||
{
|
{
|
||||||
VPSF_ABSOLUTEOFFSET = 1 << 1, // Don't include angles.
|
VPSF_ABSOLUTEOFFSET = 1 << 1, // Don't include angles.
|
||||||
VPSF_ABSOLUTEPOS = 1 << 2, // Use absolute position.
|
VPSF_ABSOLUTEPOS = 1 << 2, // Use absolute position.
|
||||||
|
VPSF_ALLOWOUTOFBOUNDS = 1 << 3, // Allow viewpoint to go out of bounds (hardware renderer only).
|
||||||
|
VPSF_ORTHOGRAPHIC = 1 << 4, // Use orthographic projection (hardware renderer only).
|
||||||
};
|
};
|
||||||
|
|
||||||
// Flags for A_TakeInventory and A_TakeFromTarget
|
// Flags for A_TakeInventory and A_TakeFromTarget
|
||||||
|
@ -1495,4 +1497,4 @@ enum EModelFlags
|
||||||
MDL_MODELSAREATTACHMENTS = 1<<12, // any model index after 0 is treated as an attachment, and therefore will use the bone results of index 0
|
MDL_MODELSAREATTACHMENTS = 1<<12, // any model index after 0 is treated as an attachment, and therefore will use the bone results of index 0
|
||||||
MDL_CORRECTPIXELSTRETCH = 1<<13, // ensure model does not distort with pixel stretch when pitch/roll is applied
|
MDL_CORRECTPIXELSTRETCH = 1<<13, // ensure model does not distort with pixel stretch when pitch/roll is applied
|
||||||
MDL_FORCECULLBACKFACES = 1<<14,
|
MDL_FORCECULLBACKFACES = 1<<14,
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue