- went back to the original portal stencil setup from 3.4.0.

The main reason is to unify the portal hierarchy again. The split into a hardware independent and a hardware dependent part turned out to be unnecessary and complicated matters.
Another issue was that the new stencil setup code was having a few subtle problems, so this recreates the original ones with indirect API calls.
This commit is contained in:
Christoph Oelckers 2018-11-14 20:59:24 +01:00
parent 8429fc8124
commit a23d1c2d25
10 changed files with 156 additions and 144 deletions

View file

@ -436,22 +436,29 @@ void FGLRenderState::SetDepthRange(float min, float max)
glDepthRange(min, max); glDepthRange(min, max);
} }
void FGLRenderState::SetColorMask(bool r, bool g, bool b, bool a)
{
glColorMask(r, g, b, a);
}
void FGLRenderState::EnableDrawBufferAttachments(bool on) void FGLRenderState::EnableDrawBufferAttachments(bool on)
{ {
EnableDrawBuffers(on ? GetPassDrawBufferCount() : 1); EnableDrawBuffers(on ? GetPassDrawBufferCount() : 1);
} }
void FGLRenderState::SetStencil(int offs, int op, int flags) void FGLRenderState::SetStencil(int offs, int op, int flags = -1)
{ {
static int op2gl[] = { GL_KEEP, GL_INCR, GL_DECR }; static int op2gl[] = { GL_KEEP, GL_INCR, GL_DECR };
glStencilFunc(GL_EQUAL, screen->stencilValue + offs, ~0); // draw sky into stencil glStencilFunc(GL_EQUAL, screen->stencilValue + offs, ~0); // draw sky into stencil
glStencilOp(GL_KEEP, GL_KEEP, op2gl[op]); // this stage doesn't modify the stencil glStencilOp(GL_KEEP, GL_KEEP, op2gl[op]); // this stage doesn't modify the stencil
bool cmon = !(flags & SF_ColorMaskOff); if (flags != -1)
bool cmalpha = cmon || (flags & SF_ColorMaskAlpha); {
glColorMask(cmon, cmon, cmon, cmalpha); // don't write to the graphics buffer bool cmon = !(flags & SF_ColorMaskOff);
glDepthMask(!(flags & SF_DepthMaskOff)); glColorMask(cmon, cmon, cmon, cmon); // don't write to the graphics buffer
glDepthMask(!(flags & SF_DepthMaskOff));
}
} }
void FGLRenderState::ToggleState(int state, bool on) void FGLRenderState::ToggleState(int state, bool on)

View file

@ -153,6 +153,7 @@ public:
void SetDepthMask(bool on) override; void SetDepthMask(bool on) override;
void SetDepthFunc(int func) override; void SetDepthFunc(int func) override;
void SetDepthRange(float min, float max) override; void SetDepthRange(float min, float max) override;
void SetColorMask(bool r, bool g, bool b, bool a) override;
void EnableDrawBufferAttachments(bool on) override; void EnableDrawBufferAttachments(bool on) override;
void SetStencil(int offs, int op, int flags) override; void SetStencil(int offs, int op, int flags) override;
void SetCulling(int mode) override; void SetCulling(int mode) override;

View file

@ -667,10 +667,10 @@ void HWDrawInfo::AddSubsectorToPortal(FSectorPortalGroup *ptg, subsector_t *sub)
auto portal = FindPortal(ptg); auto portal = FindPortal(ptg);
if (!portal) if (!portal)
{ {
portal = new HWScenePortal(screen->mPortalState, new HWSectorStackPortal(ptg)); portal = new HWSectorStackPortal(screen->mPortalState, ptg);
Portals.Push(portal); Portals.Push(portal);
} }
auto ptl = static_cast<HWSectorStackPortal*>(static_cast<HWScenePortal*>(portal)->mScene); auto ptl = static_cast<HWSectorStackPortal*>(portal);
ptl->AddSubsector(sub); ptl->AddSubsector(sub);
} }

View file

@ -144,7 +144,7 @@ struct HWDrawInfo
HWDrawInfo * outer = nullptr; HWDrawInfo * outer = nullptr;
int FullbrightFlags; int FullbrightFlags;
std::atomic<int> spriteindex; std::atomic<int> spriteindex;
HWScenePortalBase *mClipPortal; HWPortal *mClipPortal;
HWPortal *mCurrentPortal; HWPortal *mCurrentPortal;
//FRotator mAngles; //FRotator mAngles;
Clipper *mClipper; Clipper *mClipper;

View file

@ -26,7 +26,6 @@
*/ */
#include "c_dispatch.h" #include "c_dispatch.h"
#include "portal.h"
#include "p_maputl.h" #include "p_maputl.h"
#include "hw_portal.h" #include "hw_portal.h"
#include "hw_clipper.h" #include "hw_clipper.h"
@ -172,13 +171,14 @@ void HWPortal::DrawPortalStencil(FRenderState &state, int pass)
if (mPrimIndices.Size() == 0) if (mPrimIndices.Size() == 0)
{ {
mPrimIndices.Resize(2 * lines.Size()); mPrimIndices.Resize(2 * lines.Size());
for (unsigned int i = 0; i < lines.Size(); i++) for (unsigned int i = 0; i < lines.Size(); i++)
{ {
mPrimIndices[i * 2] = lines[i].vertindex; mPrimIndices[i * 2] = lines[i].vertindex;
mPrimIndices[i * 2 + 1] = lines[i].vertcount; mPrimIndices[i * 2 + 1] = lines[i].vertcount;
} }
} }
for (unsigned int i = 0; i < mPrimIndices.Size(); i += 2) for (unsigned int i = 0; i < mPrimIndices.Size(); i += 2)
{ {
state.Draw(DT_TriangleFan, mPrimIndices[i], mPrimIndices[i + 1], i == 0); state.Draw(DT_TriangleFan, mPrimIndices[i], mPrimIndices[i + 1], i == 0);
@ -187,12 +187,13 @@ void HWPortal::DrawPortalStencil(FRenderState &state, int pass)
{ {
// The cap's depth handling needs special treatment so that it won't block further portal caps. // The cap's depth handling needs special treatment so that it won't block further portal caps.
if (pass == STP_DepthRestore) state.SetDepthRange(1, 1); if (pass == STP_DepthRestore) state.SetDepthRange(1, 1);
state.Draw(DT_TriangleFan, FFlatVertexBuffer::STENCILTOP_INDEX, 4); state.Draw(DT_TriangleFan, FFlatVertexBuffer::STENCILTOP_INDEX, 4, false);
state.Draw(DT_TriangleFan, FFlatVertexBuffer::STENCILBOTTOM_INDEX, 4); state.Draw(DT_TriangleFan, FFlatVertexBuffer::STENCILBOTTOM_INDEX, 4, false);
if (pass == STP_DepthRestore) state.SetDepthRange(0, 1); if (pass == STP_DepthRestore) state.SetDepthRange(0, 1);
} }
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// //
// Start // Start
@ -204,53 +205,60 @@ void HWPortal::SetupStencil(HWDrawInfo *di, FRenderState &state, bool usestencil
Clocker c(PortalAll); Clocker c(PortalAll);
rendered_portals++; rendered_portals++;
if (usestencil) if (usestencil)
{ {
// Create stencil // Create stencil
state.SetStencil(0, SOP_Increment); // create stencil, increment stencil of valid pixels
state.SetColorMask(false);
state.SetEffect(EFF_STENCIL); state.SetEffect(EFF_STENCIL);
state.EnableTexture(false); state.EnableTexture(false);
state.ResetColor(); state.ResetColor();
state.SetDepthFunc(DF_Less);
if (NeedDepthBuffer()) if (NeedDepthBuffer())
{ {
state.SetStencil(0, SOP_Increment, SF_ColorMaskOff | SF_DepthMaskOff); state.SetDepthMask(false); // don't write to Z-buffer!
state.SetDepthFunc(DF_Less);
DrawPortalStencil(state, STP_Stencil); DrawPortalStencil(state, STP_Stencil);
// Clear Z-buffer // Clear Z-buffer
state.SetStencil(1, SOP_Keep, SF_ColorMaskOff); state.SetStencil(1, SOP_Keep); // draw sky into stencil. This stage doesn't modify the stencil.
state.SetDepthMask(true); // enable z-buffer again
state.SetDepthRange(1, 1); state.SetDepthRange(1, 1);
state.SetDepthFunc(DF_Always); state.SetDepthFunc(DF_Always);
DrawPortalStencil(state, STP_DepthClear); DrawPortalStencil(state, STP_DepthClear);
// set normal drawing mode // set normal drawing mode
state.EnableTexture(true); state.EnableTexture(true);
state.SetStencil(1, SOP_Keep, SF_AllOn);
state.SetDepthRange(0, 1); state.SetDepthRange(0, 1);
state.SetDepthFunc(DF_Less); state.SetDepthFunc(DF_Less);
state.SetColorMask(true);
state.SetEffect(EFF_NONE); state.SetEffect(EFF_NONE);
} }
else else
{ {
// No z-buffer is needed therefore we can skip all the complicated stuff that is involved // No z-buffer is needed therefore we can skip all the complicated stuff that is involved
// Note: We must draw the stencil with z-write enabled here because there is no second pass! // Note: We must draw the stencil with z-write enabled here because there is no second pass!
state.SetStencil(0, SOP_Increment, SF_ColorMaskOff);
state.SetDepthFunc(DF_Less); state.SetDepthMask(true);
DrawPortalStencil(state, STP_AllInOne); DrawPortalStencil(state, STP_AllInOne);
state.SetStencil(1, SOP_Keep); // draw sky into stencil. This stage doesn't modify the stencil.
state.SetStencil(1, SOP_Keep, SF_DepthMaskOff);
state.EnableDepthTest(false);
state.EnableTexture(true); state.EnableTexture(true);
state.SetColorMask(true);
state.SetEffect(EFF_NONE); state.SetEffect(EFF_NONE);
state.EnableDepthTest(false);
state.SetDepthMask(false); // don't write to Z-buffer!
} }
screen->stencilValue++; screen->stencilValue++;
} }
else else
{ {
if (!NeedDepthBuffer()) if (!NeedDepthBuffer())
{ {
state.SetStencil(0, SOP_Keep, SF_DepthMaskOff); state.SetDepthMask(false);
state.EnableDepthTest(false); state.EnableDepthTest(false);
} }
} }
@ -259,6 +267,12 @@ void HWPortal::SetupStencil(HWDrawInfo *di, FRenderState &state, bool usestencil
savedvisibility = di->Viewpoint.camera ? di->Viewpoint.camera->renderflags & RF_MAYBEINVISIBLE : ActorRenderFlags::FromInt(0); savedvisibility = di->Viewpoint.camera ? di->Viewpoint.camera->renderflags & RF_MAYBEINVISIBLE : ActorRenderFlags::FromInt(0);
} }
//-----------------------------------------------------------------------------
//
// End
//
//-----------------------------------------------------------------------------
void HWPortal::RemoveStencil(HWDrawInfo *di, FRenderState &state, bool usestencil) void HWPortal::RemoveStencil(HWDrawInfo *di, FRenderState &state, bool usestencil)
{ {
Clocker c(PortalAll); Clocker c(PortalAll);
@ -268,53 +282,73 @@ void HWPortal::RemoveStencil(HWDrawInfo *di, FRenderState &state, bool usestenci
auto &vp = di->Viewpoint; auto &vp = di->Viewpoint;
if (vp.camera != nullptr) vp.camera->renderflags = (vp.camera->renderflags & ~RF_MAYBEINVISIBLE) | savedvisibility; if (vp.camera != nullptr) vp.camera->renderflags = (vp.camera->renderflags & ~RF_MAYBEINVISIBLE) | savedvisibility;
state.EnableDepthTest(true);
if (usestencil) if (usestencil)
{ {
state.SetColorMask(false); // no graphics
state.SetEffect(EFF_NONE); state.SetEffect(EFF_NONE);
state.ResetColor(); state.ResetColor();
state.EnableTexture(false); state.EnableTexture(false);
if (needdepth) if (needdepth)
{ {
// first step: reset the depth buffer to max. depth // first step: reset the depth buffer to max. depth
state.SetStencil(0, SOP_Keep, SF_ColorMaskOff);
state.SetDepthRange(1, 1); // always state.SetDepthRange(1, 1); // always
state.SetDepthFunc(DF_Always); // write the farthest depth value state.SetDepthFunc(DF_Always); // write the farthest depth value
DrawPortalStencil(state, STP_DepthClear); DrawPortalStencil(state, STP_DepthClear);
} }
else
{
state.EnableDepthTest(true);
}
// second step: restore the depth buffer to the previous values and reset the stencil // second step: restore the depth buffer to the previous values and reset the stencil
state.SetStencil(0, SOP_Decrement, SF_ColorMaskOff);
state.SetDepthRange(0, 1);
state.SetDepthFunc(DF_LEqual); state.SetDepthFunc(DF_LEqual);
state.SetDepthRange(0, 1);
state.SetStencil(0, SOP_Decrement);
DrawPortalStencil(state, STP_DepthRestore); DrawPortalStencil(state, STP_DepthRestore);
state.SetDepthFunc(DF_Less);
state.EnableTexture(true); state.EnableTexture(true);
state.SetEffect(EFF_NONE); state.SetEffect(EFF_NONE);
state.SetColorMask(true);
screen->stencilValue--; screen->stencilValue--;
// restore old stencil op.
state.SetStencil(0, SOP_Keep);
} }
else else
{ {
if (needdepth)
{
state.Clear(CT_Depth);
}
else
{
state.EnableDepthTest(true);
state.SetDepthMask(true);
}
// This draws a valid z-buffer into the stencil's contents to ensure it
// doesn't get overwritten by the level's geometry.
state.ResetColor(); state.ResetColor();
state.SetDepthFunc(DF_LEqual);
state.SetDepthRange(0, 1);
state.SetColorMask(0, 0, 0, 1); // mark portal in alpha channel but don't touch color
state.SetEffect(EFF_STENCIL); state.SetEffect(EFF_STENCIL);
state.EnableTexture(false); state.EnableTexture(false);
state.SetRenderStyle(STYLE_Source); state.SetRenderStyle(STYLE_Source);
state.SetStencil(0, SOP_Keep, SF_ColorMaskOff | SF_ColorMaskAlpha); // SSAO needs the alpha channel as a marker.
if (needdepth) state.Clear(CT_Depth);
state.SetDepthRange(0, 1);
state.SetDepthFunc(DF_LEqual);
DrawPortalStencil(state, STP_DepthRestore); DrawPortalStencil(state, STP_DepthRestore);
state.SetEffect(EFF_NONE); state.SetEffect(EFF_NONE);
state.EnableTexture(true); state.EnableTexture(true);
state.SetColorMask(true);
state.SetDepthFunc(DF_Less);
} }
state.SetStencil(0, SOP_Keep, SF_AllOn);
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// //
// //
@ -328,7 +362,6 @@ void HWScenePortalBase::ClearClipper(HWDrawInfo *di, Clipper *clipper)
clipper->Clear(); clipper->Clear();
auto &lines = mOwner->lines;
// Set the clipper to the minimal visible area // Set the clipper to the minimal visible area
clipper->SafeAddClipRange(0, 0xffffffff); clipper->SafeAddClipRange(0, 0xffffffff);
for (unsigned int i = 0; i < lines.Size(); i++) for (unsigned int i = 0; i < lines.Size(); i++)
@ -409,7 +442,7 @@ int HWLinePortal::ClipPoint(const DVector2 &pos)
bool HWMirrorPortal::Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *clipper) bool HWMirrorPortal::Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *clipper)
{ {
auto state = mOwner->mState; auto state = mState;
if (state->renderdepth > r_mirror_recursions) if (state->renderdepth > r_mirror_recursions)
{ {
return false; return false;
@ -490,7 +523,7 @@ bool HWMirrorPortal::Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *clippe
void HWMirrorPortal::Shutdown(HWDrawInfo *di, FRenderState &rstate) void HWMirrorPortal::Shutdown(HWDrawInfo *di, FRenderState &rstate)
{ {
mOwner->mState->MirrorFlag--; mState->MirrorFlag--;
} }
const char *HWMirrorPortal::GetName() { return "Mirror"; } const char *HWMirrorPortal::GetName() { return "Mirror"; }
@ -513,7 +546,7 @@ const char *HWMirrorPortal::GetName() { return "Mirror"; }
bool HWLineToLinePortal::Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *clipper) bool HWLineToLinePortal::Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *clipper)
{ {
// TODO: Handle recursion more intelligently // TODO: Handle recursion more intelligently
auto &state = mOwner->mState; auto &state = mState;
if (state->renderdepth>r_mirror_recursions) if (state->renderdepth>r_mirror_recursions)
{ {
return false; return false;
@ -543,7 +576,6 @@ bool HWLineToLinePortal::Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *cl
} }
} }
auto &lines = mOwner->lines;
for (unsigned i = 0; i < lines.Size(); i++) for (unsigned i = 0; i < lines.Size(); i++)
{ {
@ -589,10 +621,10 @@ const char *HWLineToLinePortal::GetName() { return "LineToLine"; }
bool HWSkyboxPortal::Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *clipper) bool HWSkyboxPortal::Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *clipper)
{ {
auto state = mOwner->mState; auto state = mState;
old_pm = state->PlaneMirrorMode; old_pm = state->PlaneMirrorMode;
if (mOwner->mState->skyboxrecursion >= 3) if (mState->skyboxrecursion >= 3)
{ {
return false; return false;
} }
@ -631,7 +663,7 @@ void HWSkyboxPortal::Shutdown(HWDrawInfo *di, FRenderState &rstate)
{ {
rstate.SetDepthClamp(oldclamp); rstate.SetDepthClamp(oldclamp);
auto state = mOwner->mState; auto state = mState;
portal->mFlags &= ~PORTSF_INSKYBOX; portal->mFlags &= ~PORTSF_INSKYBOX;
state->inskybox = false; state->inskybox = false;
state->skyboxrecursion--; state->skyboxrecursion--;
@ -699,7 +731,7 @@ void HWSectorStackPortal::SetupCoverage(HWDrawInfo *di)
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
bool HWSectorStackPortal::Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *clipper) bool HWSectorStackPortal::Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *clipper)
{ {
auto state = mOwner->mState; auto state = mState;
FSectorPortalGroup *portal = origin; FSectorPortalGroup *portal = origin;
auto &vp = di->Viewpoint; auto &vp = di->Viewpoint;
@ -751,7 +783,7 @@ const char *HWSectorStackPortal::GetName() { return "Sectorstack"; }
bool HWPlaneMirrorPortal::Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *clipper) bool HWPlaneMirrorPortal::Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *clipper)
{ {
auto state = mOwner->mState; auto state = mState;
if (state->renderdepth > r_mirror_recursions) if (state->renderdepth > r_mirror_recursions)
{ {
return false; return false;
@ -781,7 +813,7 @@ bool HWPlaneMirrorPortal::Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *c
void HWPlaneMirrorPortal::Shutdown(HWDrawInfo *di, FRenderState &rstate) void HWPlaneMirrorPortal::Shutdown(HWDrawInfo *di, FRenderState &rstate)
{ {
auto state = mOwner->mState; auto state = mState;
state->PlaneMirrorFlag--; state->PlaneMirrorFlag--;
state->PlaneMirrorMode = old_pm; state->PlaneMirrorMode = old_pm;
std::swap(screen->instack[sector_t::floor], screen->instack[sector_t::ceiling]); std::swap(screen->instack[sector_t::floor], screen->instack[sector_t::ceiling]);
@ -800,8 +832,8 @@ const char *HWPlaneMirrorPortal::GetName() { return origin->fC() < 0? "Planemirr
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
HWHorizonPortal::HWHorizonPortal(FPortalSceneState *s, GLHorizonInfo * pt, FRenderViewpoint &vp, HWDrawInfo *di, bool local) HWHorizonPortal::HWHorizonPortal(FPortalSceneState *s, GLHorizonInfo * pt, FRenderViewpoint &vp, bool local)
: HWPortal(s, local) : HWPortal(s, local)
{ {
origin = pt; origin = pt;
@ -960,7 +992,7 @@ void HWEEHorizonPortal::DrawContents(HWDrawInfo *di, FRenderState &state)
{ {
horz.plane.Texheight = vp.Pos.Z + fabs(horz.plane.Texheight); horz.plane.Texheight = vp.Pos.Z + fabs(horz.plane.Texheight);
} }
HWHorizonPortal ceil(mState, &horz, di->Viewpoint, di, true); HWHorizonPortal ceil(mState, &horz, di->Viewpoint, true);
ceil.DrawContents(di, state); ceil.DrawContents(di, state);
} }
if (sector->GetTexture(sector_t::floor) != skyflatnum) if (sector->GetTexture(sector_t::floor) != skyflatnum)
@ -974,7 +1006,7 @@ void HWEEHorizonPortal::DrawContents(HWDrawInfo *di, FRenderState &state)
{ {
horz.plane.Texheight = vp.Pos.Z - fabs(horz.plane.Texheight); horz.plane.Texheight = vp.Pos.Z - fabs(horz.plane.Texheight);
} }
HWHorizonPortal floor(mState, &horz, di->Viewpoint, di, true); HWHorizonPortal floor(mState, &horz, di->Viewpoint, true);
floor.DrawContents(di, state); floor.DrawContents(di, state);
} }
} }

View file

@ -1,13 +1,13 @@
#pragma once #pragma once
#include "portal.h" #include "tarray.h"
#include "r_utility.h"
#include "actor.h" #include "actor.h"
#include "hw_drawinfo.h" #include "hwrenderer/scene/hw_drawinfo.h"
#include "hw_drawstructs.h" #include "hwrenderer/scene/hw_drawstructs.h"
#include "hw_renderstate.h"
#include "hwrenderer/textures/hw_material.h" #include "hwrenderer/textures/hw_material.h"
#include "hwrenderer/scene/hw_renderstate.h"
class FSkyVertexBuffer;
struct GLSkyInfo struct GLSkyInfo
{ {
@ -62,11 +62,14 @@ public:
FPortalSceneState * mState; FPortalSceneState * mState;
TArray<GLWall> lines; TArray<GLWall> lines;
HWPortal(FPortalSceneState *s, bool local); HWPortal(FPortalSceneState *s, bool local = false) : mState(s)
void SetupStencil(HWDrawInfo *di, FRenderState &state, bool usestencil); {
void RemoveStencil(HWDrawInfo *di, FRenderState &state, bool usestencil); }
virtual ~HWPortal() {}
virtual ~HWPortal() {} virtual int ClipSeg(seg_t *seg, const DVector3 &viewpos) { return PClip_Inside; }
virtual int ClipSubsector(subsector_t *sub) { return PClip_Inside; }
virtual int ClipPoint(const DVector2 &pos) { return PClip_Inside; }
virtual line_t *ClipLine() { return nullptr; }
virtual void * GetSource() const = 0; // GetSource MUST be implemented! virtual void * GetSource() const = 0; // GetSource MUST be implemented!
virtual const char *GetName() = 0; virtual const char *GetName() = 0;
virtual bool IsSky() { return false; } virtual bool IsSky() { return false; }
@ -74,6 +77,8 @@ public:
virtual bool NeedDepthBuffer() { return true; } virtual bool NeedDepthBuffer() { return true; }
virtual void DrawContents(HWDrawInfo *di, FRenderState &state) = 0; virtual void DrawContents(HWDrawInfo *di, FRenderState &state) = 0;
virtual void RenderAttached(HWDrawInfo *di) {} virtual void RenderAttached(HWDrawInfo *di) {}
void SetupStencil(HWDrawInfo *di, FRenderState &state, bool usestencil);
void RemoveStencil(HWDrawInfo *di, FRenderState &state, bool usestencil);
void AddLine(GLWall * l) void AddLine(GLWall * l)
{ {
@ -83,6 +88,7 @@ public:
}; };
struct FPortalSceneState struct FPortalSceneState
{ {
int MirrorFlag = 0; int MirrorFlag = 0;
@ -116,37 +122,28 @@ struct FPortalSceneState
void RenderPortal(HWPortal *p, FRenderState &state, bool usestencil, HWDrawInfo *outer_di); void RenderPortal(HWPortal *p, FRenderState &state, bool usestencil, HWDrawInfo *outer_di);
}; };
inline HWPortal::HWPortal(FPortalSceneState *s, bool local) : mState(s)
{ class HWScenePortalBase : public HWPortal
//if (!local) s->portals.Push(this);
}
class HWScenePortalBase
{ {
protected: protected:
HWPortal *mOwner; HWScenePortalBase(FPortalSceneState *state) : HWPortal(state, false)
{
}
public: public:
HWScenePortalBase() {}
virtual ~HWScenePortalBase() {}
void SetOwner(HWPortal *p) { mOwner = p; }
void ClearClipper(HWDrawInfo *di, Clipper *clipper); void ClearClipper(HWDrawInfo *di, Clipper *clipper);
virtual int ClipSeg(seg_t *seg, const DVector3 &viewpos) { return PClip_Inside; }
virtual int ClipSubsector(subsector_t *sub) { return PClip_Inside; }
virtual int ClipPoint(const DVector2 &pos) { return PClip_Inside; }
virtual line_t *ClipLine() { return nullptr; }
virtual bool IsSky() { return false; }
virtual bool NeedCap() { return false; }
virtual bool NeedDepthBuffer() { return true; } virtual bool NeedDepthBuffer() { return true; }
virtual void * GetSource() const = 0; // GetSource MUST be implemented! virtual void DrawContents(HWDrawInfo *di, FRenderState &state)
virtual const char *GetName() = 0; {
if (Setup(di, state, di->mClipper))
{
di->DrawScene(di, DM_PORTAL);
Shutdown(di, state);
}
else state.ClearScreen();
}
virtual bool Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *clipper) = 0; virtual bool Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *clipper) = 0;
virtual void Shutdown(HWDrawInfo *di, FRenderState &rstate) {} virtual void Shutdown(HWDrawInfo *di, FRenderState &rstate) {}
virtual void RenderAttached(HWDrawInfo *di) {}
}; };
struct HWLinePortal : public HWScenePortalBase struct HWLinePortal : public HWScenePortalBase
@ -157,14 +154,14 @@ struct HWLinePortal : public HWScenePortalBase
angle_t angv1, angv2; // for quick comparisons with a line or subsector angle_t angv1, angv2; // for quick comparisons with a line or subsector
HWLinePortal(line_t *line) HWLinePortal(FPortalSceneState *state, line_t *line) : HWScenePortalBase(state)
{ {
v1 = line->v1; v1 = line->v1;
v2 = line->v2; v2 = line->v2;
CalcDelta(); CalcDelta();
} }
HWLinePortal(FLinePortalSpan *line) HWLinePortal(FPortalSceneState *state, FLinePortalSpan *line) : HWScenePortalBase(state)
{ {
if (line->lines[0]->mType != PORTT_LINKED || line->v1 == nullptr) if (line->lines[0]->mType != PORTT_LINKED || line->v1 == nullptr)
{ {
@ -212,8 +209,8 @@ protected:
public: public:
HWMirrorPortal(line_t * line) HWMirrorPortal(FPortalSceneState *state, line_t * line)
: HWLinePortal(line) : HWLinePortal(state, line)
{ {
linedef = line; linedef = line;
} }
@ -232,8 +229,8 @@ protected:
public: public:
HWLineToLinePortal(FLinePortalSpan *ll) HWLineToLinePortal(FPortalSceneState *state, FLinePortalSpan *ll)
: HWLinePortal(ll) : HWLinePortal(state, ll)
{ {
glport = ll; glport = ll;
} }
@ -256,7 +253,7 @@ protected:
public: public:
HWSkyboxPortal(FSectorPortal * pt) HWSkyboxPortal(FPortalSceneState *state, FSectorPortal * pt) : HWScenePortalBase(state)
{ {
portal = pt; portal = pt;
} }
@ -277,7 +274,7 @@ protected:
public: public:
HWSectorStackPortal(FSectorPortalGroup *pt) HWSectorStackPortal(FPortalSceneState *state, FSectorPortalGroup *pt) : HWScenePortalBase(state)
{ {
origin = pt; origin = pt;
} }
@ -301,7 +298,7 @@ protected:
public: public:
HWPlaneMirrorPortal(secplane_t * pt) HWPlaneMirrorPortal(FPortalSceneState *state, secplane_t * pt) : HWScenePortalBase(state)
{ {
origin = pt; origin = pt;
} }
@ -309,34 +306,6 @@ public:
}; };
class HWScenePortal : public HWPortal
{
public:
HWScenePortalBase *mScene;
HWScenePortal(FPortalSceneState *state, HWScenePortalBase *handler) : HWPortal(state, false)
{
mScene = handler;
handler->SetOwner(this);
}
~HWScenePortal() { delete mScene; }
virtual void * GetSource() const { return mScene->GetSource(); }
virtual const char *GetName() { return mScene->GetName(); }
virtual bool IsSky() { return mScene->IsSky(); }
virtual bool NeedCap() { return true; }
virtual bool NeedDepthBuffer() { return true; }
virtual void DrawContents(HWDrawInfo *di, FRenderState &state)
{
if (mScene->Setup(di, state, di->mClipper))
{
di->DrawScene(di, DM_PORTAL);
mScene->Shutdown(di, state);
}
else state.ClearScreen();
}
virtual void RenderAttached(HWDrawInfo *di) { return mScene->RenderAttached(di); }
};
struct HWHorizonPortal : public HWPortal struct HWHorizonPortal : public HWPortal
{ {
GLHorizonInfo * origin; GLHorizonInfo * origin;
@ -352,8 +321,8 @@ protected:
virtual const char *GetName(); virtual const char *GetName();
public: public:
HWHorizonPortal(FPortalSceneState *state, GLHorizonInfo * pt, FRenderViewpoint &vp, HWDrawInfo *di, bool local = false); HWHorizonPortal(FPortalSceneState *state, GLHorizonInfo * pt, FRenderViewpoint &vp, bool local = false);
}; };
struct HWEEHorizonPortal : public HWPortal struct HWEEHorizonPortal : public HWPortal
@ -369,7 +338,7 @@ protected:
public: public:
HWEEHorizonPortal(FPortalSceneState *state, FSectorPortal *pt, HWDrawInfo *di) : HWPortal(state, false) HWEEHorizonPortal(FPortalSceneState *state, FSectorPortal *pt) : HWPortal(state)
{ {
portal = pt; portal = pt;
} }

View file

@ -57,7 +57,6 @@ enum EStencilFlags
SF_AllOn = 0, SF_AllOn = 0,
SF_ColorMaskOff = 1, SF_ColorMaskOff = 1,
SF_DepthMaskOff = 2, SF_DepthMaskOff = 2,
SF_ColorMaskAlpha = 4, // hack value for SSAO
}; };
enum EStencilOp enum EStencilOp
@ -507,8 +506,9 @@ public:
virtual void SetDepthMask(bool on) = 0; // Used by decals and indirectly by portal setup. virtual void SetDepthMask(bool on) = 0; // Used by decals and indirectly by portal setup.
virtual void SetDepthFunc(int func) = 0; // Used by models, portals and mirror surfaces. virtual void SetDepthFunc(int func) = 0; // Used by models, portals and mirror surfaces.
virtual void SetDepthRange(float min, float max) = 0; // Used by portal setup. virtual void SetDepthRange(float min, float max) = 0; // Used by portal setup.
virtual void SetColorMask(bool r, bool g, bool b, bool a) = 0; // Used by portals.
virtual void EnableDrawBufferAttachments(bool on) = 0; // Used by fog boundary drawer. virtual void EnableDrawBufferAttachments(bool on) = 0; // Used by fog boundary drawer.
virtual void SetStencil(int offs, int op, int flags) = 0; // Used by portal setup and render hacks. virtual void SetStencil(int offs, int op, int flags=-1) = 0; // Used by portal setup and render hacks.
virtual void SetCulling(int mode) = 0; // Used by model drawer only. virtual void SetCulling(int mode) = 0; // Used by model drawer only.
virtual void EnableClipDistance(int num, bool state) = 0; // Use by sprite sorter for vertical splits. virtual void EnableClipDistance(int num, bool state) = 0; // Use by sprite sorter for vertical splits.
virtual void Clear(int targets) = 0; // not used during normal rendering virtual void Clear(int targets) = 0; // not used during normal rendering
@ -519,6 +519,10 @@ public:
virtual void EnableMultisampling(bool on) = 0; // only active for 2D virtual void EnableMultisampling(bool on) = 0; // only active for 2D
virtual void EnableLineSmooth(bool on) = 0; // constant setting for each 2D drawer operation virtual void EnableLineSmooth(bool on) = 0; // constant setting for each 2D drawer operation
void SetColorMask(bool on)
{
SetColorMask(on, on, on, on);
}
}; };

View file

@ -104,9 +104,9 @@ void HWSkyPortal::RenderBox(HWDrawInfo *di, FRenderState &state, FTextureID texn
state.mModelMatrix.loadIdentity(); state.mModelMatrix.loadIdentity();
if (!sky2) if (!sky2)
state.mModelMatrix.rotate(-180.0f+x_offset, level.info->skyrotatevector.X, level.info->skyrotatevector.Z, level.info->skyrotatevector.Y); state.mModelMatrix.rotate(-180.0f+x_offset, ::level.info->skyrotatevector.X, ::level.info->skyrotatevector.Z, ::level.info->skyrotatevector.Y);
else else
state.mModelMatrix.rotate(-180.0f+x_offset, level.info->skyrotatevector2.X, level.info->skyrotatevector2.Z, level.info->skyrotatevector2.Y); state.mModelMatrix.rotate(-180.0f+x_offset, ::level.info->skyrotatevector2.X, ::level.info->skyrotatevector2.Z, ::level.info->skyrotatevector2.Y);
if (sb->faces[5]) if (sb->faces[5])
{ {

View file

@ -498,7 +498,7 @@ void GLWall::PutPortal(HWDrawInfo *di, int ptype)
portal = di->FindPortal(horizon); portal = di->FindPortal(horizon);
if (!portal) if (!portal)
{ {
portal = new HWHorizonPortal(pstate, horizon, di->Viewpoint, di); portal = new HWHorizonPortal(pstate, horizon, di->Viewpoint);
di->Portals.Push(portal); di->Portals.Push(portal);
} }
portal->AddLine(this); portal->AddLine(this);
@ -509,10 +509,10 @@ void GLWall::PutPortal(HWDrawInfo *di, int ptype)
if (!portal) if (!portal)
{ {
// either a regular skybox or an Eternity-style horizon // either a regular skybox or an Eternity-style horizon
if (secportal->mType != PORTS_SKYVIEWPOINT) portal = new HWEEHorizonPortal(pstate, secportal, di); if (secportal->mType != PORTS_SKYVIEWPOINT) portal = new HWEEHorizonPortal(pstate, secportal);
else else
{ {
portal = new HWScenePortal(pstate, new HWSkyboxPortal(secportal)); portal = new HWSkyboxPortal(pstate, secportal);
di->Portals.Push(portal); di->Portals.Push(portal);
} }
} }
@ -523,7 +523,7 @@ void GLWall::PutPortal(HWDrawInfo *di, int ptype)
portal = di->FindPortal(this->portal); portal = di->FindPortal(this->portal);
if (!portal) if (!portal)
{ {
portal = new HWScenePortal(pstate, new HWSectorStackPortal(this->portal)); portal = new HWSectorStackPortal(pstate, this->portal);
di->Portals.Push(portal); di->Portals.Push(portal);
} }
portal->AddLine(this); portal->AddLine(this);
@ -537,7 +537,7 @@ void GLWall::PutPortal(HWDrawInfo *di, int ptype)
portal = di->FindPortal(planemirror); portal = di->FindPortal(planemirror);
if (!portal) if (!portal)
{ {
portal = new HWScenePortal(pstate, new HWPlaneMirrorPortal(planemirror)); portal = new HWPlaneMirrorPortal(pstate, planemirror);
di->Portals.Push(portal); di->Portals.Push(portal);
} }
portal->AddLine(this); portal->AddLine(this);
@ -548,7 +548,7 @@ void GLWall::PutPortal(HWDrawInfo *di, int ptype)
portal = di->FindPortal(seg->linedef); portal = di->FindPortal(seg->linedef);
if (!portal) if (!portal)
{ {
portal = new HWScenePortal(pstate, new HWMirrorPortal(seg->linedef)); portal = new HWMirrorPortal(pstate, seg->linedef);
di->Portals.Push(portal); di->Portals.Push(portal);
} }
portal->AddLine(this); portal->AddLine(this);
@ -570,7 +570,7 @@ void GLWall::PutPortal(HWDrawInfo *di, int ptype)
{ {
di->ProcessActorsInPortal(otherside->getPortal()->mGroup, di->in_area); di->ProcessActorsInPortal(otherside->getPortal()->mGroup, di->in_area);
} }
portal = new HWScenePortal(pstate, new HWLineToLinePortal(lineportal)); portal = new HWLineToLinePortal(pstate, lineportal);
di->Portals.Push(portal); di->Portals.Push(portal);
} }
portal->AddLine(this); portal->AddLine(this);

View file

@ -249,7 +249,6 @@ struct FSectorPortal
// //
//============================================================================ //============================================================================
struct GLSectorStackPortal;
struct FSectorPortalGroup struct FSectorPortalGroup
{ {
DVector2 mDisplacement; DVector2 mDisplacement;
@ -286,4 +285,4 @@ DVector2 P_GetOffsetPosition(double x, double y, double dx, double dy);
void InitPortalGroups(); void InitPortalGroups();
#endif #endif