mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-11 07:11:54 +00:00
- 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:
parent
93dac4e4d8
commit
3e4dcbe2b4
7 changed files with 131 additions and 210 deletions
|
@ -40,6 +40,7 @@
|
|||
#include "hwrenderer/scene/hw_clipper.h"
|
||||
#include "gl/scene/gl_portal.h"
|
||||
#include "gl/renderer/gl_renderstate.h"
|
||||
#include "gl/data/gl_viewpointbuffer.h"
|
||||
#include "gl/dynlights/gl_lightbuffer.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);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
|
@ -323,6 +336,11 @@ void FDrawInfo::SetDepthFunc(int func)
|
|||
glDepthFunc(df2gl[func]);
|
||||
}
|
||||
|
||||
void FDrawInfo::SetDepthRange(float min, float max)
|
||||
{
|
||||
glDepthRange(min, max);
|
||||
}
|
||||
|
||||
void FDrawInfo::EnableDrawBufferAttachments(bool on)
|
||||
{
|
||||
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);
|
||||
else
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -47,9 +47,11 @@ struct FDrawInfo : public HWDrawInfo
|
|||
void DrawIndexed(EDrawType dt, FRenderState &state, int index, int count, bool apply = true) override;
|
||||
void DrawModel(GLSprite *spr, FRenderState &state) override;
|
||||
void DrawHUDModel(HUDSprite *spr, FRenderState &state) override;
|
||||
void RenderPortal(IPortal *p, bool stencil) override;
|
||||
|
||||
void SetDepthMask(bool on) override;
|
||||
void SetDepthFunc(int func) override;
|
||||
void SetDepthRange(float min, float max) override;
|
||||
void EnableDrawBufferAttachments(bool on) override;
|
||||
void SetStencil(int offs, int op, int flags) override;
|
||||
|
||||
|
@ -69,6 +71,7 @@ struct FDrawInfo : public HWDrawInfo
|
|||
void EndDrawScene(sector_t * viewsector);
|
||||
void DrawEndScene2D(sector_t * viewsector);
|
||||
bool SetDepthClamp(bool on) override;
|
||||
void ClearScreen() override;
|
||||
|
||||
static FDrawInfo *StartDrawInfo(FRenderViewpoint &parentvp, HWViewpointUniforms *uniforms);
|
||||
FDrawInfo *EndDrawInfo();
|
||||
|
|
|
@ -54,38 +54,14 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
EXTERN_CVAR(Bool, gl_portals)
|
||||
EXTERN_CVAR(Bool, gl_noquery)
|
||||
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
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
void GLPortal::DrawPortalStencil(int pass)
|
||||
void GLPortal::DrawPortalStencil(HWDrawInfo *di, FRenderState &state, int pass)
|
||||
{
|
||||
if (mPrimIndices.Size() == 0)
|
||||
{
|
||||
|
@ -97,18 +73,17 @@ void GLPortal::DrawPortalStencil(int pass)
|
|||
mPrimIndices[i * 2 + 1] = lines[i].vertcount;
|
||||
}
|
||||
}
|
||||
gl_RenderState.Apply();
|
||||
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 (pass == STP_AllInOne) glDepthMask(false);
|
||||
else if (pass == STP_DepthRestore) glDepthRange(1, 1);
|
||||
GLRenderer->mVBO->RenderArray(GL_TRIANGLE_FAN, FFlatVertexBuffer::STENCILTOP_INDEX, 4);
|
||||
GLRenderer->mVBO->RenderArray(GL_TRIANGLE_FAN, FFlatVertexBuffer::STENCILBOTTOM_INDEX, 4);
|
||||
if (pass == STP_DepthRestore) glDepthRange(0, 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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -120,58 +95,46 @@ void GLPortal::DrawPortalStencil(int pass)
|
|||
|
||||
void GLPortal::SetupStencil(HWDrawInfo *di, FRenderState &state, bool usestencil)
|
||||
{
|
||||
Clocker c(PortalAll);
|
||||
|
||||
rendered_portals++;
|
||||
if (usestencil)
|
||||
{
|
||||
|
||||
// Create stencil
|
||||
glStencilFunc(GL_EQUAL, screen->stencilValue, ~0); // create stencil
|
||||
glStencilOp(GL_KEEP, GL_KEEP, GL_INCR); // increment stencil of valid pixels
|
||||
glColorMask(0, 0, 0, 0); // don't write to the graphics buffer
|
||||
gl_RenderState.SetEffect(EFF_STENCIL);
|
||||
gl_RenderState.EnableTexture(false);
|
||||
gl_RenderState.ResetColor();
|
||||
glDepthFunc(GL_LESS);
|
||||
gl_RenderState.Apply();
|
||||
state.SetEffect(EFF_STENCIL);
|
||||
state.EnableTexture(false);
|
||||
state.ResetColor();
|
||||
|
||||
if (NeedDepthBuffer())
|
||||
{
|
||||
glDepthMask(false); // don't write to Z-buffer!
|
||||
|
||||
DrawPortalStencil(STP_Stencil);
|
||||
di->SetStencil(0, SOP_Increment, SF_ColorMaskOff | SF_DepthMaskOff);
|
||||
di->SetDepthFunc(DF_Less);
|
||||
DrawPortalStencil(di, state, STP_Stencil);
|
||||
|
||||
// Clear Z-buffer
|
||||
glStencilFunc(GL_EQUAL, screen->stencilValue + 1, ~0); // draw sky into stencil
|
||||
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); // this stage doesn't modify the stencil
|
||||
glDepthMask(true); // enable z-buffer again
|
||||
glDepthRange(1, 1);
|
||||
glDepthFunc(GL_ALWAYS);
|
||||
DrawPortalStencil(STP_DepthClear);
|
||||
di->SetStencil(1, SOP_Keep, SF_ColorMaskOff);
|
||||
di->SetDepthRange(1, 1);
|
||||
di->SetDepthFunc(DF_Always);
|
||||
DrawPortalStencil(di, state, STP_DepthClear);
|
||||
|
||||
// set normal drawing mode
|
||||
gl_RenderState.EnableTexture(true);
|
||||
glDepthFunc(GL_LESS);
|
||||
glColorMask(1, 1, 1, 1);
|
||||
gl_RenderState.SetEffect(EFF_NONE);
|
||||
glDepthRange(0, 1);
|
||||
|
||||
GLuint sampleCount = 1;
|
||||
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
|
||||
// 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!
|
||||
di->SetStencil(0, SOP_Increment, SF_ColorMaskOff);
|
||||
di->SetDepthFunc(DF_Less);
|
||||
DrawPortalStencil(di, state, STP_AllInOne);
|
||||
|
||||
glDepthMask(true);
|
||||
DrawPortalStencil(STP_AllInOne);
|
||||
glStencilFunc(GL_EQUAL, screen->stencilValue + 1, ~0); // draw sky into stencil
|
||||
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!
|
||||
di->SetStencil(1, SOP_Keep, SF_DepthTestOff | SF_DepthMaskOff);
|
||||
state.EnableTexture(true);
|
||||
state.SetEffect(EFF_NONE);
|
||||
}
|
||||
|
||||
screen->stencilValue++;
|
||||
|
@ -180,139 +143,66 @@ void GLPortal::SetupStencil(HWDrawInfo *di, FRenderState &state, bool usestencil
|
|||
{
|
||||
if (!NeedDepthBuffer())
|
||||
{
|
||||
glDepthMask(false);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
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)
|
||||
{
|
||||
glColorMask(0, 0, 0, 0); // no graphics
|
||||
gl_RenderState.SetEffect(EFF_NONE);
|
||||
gl_RenderState.ResetColor();
|
||||
gl_RenderState.EnableTexture(false);
|
||||
gl_RenderState.Apply();
|
||||
state.SetEffect(EFF_NONE);
|
||||
state.ResetColor();
|
||||
state.EnableTexture(false);
|
||||
|
||||
if (needdepth)
|
||||
{
|
||||
// first step: reset the depth buffer to max. depth
|
||||
glDepthRange(1, 1); // always
|
||||
glDepthFunc(GL_ALWAYS); // write the farthest depth value
|
||||
DrawPortalStencil(STP_DepthClear);
|
||||
}
|
||||
else
|
||||
{
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
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
|
||||
glDepthFunc(GL_LEQUAL);
|
||||
glDepthRange(0, 1);
|
||||
glStencilOp(GL_KEEP, GL_KEEP, GL_DECR);
|
||||
glStencilFunc(GL_EQUAL, screen->stencilValue, ~0); // draw sky into stencil
|
||||
DrawPortalStencil(STP_DepthRestore);
|
||||
glDepthFunc(GL_LESS);
|
||||
di->SetStencil(0, SOP_Decrement, SF_ColorMaskOff);
|
||||
di->SetDepthRange(0, 1);
|
||||
di->SetDepthFunc(DF_LEqual);
|
||||
DrawPortalStencil(di, state, STP_DepthRestore);
|
||||
|
||||
|
||||
gl_RenderState.EnableTexture(true);
|
||||
gl_RenderState.SetEffect(EFF_NONE);
|
||||
glColorMask(1, 1, 1, 1);
|
||||
state.EnableTexture(true);
|
||||
state.SetEffect(EFF_NONE);
|
||||
screen->stencilValue--;
|
||||
|
||||
// restore old stencil op.
|
||||
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
|
||||
glStencilFunc(GL_EQUAL, screen->stencilValue, ~0); // draw sky into stencil
|
||||
}
|
||||
else
|
||||
{
|
||||
if (needdepth)
|
||||
{
|
||||
glClear(GL_DEPTH_BUFFER_BIT);
|
||||
}
|
||||
else
|
||||
{
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glDepthMask(true);
|
||||
}
|
||||
auto &vp = di->Viewpoint;
|
||||
state.ResetColor();
|
||||
state.SetEffect(EFF_STENCIL);
|
||||
state.EnableTexture(false);
|
||||
state.SetRenderStyle(STYLE_Source);
|
||||
|
||||
// Restore the old view
|
||||
if (vp.camera != nullptr) vp.camera->renderflags = (vp.camera->renderflags & ~RF_MAYBEINVISIBLE) | savedvisibility;
|
||||
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);
|
||||
|
||||
// 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);
|
||||
state.SetEffect(EFF_NONE);
|
||||
state.EnableTexture(true);
|
||||
}
|
||||
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);
|
||||
if (!gltexture)
|
||||
{
|
||||
ClearScreen(di);
|
||||
di->ClearScreen();
|
||||
return;
|
||||
}
|
||||
di->SetCameraPos(vp.Pos);
|
||||
|
|
|
@ -58,11 +58,12 @@ private:
|
|||
STP_DepthRestore,
|
||||
STP_AllInOne
|
||||
};
|
||||
void DrawPortalStencil(int pass);
|
||||
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);
|
||||
|
||||
|
@ -70,10 +71,6 @@ protected:
|
|||
int level;
|
||||
|
||||
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
|
||||
|
@ -98,7 +95,7 @@ public:
|
|||
static_cast<FDrawInfo*>(di)->DrawScene(DM_PORTAL);
|
||||
mScene->Shutdown(di);
|
||||
}
|
||||
else ClearScreen(di);
|
||||
else di->ClearScreen();
|
||||
}
|
||||
virtual void RenderAttached(HWDrawInfo *di) { return mScene->RenderAttached(di); }
|
||||
};
|
||||
|
|
|
@ -29,7 +29,8 @@ enum EStencilFlags
|
|||
SF_AllOn = 0,
|
||||
SF_ColorMaskOff = 1,
|
||||
SF_DepthMaskOff = 2,
|
||||
SF_DepthTestOff = 4
|
||||
SF_DepthTestOff = 4,
|
||||
SF_DepthClear = 8
|
||||
};
|
||||
|
||||
enum EStencilOp
|
||||
|
@ -332,16 +333,18 @@ public:
|
|||
|
||||
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 DrawIndexed(EDrawType dt, FRenderState &state, int index, int count, bool apply = true) = 0;
|
||||
virtual void DrawModel(GLSprite *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.
|
||||
virtual void SetDepthMask(bool on) = 0;
|
||||
virtual void SetDepthFunc(int func) = 0;
|
||||
virtual void SetDepthRange(float min, float max) = 0;
|
||||
virtual void EnableDrawBufferAttachments(bool on) = 0;
|
||||
virtual void SetStencil(int offs, int op, int flags) = 0;
|
||||
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
#include "g_levellocals.h"
|
||||
|
||||
EXTERN_CVAR(Int, r_mirror_recursions)
|
||||
EXTERN_CVAR(Bool, gl_portals)
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
|
@ -82,20 +83,15 @@ void FPortalSceneState::EndFrame(HWDrawInfo *di)
|
|||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
p->RenderPortal(true, usequery, di);
|
||||
RenderPortal(p, true, di);
|
||||
}
|
||||
delete p;
|
||||
}
|
||||
|
@ -146,13 +142,20 @@ bool FPortalSceneState::RenderFirstSkyPortal(int recursion, HWDrawInfo *outer_di
|
|||
if (best)
|
||||
{
|
||||
portals.Delete(bestindex);
|
||||
best->RenderPortal(false, false, outer_di);
|
||||
RenderPortal(best, false, outer_di);
|
||||
delete best;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void FPortalSceneState::RenderPortal(IPortal *p, bool usestencil, HWDrawInfo *outer_di)
|
||||
{
|
||||
if (gl_portals) outer_di->RenderPortal(p, usestencil);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
|
|
|
@ -53,27 +53,12 @@ public:
|
|||
virtual bool NeedDepthBuffer() { return true; }
|
||||
virtual void DrawContents(HWDrawInfo *di) = 0;
|
||||
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)
|
||||
{
|
||||
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();
|
||||
bool RenderFirstSkyPortal(int recursion, 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)
|
||||
|
@ -117,8 +101,6 @@ inline IPortal::IPortal(FPortalSceneState *s, bool local) : mState(s)
|
|||
}
|
||||
|
||||
|
||||
|
||||
|
||||
class HWScenePortalBase
|
||||
{
|
||||
protected:
|
||||
|
|
Loading…
Reference in a new issue