- merged GLPortal into HWPortal after all direct OpenGL dependencies have been removed.

This commit is contained in:
Christoph Oelckers 2018-10-24 07:49:06 +02:00
parent d757efde96
commit c76c4b77ec
9 changed files with 183 additions and 196 deletions

View File

@ -108,16 +108,6 @@ class FFlatVertexBuffer : public FVertexBuffer, public FFlatVertexGenerator
static const unsigned int BUFFER_SIZE_TO_USE = 1999500; static const unsigned int BUFFER_SIZE_TO_USE = 1999500;
public: public:
enum
{
QUAD_INDEX = 0,
FULLSCREEN_INDEX = 4,
PRESENT_INDEX = 8,
STENCILTOP_INDEX = 12,
STENCILBOTTOM_INDEX = 16,
NUM_RESERVED = 20
};
FFlatVertexBuffer(int width, int height); FFlatVertexBuffer(int width, int height);
~FFlatVertexBuffer(); ~FFlatVertexBuffer();

View File

@ -21,7 +21,7 @@ class FSkyVertexBuffer;
class OpenGLFrameBuffer; class OpenGLFrameBuffer;
struct FDrawInfo; struct FDrawInfo;
class FShaderManager; class FShaderManager;
class GLPortal; class HWPortal;
class FLightBuffer; class FLightBuffer;
class FSamplerManager; class FSamplerManager;
class DPSprite; class DPSprite;

View File

@ -314,7 +314,7 @@ void FDrawInfo::DrawHUDModel(HUDSprite *huds, FRenderState &state)
void FDrawInfo::RenderPortal(HWPortal *p, bool usestencil) void FDrawInfo::RenderPortal(HWPortal *p, bool usestencil)
{ {
auto gp = static_cast<GLPortal *>(p); auto gp = static_cast<HWPortal *>(p);
gp->SetupStencil(this, gl_RenderState, usestencil); gp->SetupStencil(this, gl_RenderState, usestencil);
auto new_di = StartDrawInfo(Viewpoint, &VPUniforms); auto new_di = StartDrawInfo(Viewpoint, &VPUniforms);
new_di->mCurrentPortal = gp; new_di->mCurrentPortal = gp;

View File

@ -56,153 +56,6 @@
EXTERN_CVAR(Int, r_mirror_recursions) EXTERN_CVAR(Int, r_mirror_recursions)
//-----------------------------------------------------------------------------
//
// DrawPortalStencil
//
//-----------------------------------------------------------------------------
void GLPortal::DrawPortalStencil(HWDrawInfo *di, FRenderState &state, int pass)
{
if (mPrimIndices.Size() == 0)
{
mPrimIndices.Resize(2 * lines.Size());
for (unsigned int i = 0; i < lines.Size(); i++)
{
mPrimIndices[i * 2] = lines[i].vertindex;
mPrimIndices[i * 2 + 1] = lines[i].vertcount;
}
}
for (unsigned int i = 0; i < mPrimIndices.Size(); i += 2)
{
di->Draw(DT_TriangleFan, state, mPrimIndices[i], mPrimIndices[i + 1], i==0);
}
if (NeedCap() && lines.Size() > 1)
{
// The cap's depth handling needs special treatment so that it won't block further portal caps.
if (pass == STP_DepthRestore) di->SetDepthRange(1, 1);
di->Draw(DT_TriangleFan, state, FFlatVertexBuffer::STENCILTOP_INDEX, 4);
di->Draw(DT_TriangleFan, state, FFlatVertexBuffer::STENCILBOTTOM_INDEX, 4);
if (pass == STP_DepthRestore) di->SetDepthRange(0, 1);
}
}
//-----------------------------------------------------------------------------
//
// Start
//
//-----------------------------------------------------------------------------
void GLPortal::SetupStencil(HWDrawInfo *di, FRenderState &state, bool usestencil)
{
Clocker c(PortalAll);
rendered_portals++;
if (usestencil)
{
// Create stencil
state.SetEffect(EFF_STENCIL);
state.EnableTexture(false);
state.ResetColor();
if (NeedDepthBuffer())
{
di->SetStencil(0, SOP_Increment, SF_ColorMaskOff | SF_DepthMaskOff);
di->SetDepthFunc(DF_Less);
DrawPortalStencil(di, state, STP_Stencil);
// Clear Z-buffer
di->SetStencil(1, SOP_Keep, SF_ColorMaskOff);
di->SetDepthRange(1, 1);
di->SetDepthFunc(DF_Always);
DrawPortalStencil(di, state, STP_DepthClear);
// set normal drawing mode
state.EnableTexture(true);
di->SetStencil(1, SOP_Keep, SF_AllOn);
di->SetDepthRange(0, 1);
di->SetDepthFunc(DF_Less);
state.SetEffect(EFF_NONE);
}
else
{
// 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!
di->SetStencil(0, SOP_Increment, SF_ColorMaskOff);
di->SetDepthFunc(DF_Less);
DrawPortalStencil(di, state, STP_AllInOne);
di->SetStencil(1, SOP_Keep, SF_DepthTestOff | SF_DepthMaskOff);
state.EnableTexture(true);
state.SetEffect(EFF_NONE);
}
screen->stencilValue++;
}
else
{
if (!NeedDepthBuffer())
{
di->SetStencil(0, SOP_Keep, SF_DepthTestOff | SF_DepthMaskOff);
}
}
// save viewpoint
savedvisibility = di->Viewpoint.camera ? di->Viewpoint.camera->renderflags & RF_MAYBEINVISIBLE : ActorRenderFlags::FromInt(0);
}
void GLPortal::RemoveStencil(HWDrawInfo *di, FRenderState &state, bool usestencil)
{
Clocker c(PortalAll);
bool needdepth = NeedDepthBuffer();
// Restore the old view
auto &vp = di->Viewpoint;
if (vp.camera != nullptr) vp.camera->renderflags = (vp.camera->renderflags & ~RF_MAYBEINVISIBLE) | savedvisibility;
if (usestencil)
{
state.SetEffect(EFF_NONE);
state.ResetColor();
state.EnableTexture(false);
if (needdepth)
{
// first step: reset the depth buffer to max. depth
di->SetStencil(0, SOP_Keep, SF_ColorMaskOff);
di->SetDepthRange(1, 1); // always
di->SetDepthFunc(DF_Always); // write the farthest depth value
DrawPortalStencil(di, state, STP_DepthClear);
}
// second step: restore the depth buffer to the previous values and reset the stencil
di->SetStencil(0, SOP_Decrement, SF_ColorMaskOff);
di->SetDepthRange(0, 1);
di->SetDepthFunc(DF_LEqual);
DrawPortalStencil(di, state, STP_DepthRestore);
state.EnableTexture(true);
state.SetEffect(EFF_NONE);
screen->stencilValue--;
}
else
{
state.ResetColor();
state.SetEffect(EFF_STENCIL);
state.EnableTexture(false);
state.SetRenderStyle(STYLE_Source);
di->SetStencil(0, SOP_Keep, needdepth? SF_ColorMaskOff | SF_DepthClear : SF_ColorMaskOff);
di->SetDepthRange(0, 1);
di->SetDepthFunc(DF_LEqual);
DrawPortalStencil(di, state, STP_DepthRestore);
state.SetEffect(EFF_NONE);
state.EnableTexture(true);
}
di->SetStencil(0, SOP_Keep, SF_AllOn);
}
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// //
@ -214,7 +67,7 @@ void GLPortal::RemoveStencil(HWDrawInfo *di, FRenderState &state, bool usestenci
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
GLHorizonPortal::GLHorizonPortal(FPortalSceneState *s, GLHorizonInfo * pt, FRenderViewpoint &vp, bool local) GLHorizonPortal::GLHorizonPortal(FPortalSceneState *s, GLHorizonInfo * pt, FRenderViewpoint &vp, bool local)
: GLPortal(s, local) : HWPortal(s, local)
{ {
origin = pt; origin = pt;

View File

@ -46,38 +46,11 @@
struct GLEEHorizonPortal; struct GLEEHorizonPortal;
class GLPortal : public HWPortal class GLScenePortal : public HWPortal
{
private:
enum
{
STP_Stencil,
STP_DepthClear,
STP_DepthRestore,
STP_AllInOne
};
void DrawPortalStencil(HWDrawInfo *di, FRenderState &state, int pass);
ActorRenderFlags savedvisibility;
TArray<unsigned int> mPrimIndices;
public:
void SetupStencil(HWDrawInfo *di, FRenderState &state, bool usestencil);
void RemoveStencil(HWDrawInfo *di, FRenderState &state, bool usestencil);
protected:
int level;
GLPortal(FPortalSceneState *state, bool local = false) : HWPortal(state, local) { }
};
class GLScenePortal : public GLPortal
{ {
public: public:
HWScenePortalBase *mScene; HWScenePortalBase *mScene;
GLScenePortal(FPortalSceneState *state, HWScenePortalBase *handler) : GLPortal(state) GLScenePortal(FPortalSceneState *state, HWScenePortalBase *handler) : HWPortal(state, false)
{ {
mScene = handler; mScene = handler;
handler->SetOwner(this); handler->SetOwner(this);
@ -101,7 +74,7 @@ public:
}; };
struct GLSkyPortal : public GLPortal struct GLSkyPortal : public HWPortal
{ {
GLSkyInfo * origin; GLSkyInfo * origin;
friend struct GLEEHorizonPortal; friend struct GLEEHorizonPortal;
@ -117,14 +90,14 @@ public:
GLSkyPortal(FPortalSceneState *state, GLSkyInfo * pt, bool local = false) GLSkyPortal(FPortalSceneState *state, GLSkyInfo * pt, bool local = false)
: GLPortal(state, local) : HWPortal(state, local)
{ {
origin=pt; origin=pt;
} }
}; };
struct GLHorizonPortal : public GLPortal struct GLHorizonPortal : public HWPortal
{ {
GLHorizonInfo * origin; GLHorizonInfo * origin;
unsigned int voffset; unsigned int voffset;
@ -143,7 +116,7 @@ public:
GLHorizonPortal(FPortalSceneState *state, GLHorizonInfo * pt, FRenderViewpoint &vp, bool local = false); GLHorizonPortal(FPortalSceneState *state, GLHorizonInfo * pt, FRenderViewpoint &vp, bool local = false);
}; };
struct GLEEHorizonPortal : public GLPortal struct GLEEHorizonPortal : public HWPortal
{ {
FSectorPortal * portal; FSectorPortal * portal;
@ -156,7 +129,7 @@ protected:
public: public:
GLEEHorizonPortal(FPortalSceneState *state, FSectorPortal *pt) : GLPortal(state) GLEEHorizonPortal(FPortalSceneState *state, FSectorPortal *pt) : HWPortal(state, false)
{ {
portal=pt; portal=pt;
} }

View File

@ -230,7 +230,7 @@ void FDrawInfo::RenderTranslucent()
// //
// gl_drawscene - this function renders the scene from the current // gl_drawscene - this function renders the scene from the current
// viewpoint, including mirrors and skyboxes and other portals // viewpoint, including mirrors and skyboxes and other portals
// It is assumed that the GLPortal::EndFrame returns with the // It is assumed that the HWPortal::EndFrame returns with the
// stencil, z-buffer and the projection matrix intact! // stencil, z-buffer and the projection matrix intact!
// //
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------

View File

@ -147,7 +147,7 @@ public:
}; };
friend struct HWDrawList; friend struct HWDrawList;
friend class GLPortal; friend class HWPortal;
vertex_t * vertexes[2]; // required for polygon splitting vertex_t * vertexes[2]; // required for polygon splitting
FMaterial *gltexture; FMaterial *gltexture;

View File

@ -32,6 +32,9 @@
#include "hw_clipper.h" #include "hw_clipper.h"
#include "actor.h" #include "actor.h"
#include "g_levellocals.h" #include "g_levellocals.h"
#include "hw_renderstate.h"
#include "hwrenderer/data/flatvertices.h"
#include "hwrenderer/utility/hw_clock.h"
EXTERN_CVAR(Int, r_mirror_recursions) EXTERN_CVAR(Int, r_mirror_recursions)
EXTERN_CVAR(Bool, gl_portals) EXTERN_CVAR(Bool, gl_portals)
@ -156,6 +159,156 @@ void FPortalSceneState::RenderPortal(HWPortal *p, bool usestencil, HWDrawInfo *o
} }
//-----------------------------------------------------------------------------
//
// DrawPortalStencil
//
//-----------------------------------------------------------------------------
void HWPortal::DrawPortalStencil(HWDrawInfo *di, FRenderState &state, int pass)
{
if (mPrimIndices.Size() == 0)
{
mPrimIndices.Resize(2 * lines.Size());
for (unsigned int i = 0; i < lines.Size(); i++)
{
mPrimIndices[i * 2] = lines[i].vertindex;
mPrimIndices[i * 2 + 1] = lines[i].vertcount;
}
}
for (unsigned int i = 0; i < mPrimIndices.Size(); i += 2)
{
di->Draw(DT_TriangleFan, state, mPrimIndices[i], mPrimIndices[i + 1], i == 0);
}
if (NeedCap() && lines.Size() > 1)
{
// The cap's depth handling needs special treatment so that it won't block further portal caps.
if (pass == STP_DepthRestore) di->SetDepthRange(1, 1);
di->Draw(DT_TriangleFan, state, FFlatVertexGenerator::STENCILTOP_INDEX, 4);
di->Draw(DT_TriangleFan, state, FFlatVertexGenerator::STENCILBOTTOM_INDEX, 4);
if (pass == STP_DepthRestore) di->SetDepthRange(0, 1);
}
}
//-----------------------------------------------------------------------------
//
// Start
//
//-----------------------------------------------------------------------------
void HWPortal::SetupStencil(HWDrawInfo *di, FRenderState &state, bool usestencil)
{
Clocker c(PortalAll);
rendered_portals++;
if (usestencil)
{
// Create stencil
state.SetEffect(EFF_STENCIL);
state.EnableTexture(false);
state.ResetColor();
if (NeedDepthBuffer())
{
di->SetStencil(0, SOP_Increment, SF_ColorMaskOff | SF_DepthMaskOff);
di->SetDepthFunc(DF_Less);
DrawPortalStencil(di, state, STP_Stencil);
// Clear Z-buffer
di->SetStencil(1, SOP_Keep, SF_ColorMaskOff);
di->SetDepthRange(1, 1);
di->SetDepthFunc(DF_Always);
DrawPortalStencil(di, state, STP_DepthClear);
// set normal drawing mode
state.EnableTexture(true);
di->SetStencil(1, SOP_Keep, SF_AllOn);
di->SetDepthRange(0, 1);
di->SetDepthFunc(DF_Less);
state.SetEffect(EFF_NONE);
}
else
{
// 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!
di->SetStencil(0, SOP_Increment, SF_ColorMaskOff);
di->SetDepthFunc(DF_Less);
DrawPortalStencil(di, state, STP_AllInOne);
di->SetStencil(1, SOP_Keep, SF_DepthTestOff | SF_DepthMaskOff);
state.EnableTexture(true);
state.SetEffect(EFF_NONE);
}
screen->stencilValue++;
}
else
{
if (!NeedDepthBuffer())
{
di->SetStencil(0, SOP_Keep, SF_DepthTestOff | SF_DepthMaskOff);
}
}
// save viewpoint
savedvisibility = di->Viewpoint.camera ? di->Viewpoint.camera->renderflags & RF_MAYBEINVISIBLE : ActorRenderFlags::FromInt(0);
}
void HWPortal::RemoveStencil(HWDrawInfo *di, FRenderState &state, bool usestencil)
{
Clocker c(PortalAll);
bool needdepth = NeedDepthBuffer();
// Restore the old view
auto &vp = di->Viewpoint;
if (vp.camera != nullptr) vp.camera->renderflags = (vp.camera->renderflags & ~RF_MAYBEINVISIBLE) | savedvisibility;
if (usestencil)
{
state.SetEffect(EFF_NONE);
state.ResetColor();
state.EnableTexture(false);
if (needdepth)
{
// first step: reset the depth buffer to max. depth
di->SetStencil(0, SOP_Keep, SF_ColorMaskOff);
di->SetDepthRange(1, 1); // always
di->SetDepthFunc(DF_Always); // write the farthest depth value
DrawPortalStencil(di, state, STP_DepthClear);
}
// second step: restore the depth buffer to the previous values and reset the stencil
di->SetStencil(0, SOP_Decrement, SF_ColorMaskOff);
di->SetDepthRange(0, 1);
di->SetDepthFunc(DF_LEqual);
DrawPortalStencil(di, state, STP_DepthRestore);
state.EnableTexture(true);
state.SetEffect(EFF_NONE);
screen->stencilValue--;
}
else
{
state.ResetColor();
state.SetEffect(EFF_STENCIL);
state.EnableTexture(false);
state.SetRenderStyle(STYLE_Source);
di->SetStencil(0, SOP_Keep, needdepth ? SF_ColorMaskOff | SF_DepthClear : SF_ColorMaskOff);
di->SetDepthRange(0, 1);
di->SetDepthFunc(DF_LEqual);
DrawPortalStencil(di, state, STP_DepthRestore);
state.SetEffect(EFF_NONE);
state.EnableTexture(true);
}
di->SetStencil(0, SOP_Keep, SF_AllOn);
}
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// //
// //

View File

@ -1,6 +1,7 @@
#pragma once #pragma once
#include "portal.h" #include "portal.h"
#include "actor.h"
#include "hw_drawinfo.h" #include "hw_drawinfo.h"
#include "hw_drawstructs.h" #include "hw_drawstructs.h"
#include "hwrenderer/textures/hw_material.h" #include "hwrenderer/textures/hw_material.h"
@ -40,11 +41,28 @@ struct FPortalSceneState;
class HWPortal class HWPortal
{ {
friend struct FPortalSceneState; friend struct FPortalSceneState;
enum
{
STP_Stencil,
STP_DepthClear,
STP_DepthRestore,
STP_AllInOne
};
ActorRenderFlags savedvisibility;
TArray<unsigned int> mPrimIndices;
void DrawPortalStencil(HWDrawInfo *di, FRenderState &state, int pass);
public: public:
FPortalSceneState * mState; FPortalSceneState * mState;
TArray<GLWall> lines; TArray<GLWall> lines;
HWPortal(FPortalSceneState *s, bool local); HWPortal(FPortalSceneState *s, bool local);
void SetupStencil(HWDrawInfo *di, FRenderState &state, bool usestencil);
void RemoveStencil(HWDrawInfo *di, FRenderState &state, bool usestencil);
virtual ~HWPortal() {} virtual ~HWPortal() {}
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;