Add portal plane clipping

This commit is contained in:
Magnus Norddahl 2016-11-26 09:01:58 +01:00
parent 70181f4146
commit 8bbb63e913
6 changed files with 39 additions and 8 deletions

View file

@ -44,7 +44,7 @@ void RenderPolyScene::Render()
ClearBuffers(); ClearBuffers();
SetSceneViewport(); SetSceneViewport();
SetupPerspectiveMatrix(); SetupPerspectiveMatrix();
MainPortal.SetViewpoint(WorldToClip, GetNextStencilValue()); MainPortal.SetViewpoint(WorldToClip, Vec4f(0.0f), GetNextStencilValue());
MainPortal.Render(0); MainPortal.Render(0);
Skydome.Render(WorldToClip); Skydome.Render(WorldToClip);
MainPortal.RenderTranslucent(0); MainPortal.RenderTranslucent(0);

View file

@ -28,11 +28,12 @@
#include "r_poly_cull.h" #include "r_poly_cull.h"
#include "r_poly.h" #include "r_poly.h"
void PolyCull::CullScene(const TriMatrix &worldToClip) void PolyCull::CullScene(const TriMatrix &worldToClip, const Vec4f &portalClipPlane)
{ {
ClearSolidSegments(); ClearSolidSegments();
PvsSectors.clear(); PvsSectors.clear();
frustumPlanes = FrustumPlanes(worldToClip); frustumPlanes = FrustumPlanes(worldToClip);
PortalClipPlane = portalClipPlane;
// Cull front to back // Cull front to back
MaxCeilingHeight = 0.0; MaxCeilingHeight = 0.0;
@ -174,6 +175,11 @@ bool PolyCull::CheckBBox(float *bspcoord)
if (result == IntersectionTest::outside) if (result == IntersectionTest::outside)
return false; return false;
// Skip if its in front of the portal:
if (PortalClipPlane != Vec4f(0.0f) && IntersectionTest::plane_aabb(PortalClipPlane, aabb) == IntersectionTest::outside)
return false;
// Occlusion test using solid segments: // Occlusion test using solid segments:
static const int lines[4][4] = static const int lines[4][4] =
@ -219,6 +225,10 @@ bool PolyCull::GetSegmentRangeForLine(double x1, double y1, double x2, double y2
{ {
double znear = 5.0; double znear = 5.0;
// Cull if entirely behind the portal clip plane (tbd: should we clip the segment?)
if (Vec4f::dot(PortalClipPlane, Vec4f((float)x1, (float)y1, 0.0f, 1.0f)) < 0.0f && Vec4f::dot(PortalClipPlane, Vec4f((float)x2, (float)y2, 0.0f, 1.0f)) < 0.0f)
return false;
// Transform to 2D view space: // Transform to 2D view space:
x1 = x1 - ViewPos.X; x1 = x1 - ViewPos.X;
y1 = y1 - ViewPos.Y; y1 = y1 - ViewPos.Y;

View file

@ -28,7 +28,7 @@
class PolyCull class PolyCull
{ {
public: public:
void CullScene(const TriMatrix &worldToClip); void CullScene(const TriMatrix &worldToClip, const Vec4f &portalClipPlane);
bool GetSegmentRangeForLine(double x1, double y1, double x2, double y2, int &sx1, int &sx2) const; bool GetSegmentRangeForLine(double x1, double y1, double x2, double y2, int &sx1, int &sx2) const;
void MarkSegmentCulled(int x1, int x2); void MarkSegmentCulled(int x1, int x2);
@ -59,4 +59,5 @@ private:
const int SolidCullScale = 3000; const int SolidCullScale = 3000;
FrustumPlanes frustumPlanes; FrustumPlanes frustumPlanes;
Vec4f PortalClipPlane;
}; };

View file

@ -26,6 +26,8 @@
#include <algorithm> #include <algorithm>
#include <cmath> #include <cmath>
class Vec3f;
class Vec4f class Vec4f
{ {
public: public:
@ -33,6 +35,7 @@ public:
Vec4f(const Vec4f &) = default; Vec4f(const Vec4f &) = default;
Vec4f(float x, float y, float z, float w) : x(x), y(y), z(z), w(w) { } Vec4f(float x, float y, float z, float w) : x(x), y(y), z(z), w(w) { }
Vec4f(float v) : x(v), y(v), z(v), w(v) { } Vec4f(float v) : x(v), y(v), z(v), w(v) { }
Vec4f(const Vec3f &xyz, float w);
static float dot(const Vec4f &a, const Vec4f &b) { return a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w; } static float dot(const Vec4f &a, const Vec4f &b) { return a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w; }
static float dot3(const Vec4f &a, const Vec4f &b) { return a.x * b.x + a.y * b.y + a.z * b.z; } static float dot3(const Vec4f &a, const Vec4f &b) { return a.x * b.x + a.y * b.y + a.z * b.z; }
@ -51,6 +54,9 @@ public:
float x, y, z, w; float x, y, z, w;
}; };
inline bool operator==(const Vec4f &a, const Vec4f &b) { return a.x == b.x && a.y == b.y && a.z == b.z && a.w == b.w; }
inline bool operator!=(const Vec4f &a, const Vec4f &b) { return a.x != b.x || a.y != b.y || a.z != b.z || a.w == b.w; }
class Vec3f class Vec3f
{ {
public: public:
@ -75,6 +81,9 @@ public:
float x, y, z; float x, y, z;
}; };
inline bool operator==(const Vec3f &a, const Vec3f &b) { return a.x == b.x && a.y == b.y && a.z == b.z; }
inline bool operator!=(const Vec3f &a, const Vec3f &b) { return a.x != b.x || a.y != b.y || a.z != b.z; }
inline Vec3f operator+(const Vec3f &a, const Vec3f &b) { return Vec3f(a.x + b.x, a.y + b.y, a.z + b.z); } inline Vec3f operator+(const Vec3f &a, const Vec3f &b) { return Vec3f(a.x + b.x, a.y + b.y, a.z + b.z); }
inline Vec3f operator-(const Vec3f &a, const Vec3f &b) { return Vec3f(a.x - b.x, a.y - b.y, a.z - b.z); } inline Vec3f operator-(const Vec3f &a, const Vec3f &b) { return Vec3f(a.x - b.x, a.y - b.y, a.z - b.z); }
inline Vec3f operator*(const Vec3f &a, const Vec3f &b) { return Vec3f(a.x * b.x, a.y * b.y, a.z * b.z); } inline Vec3f operator*(const Vec3f &a, const Vec3f &b) { return Vec3f(a.x * b.x, a.y * b.y, a.z * b.z); }
@ -90,6 +99,8 @@ inline Vec3f operator-(float a, const Vec3f &b) { return Vec3f(a - b.x, a - b.y,
inline Vec3f operator*(float a, const Vec3f &b) { return Vec3f(a * b.x, a * b.y, a * b.z); } inline Vec3f operator*(float a, const Vec3f &b) { return Vec3f(a * b.x, a * b.y, a * b.z); }
inline Vec3f operator/(float a, const Vec3f &b) { return Vec3f(a / b.x, a / b.y, a / b.z); } inline Vec3f operator/(float a, const Vec3f &b) { return Vec3f(a / b.x, a / b.y, a / b.z); }
inline Vec4f::Vec4f(const Vec3f &xyz, float w) : x(xyz.x), y(xyz.y), z(xyz.z), w(w) { }
typedef TriMatrix Mat4f; typedef TriMatrix Mat4f;
class AxisAlignedBoundingBox class AxisAlignedBoundingBox

View file

@ -45,16 +45,17 @@ RenderPolyPortal::~RenderPolyPortal()
{ {
} }
void RenderPolyPortal::SetViewpoint(const TriMatrix &worldToClip, uint32_t stencilValue) void RenderPolyPortal::SetViewpoint(const TriMatrix &worldToClip, const Vec4f &portalPlane, uint32_t stencilValue)
{ {
WorldToClip = worldToClip; WorldToClip = worldToClip;
StencilValue = stencilValue; StencilValue = stencilValue;
PortalPlane = portalPlane;
} }
void RenderPolyPortal::Render(int portalDepth) void RenderPolyPortal::Render(int portalDepth)
{ {
ClearBuffers(); ClearBuffers();
Cull.CullScene(WorldToClip); Cull.CullScene(WorldToClip, PortalPlane);
RenderSectors(); RenderSectors();
RenderPortals(portalDepth); RenderPortals(portalDepth);
} }
@ -340,7 +341,7 @@ void PolyDrawSectorPortal::Render(int portalDepth)
TriMatrix::translate((float)-ViewPos.X, (float)-ViewPos.Y, (float)-ViewPos.Z); TriMatrix::translate((float)-ViewPos.X, (float)-ViewPos.Y, (float)-ViewPos.Z);
TriMatrix worldToClip = TriMatrix::perspective(fovy, ratio, 5.0f, 65535.0f) * worldToView; TriMatrix worldToClip = TriMatrix::perspective(fovy, ratio, 5.0f, 65535.0f) * worldToView;
RenderPortal.SetViewpoint(worldToClip, StencilValue); RenderPortal.SetViewpoint(worldToClip, Vec4f(0.0f), StencilValue);
RenderPortal.Render(portalDepth); RenderPortal.Render(portalDepth);
RestoreGlobals(); RestoreGlobals();
@ -440,7 +441,14 @@ void PolyDrawLinePortal::Render(int portalDepth)
TriMatrix::translate((float)-ViewPos.X, (float)-ViewPos.Y, (float)-ViewPos.Z); TriMatrix::translate((float)-ViewPos.X, (float)-ViewPos.Y, (float)-ViewPos.Z);
TriMatrix worldToClip = TriMatrix::perspective(fovy, ratio, 5.0f, 65535.0f) * worldToView; TriMatrix worldToClip = TriMatrix::perspective(fovy, ratio, 5.0f, 65535.0f) * worldToView;
RenderPortal.SetViewpoint(worldToClip, StencilValue); // Calculate plane clipping
DVector2 planePos = Portal->mDestination->v1->fPos();
DVector2 planeNormal = (Portal->mDestination->v2->fPos() - Portal->mDestination->v1->fPos()).Rotated90CW();
planeNormal.MakeUnit();
double planeD = -(planeNormal | (planePos + planeNormal * 5.0));
Vec4f portalPlane((float)planeNormal.X, (float)planeNormal.Y, 0.0f, (float)planeD);
RenderPortal.SetViewpoint(worldToClip, portalPlane, StencilValue);
RenderPortal.Render(portalDepth); RenderPortal.Render(portalDepth);
RestoreGlobals(); RestoreGlobals();

View file

@ -83,7 +83,7 @@ class RenderPolyPortal
public: public:
RenderPolyPortal(); RenderPolyPortal();
~RenderPolyPortal(); ~RenderPolyPortal();
void SetViewpoint(const TriMatrix &worldToClip, uint32_t stencilValue); void SetViewpoint(const TriMatrix &worldToClip, const Vec4f &portalPlane, uint32_t stencilValue);
void Render(int portalDepth); void Render(int portalDepth);
void RenderTranslucent(int portalDepth); void RenderTranslucent(int portalDepth);
@ -99,6 +99,7 @@ private:
SpriteRange GetSpritesForSector(sector_t *sector); SpriteRange GetSpritesForSector(sector_t *sector);
TriMatrix WorldToClip; TriMatrix WorldToClip;
Vec4f PortalPlane;
uint32_t StencilValue = 0; uint32_t StencilValue = 0;
PolyCull Cull; PolyCull Cull;
uint32_t NextSubsectorDepth = 0; uint32_t NextSubsectorDepth = 0;