mirror of
https://github.com/ZDoom/gzdoom.git
synced 2025-02-03 15:11:42 +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 "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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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); }
|
||||||
};
|
};
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
|
|
|
@ -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:
|
||||||
|
|
Loading…
Reference in a new issue