- groundwork for separating the portal data from the renderer.

With GLPortal being responsible for all the setup a lot of code was tied to the backend.
Now FDrawInfo will manage the setup and only call pure data generation functions in the actual portal object.
This commit is contained in:
Christoph Oelckers 2018-10-24 00:19:07 +02:00
parent 93dac4e4d8
commit 3e4dcbe2b4
7 changed files with 131 additions and 210 deletions

View file

@ -40,6 +40,7 @@
#include "hwrenderer/scene/hw_clipper.h" #include "hwrenderer/scene/hw_clipper.h"
#include "gl/scene/gl_portal.h" #include "gl/scene/gl_portal.h"
#include "gl/renderer/gl_renderstate.h" #include "gl/renderer/gl_renderstate.h"
#include "gl/data/gl_viewpointbuffer.h"
#include "gl/dynlights/gl_lightbuffer.h" #include "gl/dynlights/gl_lightbuffer.h"
#include "gl/models/gl_models.h" #include "gl/models/gl_models.h"
@ -311,6 +312,18 @@ void FDrawInfo::DrawHUDModel(HUDSprite *huds, FRenderState &state)
renderer.RenderHUDModel(huds->weapon, huds->mx, huds->my); renderer.RenderHUDModel(huds->weapon, huds->mx, huds->my);
} }
void FDrawInfo::RenderPortal(IPortal *p, bool usestencil)
{
auto gp = static_cast<GLPortal *>(p);
gp->SetupStencil(this, gl_RenderState, usestencil);
auto new_di = StartDrawInfo(Viewpoint, &VPUniforms);
new_di->mCurrentPortal = gp;
gp->DrawContents(new_di);
new_di->EndDrawInfo();
GLRenderer->mViewpoints->Bind(vpIndex);
gp->RemoveStencil(this, gl_RenderState, usestencil);
}
void FDrawInfo::SetDepthMask(bool on) void FDrawInfo::SetDepthMask(bool on)
{ {
@ -323,6 +336,11 @@ void FDrawInfo::SetDepthFunc(int func)
glDepthFunc(df2gl[func]); glDepthFunc(df2gl[func]);
} }
void FDrawInfo::SetDepthRange(float min, float max)
{
glDepthRange(min, max);
}
void FDrawInfo::EnableDrawBufferAttachments(bool on) void FDrawInfo::EnableDrawBufferAttachments(bool on)
{ {
gl_RenderState.EnableDrawBuffers(on? gl_RenderState.GetPassDrawBufferCount() : 1); gl_RenderState.EnableDrawBuffers(on? gl_RenderState.GetPassDrawBufferCount() : 1);
@ -342,6 +360,31 @@ void FDrawInfo::SetStencil(int offs, int op, int flags)
glDisable(GL_DEPTH_TEST); glDisable(GL_DEPTH_TEST);
else else
glEnable(GL_DEPTH_TEST); glEnable(GL_DEPTH_TEST);
if (flags & SF_DepthClear)
glClear(GL_DEPTH_BUFFER_BIT);
}
//==========================================================================
//
//
//
//==========================================================================
void FDrawInfo::ClearScreen()
{
bool multi = !!glIsEnabled(GL_MULTISAMPLE);
GLRenderer->mViewpoints->Set2D(SCREENWIDTH, SCREENHEIGHT);
gl_RenderState.SetColor(0, 0, 0);
gl_RenderState.Apply();
glDisable(GL_MULTISAMPLE);
glDisable(GL_DEPTH_TEST);
glDrawArrays(GL_TRIANGLE_STRIP, FFlatVertexBuffer::FULLSCREEN_INDEX, 4);
glEnable(GL_DEPTH_TEST);
if (multi) glEnable(GL_MULTISAMPLE);
} }

View file

@ -47,9 +47,11 @@ struct FDrawInfo : public HWDrawInfo
void DrawIndexed(EDrawType dt, FRenderState &state, int index, int count, bool apply = true) override; void DrawIndexed(EDrawType dt, FRenderState &state, int index, int count, bool apply = true) override;
void DrawModel(GLSprite *spr, FRenderState &state) override; void DrawModel(GLSprite *spr, FRenderState &state) override;
void DrawHUDModel(HUDSprite *spr, FRenderState &state) override; void DrawHUDModel(HUDSprite *spr, FRenderState &state) override;
void RenderPortal(IPortal *p, bool stencil) override;
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 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;
@ -69,6 +71,7 @@ struct FDrawInfo : public HWDrawInfo
void EndDrawScene(sector_t * viewsector); void EndDrawScene(sector_t * viewsector);
void DrawEndScene2D(sector_t * viewsector); void DrawEndScene2D(sector_t * viewsector);
bool SetDepthClamp(bool on) override; bool SetDepthClamp(bool on) override;
void ClearScreen() override;
static FDrawInfo *StartDrawInfo(FRenderViewpoint &parentvp, HWViewpointUniforms *uniforms); static FDrawInfo *StartDrawInfo(FRenderViewpoint &parentvp, HWViewpointUniforms *uniforms);
FDrawInfo *EndDrawInfo(); FDrawInfo *EndDrawInfo();

View file

@ -54,38 +54,14 @@
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
EXTERN_CVAR(Bool, gl_portals)
EXTERN_CVAR(Bool, gl_noquery)
EXTERN_CVAR(Int, r_mirror_recursions) EXTERN_CVAR(Int, r_mirror_recursions)
//==========================================================================
//
//
//
//==========================================================================
void GLPortal::ClearScreen(HWDrawInfo *di)
{
bool multi = !!glIsEnabled(GL_MULTISAMPLE);
GLRenderer->mViewpoints->Set2D(SCREENWIDTH, SCREENHEIGHT);
gl_RenderState.SetColor(0, 0, 0);
gl_RenderState.Apply();
glDisable(GL_MULTISAMPLE);
glDisable(GL_DEPTH_TEST);
glDrawArrays(GL_TRIANGLE_STRIP, FFlatVertexBuffer::FULLSCREEN_INDEX, 4);
glEnable(GL_DEPTH_TEST);
if (multi) glEnable(GL_MULTISAMPLE);
}
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// //
// DrawPortalStencil // DrawPortalStencil
// //
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void GLPortal::DrawPortalStencil(int pass) void GLPortal::DrawPortalStencil(HWDrawInfo *di, FRenderState &state, int pass)
{ {
if (mPrimIndices.Size() == 0) if (mPrimIndices.Size() == 0)
{ {
@ -97,18 +73,17 @@ void GLPortal::DrawPortalStencil(int pass)
mPrimIndices[i * 2 + 1] = lines[i].vertcount; mPrimIndices[i * 2 + 1] = lines[i].vertcount;
} }
} }
gl_RenderState.Apply();
for (unsigned int i = 0; i < mPrimIndices.Size(); i += 2) for (unsigned int i = 0; i < mPrimIndices.Size(); i += 2)
{ {
GLRenderer->mVBO->RenderArray(GL_TRIANGLE_FAN, mPrimIndices[i], mPrimIndices[i + 1]); di->Draw(DT_TriangleFan, state, mPrimIndices[i], mPrimIndices[i + 1], i==0);
} }
if (NeedCap() && lines.Size() > 1) if (NeedCap() && lines.Size() > 1)
{ {
if (pass == STP_AllInOne) glDepthMask(false); // The cap's depth handling needs special treatment so that it won't block further portal caps.
else if (pass == STP_DepthRestore) glDepthRange(1, 1); if (pass == STP_DepthRestore) di->SetDepthRange(1, 1);
GLRenderer->mVBO->RenderArray(GL_TRIANGLE_FAN, FFlatVertexBuffer::STENCILTOP_INDEX, 4); di->Draw(DT_TriangleFan, state, FFlatVertexBuffer::STENCILTOP_INDEX, 4);
GLRenderer->mVBO->RenderArray(GL_TRIANGLE_FAN, FFlatVertexBuffer::STENCILBOTTOM_INDEX, 4); di->Draw(DT_TriangleFan, state, FFlatVertexBuffer::STENCILBOTTOM_INDEX, 4);
if (pass == STP_DepthRestore) glDepthRange(0, 1); if (pass == STP_DepthRestore) di->SetDepthRange(0, 1);
} }
} }
@ -120,58 +95,46 @@ void GLPortal::DrawPortalStencil(int pass)
void GLPortal::SetupStencil(HWDrawInfo *di, FRenderState &state, bool usestencil) void GLPortal::SetupStencil(HWDrawInfo *di, FRenderState &state, bool usestencil)
{ {
Clocker c(PortalAll);
rendered_portals++;
if (usestencil) if (usestencil)
{ {
// Create stencil // Create stencil
glStencilFunc(GL_EQUAL, screen->stencilValue, ~0); // create stencil state.SetEffect(EFF_STENCIL);
glStencilOp(GL_KEEP, GL_KEEP, GL_INCR); // increment stencil of valid pixels state.EnableTexture(false);
glColorMask(0, 0, 0, 0); // don't write to the graphics buffer state.ResetColor();
gl_RenderState.SetEffect(EFF_STENCIL);
gl_RenderState.EnableTexture(false);
gl_RenderState.ResetColor();
glDepthFunc(GL_LESS);
gl_RenderState.Apply();
if (NeedDepthBuffer()) if (NeedDepthBuffer())
{ {
glDepthMask(false); // don't write to Z-buffer! di->SetStencil(0, SOP_Increment, SF_ColorMaskOff | SF_DepthMaskOff);
di->SetDepthFunc(DF_Less);
DrawPortalStencil(STP_Stencil); DrawPortalStencil(di, state, STP_Stencil);
// Clear Z-buffer // Clear Z-buffer
glStencilFunc(GL_EQUAL, screen->stencilValue + 1, ~0); // draw sky into stencil di->SetStencil(1, SOP_Keep, SF_ColorMaskOff);
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); // this stage doesn't modify the stencil di->SetDepthRange(1, 1);
glDepthMask(true); // enable z-buffer again di->SetDepthFunc(DF_Always);
glDepthRange(1, 1); DrawPortalStencil(di, state, STP_DepthClear);
glDepthFunc(GL_ALWAYS);
DrawPortalStencil(STP_DepthClear);
// set normal drawing mode // set normal drawing mode
gl_RenderState.EnableTexture(true); state.EnableTexture(true);
glDepthFunc(GL_LESS); di->SetStencil(1, SOP_Keep, SF_AllOn);
glColorMask(1, 1, 1, 1); di->SetDepthRange(0, 1);
gl_RenderState.SetEffect(EFF_NONE); di->SetDepthFunc(DF_Less);
glDepthRange(0, 1); state.SetEffect(EFF_NONE);
GLuint sampleCount = 1;
} }
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
// No occlusion queries will be done here. For these portals the overhead is far greater
// than the benefit.
// 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!
di->SetStencil(0, SOP_Increment, SF_ColorMaskOff);
di->SetDepthFunc(DF_Less);
DrawPortalStencil(di, state, STP_AllInOne);
glDepthMask(true); di->SetStencil(1, SOP_Keep, SF_DepthTestOff | SF_DepthMaskOff);
DrawPortalStencil(STP_AllInOne); state.EnableTexture(true);
glStencilFunc(GL_EQUAL, screen->stencilValue + 1, ~0); // draw sky into stencil state.SetEffect(EFF_NONE);
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); // this stage doesn't modify the stencil
gl_RenderState.EnableTexture(true);
glColorMask(1, 1, 1, 1);
gl_RenderState.SetEffect(EFF_NONE);
glDisable(GL_DEPTH_TEST);
glDepthMask(false); // don't write to Z-buffer!
} }
screen->stencilValue++; screen->stencilValue++;
@ -180,139 +143,66 @@ void GLPortal::SetupStencil(HWDrawInfo *di, FRenderState &state, bool usestencil
{ {
if (!NeedDepthBuffer()) if (!NeedDepthBuffer())
{ {
glDepthMask(false); di->SetStencil(0, SOP_Keep, SF_DepthTestOff | SF_DepthMaskOff);
glDisable(GL_DEPTH_TEST);
} }
} }
// save viewpoint
savedvisibility = di->Viewpoint.camera ? di->Viewpoint.camera->renderflags & RF_MAYBEINVISIBLE : ActorRenderFlags::FromInt(0);
} }
void GLPortal::RemoveStencil(HWDrawInfo *di, FRenderState &state, bool usestencil) void GLPortal::RemoveStencil(HWDrawInfo *di, FRenderState &state, bool usestencil)
{ {
Clocker c(PortalAll);
bool needdepth = NeedDepthBuffer(); 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) if (usestencil)
{ {
glColorMask(0, 0, 0, 0); // no graphics state.SetEffect(EFF_NONE);
gl_RenderState.SetEffect(EFF_NONE); state.ResetColor();
gl_RenderState.ResetColor(); state.EnableTexture(false);
gl_RenderState.EnableTexture(false);
gl_RenderState.Apply();
if (needdepth) if (needdepth)
{ {
// first step: reset the depth buffer to max. depth // first step: reset the depth buffer to max. depth
glDepthRange(1, 1); // always di->SetStencil(0, SOP_Keep, SF_ColorMaskOff);
glDepthFunc(GL_ALWAYS); // write the farthest depth value di->SetDepthRange(1, 1); // always
DrawPortalStencil(STP_DepthClear); di->SetDepthFunc(DF_Always); // write the farthest depth value
} DrawPortalStencil(di, state, STP_DepthClear);
else
{
glEnable(GL_DEPTH_TEST);
} }
// 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
glDepthFunc(GL_LEQUAL); di->SetStencil(0, SOP_Decrement, SF_ColorMaskOff);
glDepthRange(0, 1); di->SetDepthRange(0, 1);
glStencilOp(GL_KEEP, GL_KEEP, GL_DECR); di->SetDepthFunc(DF_LEqual);
glStencilFunc(GL_EQUAL, screen->stencilValue, ~0); // draw sky into stencil DrawPortalStencil(di, state, STP_DepthRestore);
DrawPortalStencil(STP_DepthRestore);
glDepthFunc(GL_LESS);
state.EnableTexture(true);
gl_RenderState.EnableTexture(true); state.SetEffect(EFF_NONE);
gl_RenderState.SetEffect(EFF_NONE);
glColorMask(1, 1, 1, 1);
screen->stencilValue--; screen->stencilValue--;
// restore old stencil op.
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
glStencilFunc(GL_EQUAL, screen->stencilValue, ~0); // draw sky into stencil
} }
else else
{ {
if (needdepth) state.ResetColor();
{ state.SetEffect(EFF_STENCIL);
glClear(GL_DEPTH_BUFFER_BIT); state.EnableTexture(false);
} state.SetRenderStyle(STYLE_Source);
else
{ di->SetStencil(0, SOP_Keep, needdepth? SF_ColorMaskOff | SF_DepthClear : SF_ColorMaskOff);
glEnable(GL_DEPTH_TEST); di->SetDepthRange(0, 1);
glDepthMask(true); di->SetDepthFunc(DF_LEqual);
} DrawPortalStencil(di, state, STP_DepthRestore);
auto &vp = di->Viewpoint;
state.SetEffect(EFF_NONE);
// Restore the old view state.EnableTexture(true);
if (vp.camera != nullptr) vp.camera->renderflags = (vp.camera->renderflags & ~RF_MAYBEINVISIBLE) | savedvisibility;
// This draws a valid z-buffer into the stencil's contents to ensure it
// doesn't get overwritten by the level's geometry.
gl_RenderState.ResetColor();
glDepthFunc(GL_LEQUAL);
glDepthRange(0, 1);
glColorMask(0, 0, 0, 1); // mark portal in alpha channel but don't touch color
gl_RenderState.SetEffect(EFF_STENCIL);
gl_RenderState.EnableTexture(false);
gl_RenderState.SetRenderStyle(STYLE_Source);
gl_RenderState.Apply();
DrawPortalStencil(STP_DepthRestore);
gl_RenderState.SetEffect(EFF_NONE);
gl_RenderState.EnableTexture(true);
glColorMask(1, 1, 1, 1); // mark portal in alpha channel but don't touch color
glDepthFunc(GL_LESS);
} }
di->SetStencil(0, SOP_Keep, SF_AllOn);
} }
//-----------------------------------------------------------------------------
//
// Start
//
//-----------------------------------------------------------------------------
bool GLPortal::Start(bool usestencil, bool doquery, HWDrawInfo *outer_di, HWDrawInfo **pDi)
{
*pDi = nullptr;
rendered_portals++;
Clocker c(PortalAll);
if (!gl_portals)
{
return false;
}
SetupStencil(outer_di, gl_RenderState, usestencil);
*pDi = FDrawInfo::StartDrawInfo(outer_di->Viewpoint, &outer_di->VPUniforms);
(*pDi)->mCurrentPortal = this;
// save viewpoint
savedvisibility = outer_di->Viewpoint.camera ? outer_di->Viewpoint.camera->renderflags & RF_MAYBEINVISIBLE : ActorRenderFlags::FromInt(0);
return true;
}
//-----------------------------------------------------------------------------
//
// End
//
//-----------------------------------------------------------------------------
void GLPortal::End(HWDrawInfo *di, bool usestencil)
{
Clocker c(PortalAll);
di = static_cast<FDrawInfo*>(di)->EndDrawInfo();
GLRenderer->mViewpoints->Bind(static_cast<FDrawInfo*>(di)->vpIndex);
auto &vp = di->Viewpoint;
// Restore the old view
if (vp.camera != nullptr) vp.camera->renderflags = (vp.camera->renderflags & ~RF_MAYBEINVISIBLE) | savedvisibility;
RemoveStencil(di, gl_RenderState, usestencil);
}
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// //
@ -402,7 +292,7 @@ void GLHorizonPortal::DrawContents(HWDrawInfo *hwdi)
gltexture=FMaterial::ValidateTexture(sp->texture, false, true); gltexture=FMaterial::ValidateTexture(sp->texture, false, true);
if (!gltexture) if (!gltexture)
{ {
ClearScreen(di); di->ClearScreen();
return; return;
} }
di->SetCameraPos(vp.Pos); di->SetCameraPos(vp.Pos);

View file

@ -58,11 +58,12 @@ private:
STP_DepthRestore, STP_DepthRestore,
STP_AllInOne STP_AllInOne
}; };
void DrawPortalStencil(int pass); void DrawPortalStencil(HWDrawInfo *di, FRenderState &state, int pass);
ActorRenderFlags savedvisibility; ActorRenderFlags savedvisibility;
TArray<unsigned int> mPrimIndices; TArray<unsigned int> mPrimIndices;
public:
void SetupStencil(HWDrawInfo *di, FRenderState &state, bool usestencil); void SetupStencil(HWDrawInfo *di, FRenderState &state, bool usestencil);
void RemoveStencil(HWDrawInfo *di, FRenderState &state, bool usestencil); void RemoveStencil(HWDrawInfo *di, FRenderState &state, bool usestencil);
@ -70,10 +71,6 @@ protected:
int level; int level;
GLPortal(FPortalSceneState *state, bool local = false) : IPortal(state, local) { } GLPortal(FPortalSceneState *state, bool local = false) : IPortal(state, local) { }
bool Start(bool usestencil, bool doquery, HWDrawInfo *outer_di, HWDrawInfo **pDi) override;
void End(HWDrawInfo *di, bool usestencil) override;
void ClearScreen(HWDrawInfo *di);
}; };
class GLScenePortal : public GLPortal class GLScenePortal : public GLPortal
@ -98,7 +95,7 @@ public:
static_cast<FDrawInfo*>(di)->DrawScene(DM_PORTAL); static_cast<FDrawInfo*>(di)->DrawScene(DM_PORTAL);
mScene->Shutdown(di); mScene->Shutdown(di);
} }
else ClearScreen(di); else di->ClearScreen();
} }
virtual void RenderAttached(HWDrawInfo *di) { return mScene->RenderAttached(di); } virtual void RenderAttached(HWDrawInfo *di) { return mScene->RenderAttached(di); }
}; };

View file

@ -29,7 +29,8 @@ enum EStencilFlags
SF_AllOn = 0, SF_AllOn = 0,
SF_ColorMaskOff = 1, SF_ColorMaskOff = 1,
SF_DepthMaskOff = 2, SF_DepthMaskOff = 2,
SF_DepthTestOff = 4 SF_DepthTestOff = 4,
SF_DepthClear = 8
}; };
enum EStencilOp enum EStencilOp
@ -332,16 +333,18 @@ public:
virtual std::pair<FFlatVertex *, unsigned int> AllocVertices(unsigned int count) = 0; virtual std::pair<FFlatVertex *, unsigned int> AllocVertices(unsigned int count) = 0;
virtual void ClearScreen() = 0;
virtual void Draw(EDrawType dt, FRenderState &state, int index, int count, bool apply = true) = 0; virtual void Draw(EDrawType dt, FRenderState &state, int index, int count, bool apply = true) = 0;
virtual void DrawIndexed(EDrawType dt, FRenderState &state, int index, int count, bool apply = true) = 0; virtual void DrawIndexed(EDrawType dt, FRenderState &state, int index, int count, bool apply = true) = 0;
virtual void DrawModel(GLSprite *spr, FRenderState &state) = 0; virtual void DrawModel(GLSprite *spr, FRenderState &state) = 0;
virtual void DrawHUDModel(HUDSprite *spr, FRenderState &state) = 0; virtual void DrawHUDModel(HUDSprite *spr, FRenderState &state) = 0;
virtual void RenderPortal(IPortal *p, bool usestencil) = 0;
// Immediate render state change commands. These only change infrequently and should not clutter the render state. // Immediate render state change commands. These only change infrequently and should not clutter the render state.
virtual void SetDepthMask(bool on) = 0; virtual void SetDepthMask(bool on) = 0;
virtual void SetDepthFunc(int func) = 0; virtual void SetDepthFunc(int func) = 0;
virtual void SetDepthRange(float min, float max) = 0;
virtual void EnableDrawBufferAttachments(bool on) = 0; virtual void EnableDrawBufferAttachments(bool on) = 0;
virtual void SetStencil(int offs, int op, int flags) = 0; virtual void SetStencil(int offs, int op, int flags) = 0;

View file

@ -34,6 +34,7 @@
#include "g_levellocals.h" #include "g_levellocals.h"
EXTERN_CVAR(Int, r_mirror_recursions) EXTERN_CVAR(Int, r_mirror_recursions)
EXTERN_CVAR(Bool, gl_portals)
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// //
@ -82,20 +83,15 @@ void FPortalSceneState::EndFrame(HWDrawInfo *di)
indent += " "; indent += " ";
} }
// Only use occlusion query if there are more than 2 portals.
// Otherwise there's too much overhead.
// (And don't forget to consider the separating null pointers!)
bool usequery = di->Portals.Size() > 2 + (unsigned)renderdepth;
while (di->Portals.Pop(p) && p) while (di->Portals.Pop(p) && p)
{ {
if (gl_portalinfo) if (gl_portalinfo)
{ {
Printf("%sProcessing %s, depth = %d, query = %d\n", indent.GetChars(), p->GetName(), renderdepth, usequery); Printf("%sProcessing %s, depth = %d\n", indent.GetChars(), p->GetName(), renderdepth);
} }
if (p->lines.Size() > 0) if (p->lines.Size() > 0)
{ {
p->RenderPortal(true, usequery, di); RenderPortal(p, true, di);
} }
delete p; delete p;
} }
@ -146,13 +142,20 @@ bool FPortalSceneState::RenderFirstSkyPortal(int recursion, HWDrawInfo *outer_di
if (best) if (best)
{ {
portals.Delete(bestindex); portals.Delete(bestindex);
best->RenderPortal(false, false, outer_di); RenderPortal(best, false, outer_di);
delete best; delete best;
return true; return true;
} }
return false; return false;
} }
void FPortalSceneState::RenderPortal(IPortal *p, bool usestencil, HWDrawInfo *outer_di)
{
if (gl_portals) outer_di->RenderPortal(p, usestencil);
}
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// //
// //

View file

@ -53,27 +53,12 @@ public:
virtual bool NeedDepthBuffer() { return true; } virtual bool NeedDepthBuffer() { return true; }
virtual void DrawContents(HWDrawInfo *di) = 0; virtual void DrawContents(HWDrawInfo *di) = 0;
virtual void RenderAttached(HWDrawInfo *di) {} virtual void RenderAttached(HWDrawInfo *di) {}
virtual bool Start(bool usestencil, bool doquery, HWDrawInfo *outer_di, HWDrawInfo **pDi) = 0;
virtual void End(HWDrawInfo *di, bool usestencil) = 0;
void AddLine(GLWall * l) void AddLine(GLWall * l)
{ {
lines.Push(*l); lines.Push(*l);
} }
void RenderPortal(bool usestencil, bool doquery, HWDrawInfo *outer_di)
{
// Start may perform an occlusion query. If that returns 0 there
// is no need to draw the stencil's contents and there's also no
// need to restore the affected area becasue there is none!
HWDrawInfo *di;
if (Start(usestencil, doquery, outer_di, &di))
{
DrawContents(di);
End(di, usestencil);
}
}
}; };
@ -107,8 +92,7 @@ struct FPortalSceneState
void StartFrame(); void StartFrame();
bool RenderFirstSkyPortal(int recursion, HWDrawInfo *outer_di); bool RenderFirstSkyPortal(int recursion, HWDrawInfo *outer_di);
void EndFrame(HWDrawInfo *outer_di); void EndFrame(HWDrawInfo *outer_di);
void RenderPortal(IPortal *p, bool usestencil, HWDrawInfo *outer_di);
}; };
inline IPortal::IPortal(FPortalSceneState *s, bool local) : mState(s) inline IPortal::IPortal(FPortalSceneState *s, bool local) : mState(s)
@ -117,8 +101,6 @@ inline IPortal::IPortal(FPortalSceneState *s, bool local) : mState(s)
} }
class HWScenePortalBase class HWScenePortalBase
{ {
protected: protected: