From c76c4b77ecdae3a0acd4a962c8c5f70d3e436ffb Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 24 Oct 2018 07:49:06 +0200 Subject: [PATCH] - merged GLPortal into HWPortal after all direct OpenGL dependencies have been removed. --- src/gl/data/gl_vertexbuffer.h | 10 -- src/gl/renderer/gl_renderer.h | 2 +- src/gl/scene/gl_drawinfo.cpp | 2 +- src/gl/scene/gl_portal.cpp | 149 +------------------------ src/gl/scene/gl_portal.h | 41 ++----- src/gl/scene/gl_scene.cpp | 2 +- src/hwrenderer/scene/hw_drawstructs.h | 2 +- src/hwrenderer/scene/hw_portal.cpp | 153 ++++++++++++++++++++++++++ src/hwrenderer/scene/hw_portal.h | 18 +++ 9 files changed, 183 insertions(+), 196 deletions(-) diff --git a/src/gl/data/gl_vertexbuffer.h b/src/gl/data/gl_vertexbuffer.h index c93b77c2d..b97e69db9 100644 --- a/src/gl/data/gl_vertexbuffer.h +++ b/src/gl/data/gl_vertexbuffer.h @@ -108,16 +108,6 @@ class FFlatVertexBuffer : public FVertexBuffer, public FFlatVertexGenerator static const unsigned int BUFFER_SIZE_TO_USE = 1999500; 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(); diff --git a/src/gl/renderer/gl_renderer.h b/src/gl/renderer/gl_renderer.h index ea602e956..bc04b813e 100644 --- a/src/gl/renderer/gl_renderer.h +++ b/src/gl/renderer/gl_renderer.h @@ -21,7 +21,7 @@ class FSkyVertexBuffer; class OpenGLFrameBuffer; struct FDrawInfo; class FShaderManager; -class GLPortal; +class HWPortal; class FLightBuffer; class FSamplerManager; class DPSprite; diff --git a/src/gl/scene/gl_drawinfo.cpp b/src/gl/scene/gl_drawinfo.cpp index decbb8d2c..b09381c31 100644 --- a/src/gl/scene/gl_drawinfo.cpp +++ b/src/gl/scene/gl_drawinfo.cpp @@ -314,7 +314,7 @@ void FDrawInfo::DrawHUDModel(HUDSprite *huds, FRenderState &state) void FDrawInfo::RenderPortal(HWPortal *p, bool usestencil) { - auto gp = static_cast(p); + auto gp = static_cast(p); gp->SetupStencil(this, gl_RenderState, usestencil); auto new_di = StartDrawInfo(Viewpoint, &VPUniforms); new_di->mCurrentPortal = gp; diff --git a/src/gl/scene/gl_portal.cpp b/src/gl/scene/gl_portal.cpp index 3ac86b27b..91849c45b 100644 --- a/src/gl/scene/gl_portal.cpp +++ b/src/gl/scene/gl_portal.cpp @@ -56,153 +56,6 @@ 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) - : GLPortal(s, local) + : HWPortal(s, local) { origin = pt; diff --git a/src/gl/scene/gl_portal.h b/src/gl/scene/gl_portal.h index cc0c4e0b1..27198a98e 100644 --- a/src/gl/scene/gl_portal.h +++ b/src/gl/scene/gl_portal.h @@ -46,38 +46,11 @@ struct GLEEHorizonPortal; -class GLPortal : public HWPortal -{ - -private: - - enum - { - STP_Stencil, - STP_DepthClear, - STP_DepthRestore, - STP_AllInOne - }; - void DrawPortalStencil(HWDrawInfo *di, FRenderState &state, int pass); - - ActorRenderFlags savedvisibility; - TArray 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 +class GLScenePortal : public HWPortal { public: HWScenePortalBase *mScene; - GLScenePortal(FPortalSceneState *state, HWScenePortalBase *handler) : GLPortal(state) + GLScenePortal(FPortalSceneState *state, HWScenePortalBase *handler) : HWPortal(state, false) { mScene = handler; handler->SetOwner(this); @@ -101,7 +74,7 @@ public: }; -struct GLSkyPortal : public GLPortal +struct GLSkyPortal : public HWPortal { GLSkyInfo * origin; friend struct GLEEHorizonPortal; @@ -117,14 +90,14 @@ public: GLSkyPortal(FPortalSceneState *state, GLSkyInfo * pt, bool local = false) - : GLPortal(state, local) + : HWPortal(state, local) { origin=pt; } }; -struct GLHorizonPortal : public GLPortal +struct GLHorizonPortal : public HWPortal { GLHorizonInfo * origin; unsigned int voffset; @@ -143,7 +116,7 @@ public: GLHorizonPortal(FPortalSceneState *state, GLHorizonInfo * pt, FRenderViewpoint &vp, bool local = false); }; -struct GLEEHorizonPortal : public GLPortal +struct GLEEHorizonPortal : public HWPortal { FSectorPortal * portal; @@ -156,7 +129,7 @@ protected: public: - GLEEHorizonPortal(FPortalSceneState *state, FSectorPortal *pt) : GLPortal(state) + GLEEHorizonPortal(FPortalSceneState *state, FSectorPortal *pt) : HWPortal(state, false) { portal=pt; } diff --git a/src/gl/scene/gl_scene.cpp b/src/gl/scene/gl_scene.cpp index 556721b0d..292b94b58 100644 --- a/src/gl/scene/gl_scene.cpp +++ b/src/gl/scene/gl_scene.cpp @@ -230,7 +230,7 @@ void FDrawInfo::RenderTranslucent() // // gl_drawscene - this function renders the scene from the current // 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! // //----------------------------------------------------------------------------- diff --git a/src/hwrenderer/scene/hw_drawstructs.h b/src/hwrenderer/scene/hw_drawstructs.h index 97b7ddeb5..67e2017c5 100644 --- a/src/hwrenderer/scene/hw_drawstructs.h +++ b/src/hwrenderer/scene/hw_drawstructs.h @@ -147,7 +147,7 @@ public: }; friend struct HWDrawList; - friend class GLPortal; + friend class HWPortal; vertex_t * vertexes[2]; // required for polygon splitting FMaterial *gltexture; diff --git a/src/hwrenderer/scene/hw_portal.cpp b/src/hwrenderer/scene/hw_portal.cpp index 51641c3fc..6c4c38b58 100644 --- a/src/hwrenderer/scene/hw_portal.cpp +++ b/src/hwrenderer/scene/hw_portal.cpp @@ -32,6 +32,9 @@ #include "hw_clipper.h" #include "actor.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(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); +} + + + //----------------------------------------------------------------------------- // // diff --git a/src/hwrenderer/scene/hw_portal.h b/src/hwrenderer/scene/hw_portal.h index 49c13104a..d9f0f287f 100644 --- a/src/hwrenderer/scene/hw_portal.h +++ b/src/hwrenderer/scene/hw_portal.h @@ -1,6 +1,7 @@ #pragma once #include "portal.h" +#include "actor.h" #include "hw_drawinfo.h" #include "hw_drawstructs.h" #include "hwrenderer/textures/hw_material.h" @@ -40,11 +41,28 @@ struct FPortalSceneState; class HWPortal { friend struct FPortalSceneState; + + enum + { + STP_Stencil, + STP_DepthClear, + STP_DepthRestore, + STP_AllInOne + }; + + ActorRenderFlags savedvisibility; + TArray mPrimIndices; + + void DrawPortalStencil(HWDrawInfo *di, FRenderState &state, int pass); + public: FPortalSceneState * mState; TArray lines; HWPortal(FPortalSceneState *s, bool local); + void SetupStencil(HWDrawInfo *di, FRenderState &state, bool usestencil); + void RemoveStencil(HWDrawInfo *di, FRenderState &state, bool usestencil); + virtual ~HWPortal() {} virtual void * GetSource() const = 0; // GetSource MUST be implemented! virtual const char *GetName() = 0;