diff --git a/src/gl/renderer/gl_renderer.cpp b/src/gl/renderer/gl_renderer.cpp index ee5ca09b2..80cdc3dbc 100644 --- a/src/gl/renderer/gl_renderer.cpp +++ b/src/gl/renderer/gl_renderer.cpp @@ -440,7 +440,7 @@ void FGLRenderer::Draw2D(F2DDrawer *drawer) FDrawInfo di; // For access to the virtual interface. This should be placed elsewhere... const auto &mScreenViewport = screen->mScreenViewport; glViewport(mScreenViewport.left, mScreenViewport.top, mScreenViewport.width, mScreenViewport.height); - screen->mViewpoints->Set2D(&di, screen->GetWidth(), screen->GetHeight()); + screen->mViewpoints->Set2D(gl_RenderState, screen->GetWidth(), screen->GetHeight()); glDisable(GL_DEPTH_TEST); diff --git a/src/gl/renderer/gl_renderstate.cpp b/src/gl/renderer/gl_renderstate.cpp index 4cf498c29..f2c66ac63 100644 --- a/src/gl/renderer/gl_renderstate.cpp +++ b/src/gl/renderer/gl_renderstate.cpp @@ -39,6 +39,8 @@ #include "gl/renderer/gl_renderbuffers.h" #include "gl/textures/gl_hwtexture.h" #include "gl/system/gl_buffers.h" +#include "hwrenderer/utility/hw_clock.h" +#include "hwrenderer/data/hw_viewpointbuffer.h" FGLRenderState gl_RenderState; @@ -375,3 +377,144 @@ void FGLRenderState::ApplyBlendMode() } } + +//========================================================================== +// +// API dependent draw calls +// +//========================================================================== + +static int dt2gl[] = { GL_POINTS, GL_LINES, GL_TRIANGLES, GL_TRIANGLE_FAN, GL_TRIANGLE_STRIP }; + +void FGLRenderState::Draw(int dt, int index, int count, bool apply) +{ + assert(this == &gl_RenderState); + if (apply) + { + gl_RenderState.Apply(); + } + drawcalls.Clock(); + glDrawArrays(dt2gl[dt], index, count); + drawcalls.Unclock(); +} + +void FGLRenderState::DrawIndexed(int dt, int index, int count, bool apply) +{ + assert(this == &gl_RenderState); + if (apply) + { + gl_RenderState.Apply(); + } + drawcalls.Clock(); + glDrawElements(dt2gl[dt], count, GL_UNSIGNED_INT, (void*)(intptr_t)(index * sizeof(uint32_t))); + drawcalls.Unclock(); +} + +void FGLRenderState::SetDepthMask(bool on) +{ + glDepthMask(on); +} + +void FGLRenderState::SetDepthFunc(int func) +{ + static int df2gl[] = { GL_LESS, GL_LEQUAL, GL_ALWAYS }; + glDepthFunc(df2gl[func]); +} + +void FGLRenderState::SetDepthRange(float min, float max) +{ + glDepthRange(min, max); +} + +void FGLRenderState::EnableDrawBufferAttachments(bool on) +{ + EnableDrawBuffers(on ? gl_RenderState.GetPassDrawBufferCount() : 1); +} + +void FGLRenderState::SetStencil(int offs, int op, int flags) +{ + static int op2gl[] = { GL_KEEP, GL_INCR, GL_DECR }; + + glStencilFunc(GL_EQUAL, screen->stencilValue + offs, ~0); // draw sky into stencil + glStencilOp(GL_KEEP, GL_KEEP, op2gl[op]); // this stage doesn't modify the stencil + + bool cmon = !(flags & SF_ColorMaskOff); + glColorMask(cmon, cmon, cmon, cmon); // don't write to the graphics buffer + glDepthMask(!(flags & SF_DepthMaskOff)); + if (flags & SF_DepthTestOff) + glDisable(GL_DEPTH_TEST); + else + glEnable(GL_DEPTH_TEST); + if (flags & SF_DepthClear) + glClear(GL_DEPTH_BUFFER_BIT); +} + +void FGLRenderState::SetCulling(int mode) +{ + if (mode != Cull_None) + { + glEnable(GL_CULL_FACE); + glFrontFace(mode == Cull_CCW ? GL_CCW : GL_CW); + } + else + { + glDisable(GL_CULL_FACE); + } +} + +void FGLRenderState::EnableClipDistance(int num, bool state) +{ + // Update the viewpoint-related clip plane setting. + if (!(gl.flags & RFL_NO_CLIP_PLANES)) + { + if (state) + { + glEnable(GL_CLIP_DISTANCE0 + num); + } + else + { + glDisable(GL_CLIP_DISTANCE0 + num); + } + } +} + +//========================================================================== +// +// +// +//========================================================================== +void FGLRenderState::ClearScreen() +{ + bool multi = !!glIsEnabled(GL_MULTISAMPLE); + + screen->mViewpoints->Set2D(*this, SCREENWIDTH, SCREENHEIGHT); + SetColor(0, 0, 0); + 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); +} + + + +//========================================================================== +// +// Below are less frequently altrered state settings which do not get +// buffered by the state object, but set directly instead. +// +//========================================================================== + +bool FGLRenderState::SetDepthClamp(bool on) +{ + bool res = mLastDepthClamp; + if (!on) glDisable(GL_DEPTH_CLAMP); + else glEnable(GL_DEPTH_CLAMP); + mLastDepthClamp = on; + return res; +} + diff --git a/src/gl/renderer/gl_renderstate.h b/src/gl/renderer/gl_renderstate.h index b888c91f3..8d0f78718 100644 --- a/src/gl/renderer/gl_renderstate.h +++ b/src/gl/renderer/gl_renderstate.h @@ -115,16 +115,6 @@ public: mSpecularLevel = specularLevel; } - // This wraps the depth clamp setting because we frequently need to read it which OpenGL is not particularly performant at... - bool SetDepthClamp(bool on) - { - bool res = mLastDepthClamp; - if (!on) glDisable(GL_DEPTH_CLAMP); - else glEnable(GL_DEPTH_CLAMP); - mLastDepthClamp = on; - return res; - } - void SetPassType(EPassType passType) { mPassType = passType; @@ -151,6 +141,20 @@ public: return mPassType == GBUFFER_PASS ? 3 : 1; } + void ClearScreen() override; + void Draw(int dt, int index, int count, bool apply = true) override; + void DrawIndexed(int dt, int index, int count, bool apply = true) override; + + bool SetDepthClamp(bool on) 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; + void SetCulling(int mode) override; + void EnableClipDistance(int num, bool state) override; + + }; extern FGLRenderState gl_RenderState; diff --git a/src/gl/scene/gl_drawinfo.cpp b/src/gl/scene/gl_drawinfo.cpp index db01ed6fc..90fc1d75e 100644 --- a/src/gl/scene/gl_drawinfo.cpp +++ b/src/gl/scene/gl_drawinfo.cpp @@ -19,13 +19,6 @@ // //-------------------------------------------------------------------------- // -/* -** gl_drawinfo.cpp -** Implements the draw info structure which contains most of the -** data in a scene and the draw lists - including a very thorough BSP -** style sorting algorithm for translucent objects. -** -*/ #include "gl_load/gl_system.h" #include "r_sky.h" @@ -35,7 +28,6 @@ #include "tarray.h" #include "hwrenderer/scene/hw_drawstructs.h" #include "hwrenderer/data/flatvertices.h" -#include "hwrenderer/utility/hw_clock.h" #include "gl/scene/gl_drawinfo.h" #include "hwrenderer/scene/hw_clipper.h" @@ -45,43 +37,6 @@ #include "hwrenderer/dynlights/hw_lightbuffer.h" #include "hwrenderer/models/hw_models.h" -bool FDrawInfo::SetDepthClamp(bool on) -{ - return gl_RenderState.SetDepthClamp(on); -} - -//========================================================================== -// -// -// -//========================================================================== - -static int dt2gl[] = { GL_POINTS, GL_LINES, GL_TRIANGLES, GL_TRIANGLE_FAN, GL_TRIANGLE_STRIP }; - -void FDrawInfo::Draw(EDrawType dt, FRenderState &state, int index, int count, bool apply) -{ - assert(&state == &gl_RenderState); - if (apply) - { - gl_RenderState.Apply(); - } - drawcalls.Clock(); - glDrawArrays(dt2gl[dt], index, count); - drawcalls.Unclock(); -} - -void FDrawInfo::DrawIndexed(EDrawType dt, FRenderState &state, int index, int count, bool apply) -{ - assert(&state == &gl_RenderState); - if (apply) - { - gl_RenderState.Apply(); - } - drawcalls.Clock(); - glDrawElements(dt2gl[dt], count, GL_UNSIGNED_INT, (void*)(intptr_t)(index * sizeof(uint32_t))); - drawcalls.Unclock(); -} - void FDrawInfo::RenderPortal(HWPortal *p, bool usestencil) { auto gp = static_cast(p); @@ -92,99 +47,8 @@ void FDrawInfo::RenderPortal(HWPortal *p, bool usestencil) gp->DrawContents(new_di, gl_RenderState); new_di->EndDrawInfo(); screen->mVertexData->Bind(gl_RenderState); - screen->mViewpoints->Bind(this, vpIndex); + screen->mViewpoints->Bind(gl_RenderState, vpIndex); gp->RemoveStencil(this, gl_RenderState, usestencil); } -void FDrawInfo::SetDepthMask(bool on) -{ - glDepthMask(on); -} - -void FDrawInfo::SetDepthFunc(int func) -{ - static int df2gl[] = { GL_LESS, GL_LEQUAL, GL_ALWAYS }; - 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); -} - -void FDrawInfo::SetStencil(int offs, int op, int flags) -{ - static int op2gl[] = { GL_KEEP, GL_INCR, GL_DECR }; - - glStencilFunc(GL_EQUAL, screen->stencilValue + offs, ~0); // draw sky into stencil - glStencilOp(GL_KEEP, GL_KEEP, op2gl[op]); // this stage doesn't modify the stencil - - bool cmon = !(flags & SF_ColorMaskOff); - glColorMask(cmon, cmon, cmon, cmon); // don't write to the graphics buffer - glDepthMask(!(flags & SF_DepthMaskOff)); - if (flags & SF_DepthTestOff) - glDisable(GL_DEPTH_TEST); - else - glEnable(GL_DEPTH_TEST); - if (flags & SF_DepthClear) - glClear(GL_DEPTH_BUFFER_BIT); -} - -void FDrawInfo::SetCulling(int mode) -{ - if (mode != Cull_None) - { - glEnable(GL_CULL_FACE); - glFrontFace(mode == Cull_CCW ? GL_CCW : GL_CW); - } - else - { - glDisable(GL_CULL_FACE); - } -} - -void FDrawInfo::EnableClipDistance(int num, bool state) -{ - // Update the viewpoint-related clip plane setting. - if (!(gl.flags & RFL_NO_CLIP_PLANES)) - { - if (state) - { - glEnable(GL_CLIP_DISTANCE0+num); - } - else - { - glDisable(GL_CLIP_DISTANCE0+num); - } - } -} - -//========================================================================== -// -// -// -//========================================================================== -void FDrawInfo::ClearScreen() -{ - bool multi = !!glIsEnabled(GL_MULTISAMPLE); - - screen->mViewpoints->Set2D(this, 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); -} - - diff --git a/src/gl/scene/gl_drawinfo.h b/src/gl/scene/gl_drawinfo.h index 8ebf3142c..71928119d 100644 --- a/src/gl/scene/gl_drawinfo.h +++ b/src/gl/scene/gl_drawinfo.h @@ -13,19 +13,8 @@ struct FDrawInfo : public HWDrawInfo { - - void Draw(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 RenderPortal(HWPortal *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; - void SetCulling(int mode) override; - void EnableClipDistance(int num, bool state) override; - void CreateScene(); void RenderScene(int recursion); void RenderTranslucent(); @@ -33,7 +22,5 @@ struct FDrawInfo : public HWDrawInfo void ProcessScene(bool toscreen = false); void EndDrawScene(sector_t * viewsector); void DrawEndScene2D(sector_t * viewsector); - bool SetDepthClamp(bool on) override; - void ClearScreen() override; }; #endif diff --git a/src/gl/scene/gl_scene.cpp b/src/gl/scene/gl_scene.cpp index d462360b1..4e88c4364 100644 --- a/src/gl/scene/gl_scene.cpp +++ b/src/gl/scene/gl_scene.cpp @@ -275,7 +275,7 @@ void FDrawInfo::DrawScene(int drawmode) GLRenderer->mBuffers->BindSceneFB(true); gl_RenderState.EnableDrawBuffers(gl_RenderState.GetPassDrawBufferCount()); gl_RenderState.Apply(); - screen->mViewpoints->Bind(this, vpIndex); + screen->mViewpoints->Bind(gl_RenderState, vpIndex); } // Handle all portals after rendering the opaque objects but before @@ -324,7 +324,7 @@ void FDrawInfo::DrawEndScene2D(sector_t * viewsector) HWViewpointUniforms vp = VPUniforms; vp.mViewMatrix.loadIdentity(); vp.mProjectionMatrix = vrmode->GetHUDSpriteProjection(); - screen->mViewpoints->SetViewpoint(this, &vp); + screen->mViewpoints->SetViewpoint(gl_RenderState, &vp); glDisable(GL_DEPTH_TEST); glDisable(GL_MULTISAMPLE); @@ -426,7 +426,7 @@ sector_t * FGLRenderer::RenderViewpoint (FRenderViewpoint &mainvp, AActor * came di->VPUniforms.mProjectionMatrix = eye.GetProjection(fov, ratio, fovratio); // Stereo mode specific viewpoint adjustment vp.Pos += eye.GetViewShift(vp.HWAngles.Yaw.Degrees); - di->SetupView(vp.Pos.X, vp.Pos.Y, vp.Pos.Z, false, false); + di->SetupView(gl_RenderState, vp.Pos.X, vp.Pos.Y, vp.Pos.Z, false, false); di->ProcessScene(toscreen); diff --git a/src/hwrenderer/data/hw_viewpointbuffer.cpp b/src/hwrenderer/data/hw_viewpointbuffer.cpp index fca488d44..da103063b 100644 --- a/src/hwrenderer/data/hw_viewpointbuffer.cpp +++ b/src/hwrenderer/data/hw_viewpointbuffer.cpp @@ -28,6 +28,7 @@ #include "hwrenderer/data/shaderuniforms.h" #include "hwrenderer/scene/hw_viewpointuniforms.h" #include "hwrenderer/scene/hw_drawinfo.h" +#include "hwrenderer/scene/hw_renderstate.h" #include "hw_viewpointbuffer.h" static const int INITIAL_BUFFER_SIZE = 100; // 100 viewpoints per frame should nearly always be enough @@ -60,18 +61,18 @@ void GLViewpointBuffer::CheckSize() } } -int GLViewpointBuffer::Bind(HWDrawInfo *di, unsigned int index) +int GLViewpointBuffer::Bind(FRenderState &di, unsigned int index) { if (index != mLastMappedIndex) { mLastMappedIndex = index; mBuffer->BindRange(index * mBlockAlign, mBlockAlign); - di->EnableClipDistance(0, mClipPlaneInfo[index]); + di.EnableClipDistance(0, mClipPlaneInfo[index]); } return index; } -void GLViewpointBuffer::Set2D(HWDrawInfo *di, int width, int height) +void GLViewpointBuffer::Set2D(FRenderState &di, int width, int height) { if (width != m2DWidth || height != m2DHeight) { @@ -89,7 +90,7 @@ void GLViewpointBuffer::Set2D(HWDrawInfo *di, int width, int height) Bind(di, 0); } -int GLViewpointBuffer::SetViewpoint(HWDrawInfo *di, HWViewpointUniforms *vp) +int GLViewpointBuffer::SetViewpoint(FRenderState &di, HWViewpointUniforms *vp) { CheckSize(); mBuffer->Map(); diff --git a/src/hwrenderer/data/hw_viewpointbuffer.h b/src/hwrenderer/data/hw_viewpointbuffer.h index 44afdda3b..2e1f1e620 100644 --- a/src/hwrenderer/data/hw_viewpointbuffer.h +++ b/src/hwrenderer/data/hw_viewpointbuffer.h @@ -3,7 +3,7 @@ #include "hwrenderer/data/buffers.h" struct HWViewpointUniforms; -struct HWDrawInfo; +class FRenderState; class GLViewpointBuffer { @@ -27,9 +27,9 @@ public: GLViewpointBuffer(); ~GLViewpointBuffer(); void Clear(); - int Bind(HWDrawInfo *di, unsigned int index); - void Set2D(HWDrawInfo *di, int width, int height); - int SetViewpoint(HWDrawInfo *di, HWViewpointUniforms *vp); + int Bind(FRenderState &di, unsigned int index); + void Set2D(FRenderState &di, int width, int height); + int SetViewpoint(FRenderState &di, HWViewpointUniforms *vp); unsigned int GetBlockSize() const { return mBlockSize; } }; diff --git a/src/hwrenderer/models/hw_models.cpp b/src/hwrenderer/models/hw_models.cpp index b99e508bd..9b499aca1 100644 --- a/src/hwrenderer/models/hw_models.cpp +++ b/src/hwrenderer/models/hw_models.cpp @@ -54,7 +54,7 @@ VSMatrix FGLModelRenderer::GetViewToWorldMatrix() void FGLModelRenderer::BeginDrawModel(AActor *actor, FSpriteModelFrame *smf, const VSMatrix &objectToWorldMatrix, bool mirrored) { - di->SetDepthFunc(DF_LEqual); + state.SetDepthFunc(DF_LEqual); state.EnableTexture(true); // [BB] In case the model should be rendered translucent, do back face culling. // This solves a few of the problems caused by the lack of depth sorting. @@ -62,7 +62,7 @@ void FGLModelRenderer::BeginDrawModel(AActor *actor, FSpriteModelFrame *smf, con // TO-DO: Implement proper depth sorting. if (!(actor->RenderStyle == DefaultRenderStyle()) && !(smf->flags & MDL_DONTCULLBACKFACES)) { - di->SetCulling((mirrored ^ screen->mPortalState->isMirrored()) ? Cull_CCW : Cull_CW); + state.SetCulling((mirrored ^ screen->mPortalState->isMirrored()) ? Cull_CCW : Cull_CW); } state.mModelMatrix = objectToWorldMatrix; @@ -72,21 +72,21 @@ void FGLModelRenderer::BeginDrawModel(AActor *actor, FSpriteModelFrame *smf, con void FGLModelRenderer::EndDrawModel(AActor *actor, FSpriteModelFrame *smf) { state.EnableModelMatrix(false); - di->SetDepthFunc(DF_Less); + state.SetDepthFunc(DF_Less); if (!(actor->RenderStyle == DefaultRenderStyle()) && !(smf->flags & MDL_DONTCULLBACKFACES)) - di->SetCulling(Cull_None); + state.SetCulling(Cull_None); } void FGLModelRenderer::BeginDrawHUDModel(AActor *actor, const VSMatrix &objectToWorldMatrix, bool mirrored) { - di->SetDepthFunc(DF_LEqual); + state.SetDepthFunc(DF_LEqual); // [BB] In case the model should be rendered translucent, do back face culling. // This solves a few of the problems caused by the lack of depth sorting. // TO-DO: Implement proper depth sorting. if (!(actor->RenderStyle == DefaultRenderStyle())) { - di->SetCulling((mirrored ^ screen->mPortalState->isMirrored()) ? Cull_CW : Cull_CCW); + state.SetCulling((mirrored ^ screen->mPortalState->isMirrored()) ? Cull_CW : Cull_CCW); } state.mModelMatrix = objectToWorldMatrix; @@ -97,9 +97,9 @@ void FGLModelRenderer::EndDrawHUDModel(AActor *actor) { state.EnableModelMatrix(false); - di->SetDepthFunc(DF_Less); + state.SetDepthFunc(DF_Less); if (!(actor->RenderStyle == DefaultRenderStyle())) - di->SetCulling(Cull_None); + state.SetCulling(Cull_None); } IModelVertexBuffer *FGLModelRenderer::CreateVertexBuffer(bool needindex, bool singleframe) @@ -121,12 +121,12 @@ void FGLModelRenderer::SetMaterial(FTexture *skin, bool clampNoFilter, int trans void FGLModelRenderer::DrawArrays(int start, int count) { - di->Draw(DT_Triangles, state, start, count); + state.Draw(DT_Triangles, start, count); } void FGLModelRenderer::DrawElements(int numIndices, size_t offset) { - di->DrawIndexed(DT_Triangles, state, int(offset / sizeof(unsigned int)), numIndices); + state.DrawIndexed(DT_Triangles, int(offset / sizeof(unsigned int)), numIndices); } //=========================================================================== diff --git a/src/hwrenderer/scene/hw_decal.cpp b/src/hwrenderer/scene/hw_decal.cpp index c4e19b9a4..5a3e509bf 100644 --- a/src/hwrenderer/scene/hw_decal.cpp +++ b/src/hwrenderer/scene/hw_decal.cpp @@ -87,7 +87,7 @@ void GLDecal::DrawDecal(HWDrawInfo *di, FRenderState &state) if (lightlist == nullptr) { - di->Draw(DT_TriangleFan, state, vertindex, 4); + state.Draw(DT_TriangleFan, vertindex, 4); } else { @@ -111,7 +111,7 @@ void GLDecal::DrawDecal(HWDrawInfo *di, FRenderState &state) state.SetFog(thisll, rellight, di->isFullbrightScene(), &thiscm, false); state.SetSplitPlanes(lightlist[k].plane, lowplane); - di->Draw(DT_TriangleFan, state, vertindex, 4); + state.Draw(DT_TriangleFan, vertindex, 4); } if (low1 <= dv[0].z && low2 <= dv[3].z) break; } @@ -132,7 +132,7 @@ void GLDecal::DrawDecal(HWDrawInfo *di, FRenderState &state) void HWDrawInfo::DrawDecals(FRenderState &state, TArray &decals) { side_t *wall = nullptr; - SetDepthMask(false); + state.SetDepthMask(false); state.SetDepthBias(-1, -128); state.SetLightIndex(-1); for (auto gldecal : decals) @@ -155,7 +155,7 @@ void HWDrawInfo::DrawDecals(FRenderState &state, TArray &decals) state.EnableSplit(false); state.ClearDepthBias(); state.SetTextureMode(TM_NORMAL); - SetDepthMask(true); + state.SetDepthMask(true); } //========================================================================== @@ -166,7 +166,7 @@ void HWDrawInfo::DrawDecals(FRenderState &state, TArray &decals) void GLWall::DrawDecalsForMirror(HWDrawInfo *di, FRenderState &state, TArray &decals) { - di->SetDepthMask(false); + state.SetDepthMask(false); state.SetDepthBias(-1, -128); state.SetLightIndex(-1); state.SetFog(lightlevel, rellight + getExtraLight(), di->isFullbrightScene(), &Colormap, false); @@ -179,7 +179,7 @@ void GLWall::DrawDecalsForMirror(HWDrawInfo *di, FRenderState &state, TArraySetDepthMask(true); + state.SetDepthMask(true); } //========================================================================== diff --git a/src/hwrenderer/scene/hw_drawinfo.cpp b/src/hwrenderer/scene/hw_drawinfo.cpp index ac68e9d13..83a8b66cb 100644 --- a/src/hwrenderer/scene/hw_drawinfo.cpp +++ b/src/hwrenderer/scene/hw_drawinfo.cpp @@ -364,14 +364,14 @@ void HWDrawInfo::SetViewMatrix(const FRotator &angles, float vx, float vy, float // Setup the view rotation matrix for the given viewpoint // //----------------------------------------------------------------------------- -void HWDrawInfo::SetupView(float vx, float vy, float vz, bool mirror, bool planemirror) +void HWDrawInfo::SetupView(FRenderState &state, float vx, float vy, float vz, bool mirror, bool planemirror) { auto &vp = Viewpoint; vp.SetViewAngle(r_viewwindow); SetViewMatrix(vp.HWAngles, vx, vy, vz, mirror, planemirror); SetCameraPos(vp.Pos); VPUniforms.CalcDependencies(); - vpIndex = screen->mViewpoints->SetViewpoint(this, &VPUniforms); + vpIndex = screen->mViewpoints->SetViewpoint(state, &VPUniforms); } //----------------------------------------------------------------------------- diff --git a/src/hwrenderer/scene/hw_drawinfo.h b/src/hwrenderer/scene/hw_drawinfo.h index 7aa0011e5..a27e7a2a1 100644 --- a/src/hwrenderer/scene/hw_drawinfo.h +++ b/src/hwrenderer/scene/hw_drawinfo.h @@ -345,7 +345,7 @@ public: void UpdateCurrentMapSection(); void SetViewMatrix(const FRotator &angles, float vx, float vy, float vz, bool mirror, bool planemirror); - void SetupView(float vx, float vy, float vz, bool mirror, bool planemirror); + void SetupView(FRenderState &state, float vx, float vy, float vz, bool mirror, bool planemirror); angle_t FrustumAngle(); void DrawDecals(FRenderState &state, TArray &decals); @@ -359,26 +359,10 @@ public: void AddFlat(GLFlat *flat, bool fog); void AddSprite(GLSprite *sprite, bool translucent); - virtual bool SetDepthClamp(bool on) = 0; GLDecal *AddDecal(bool onmirror); - 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 RenderPortal(HWPortal *p, bool usestencil) = 0; virtual void DrawScene(int drawmode) = 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; - virtual void SetCulling(int mode) = 0; - virtual void EnableClipDistance(int num, bool state) = 0; - - }; diff --git a/src/hwrenderer/scene/hw_drawlist.cpp b/src/hwrenderer/scene/hw_drawlist.cpp index 5342510d4..1ccbc31f3 100644 --- a/src/hwrenderer/scene/hw_drawlist.cpp +++ b/src/hwrenderer/scene/hw_drawlist.cpp @@ -926,11 +926,11 @@ void HWDrawList::DrawSorted(HWDrawInfo *di, FRenderState &state) screen->mVertexData->Unmap(); } state.ClearClipSplit(); - di->EnableClipDistance(1, true); - di->EnableClipDistance(2, true); + state.EnableClipDistance(1, true); + state.EnableClipDistance(2, true); DrawSorted(di, state, sorted); - di->EnableClipDistance(1, false); - di->EnableClipDistance(2, false); + state.EnableClipDistance(1, false); + state.EnableClipDistance(2, false); state.ClearClipSplit(); } diff --git a/src/hwrenderer/scene/hw_flats.cpp b/src/hwrenderer/scene/hw_flats.cpp index 948534fbb..66d5fd167 100644 --- a/src/hwrenderer/scene/hw_flats.cpp +++ b/src/hwrenderer/scene/hw_flats.cpp @@ -191,7 +191,7 @@ void GLFlat::DrawSubsectors(HWDrawInfo *di, FRenderState &state) state.SetLightIndex(dynlightindex); if (vcount > 0 && !di->ClipLineShouldBeActive()) { - di->DrawIndexed(DT_Triangles, state, iboindex, vcount); + state.DrawIndexed(DT_Triangles, iboindex, vcount); flatvertices += vcount; flatprimitives++; } @@ -205,7 +205,7 @@ void GLFlat::DrawSubsectors(HWDrawInfo *di, FRenderState &state) if (di->ss_renderflags[sub->Index()] & renderflags) { - di->DrawIndexed(DT_Triangles, state, index, (sub->numlines - 2) * 3, false); + state.DrawIndexed(DT_Triangles, index, (sub->numlines - 2) * 3, false); flatvertices += sub->numlines; flatprimitives++; } @@ -226,7 +226,7 @@ void GLFlat::DrawSubsectors(HWDrawInfo *di, FRenderState &state) auto num = node->sub->numlines; flatvertices += num; flatprimitives++; - di->Draw(DT_TriangleFan, state, node->vertexindex, num); + state.Draw(DT_TriangleFan,node->vertexindex, num); node = node->next; } // Flood gaps with the back side's ceiling/floor texture @@ -249,26 +249,26 @@ void GLFlat::DrawSubsectors(HWDrawInfo *di, FRenderState &state) // Create stencil state.SetEffect(EFF_STENCIL); state.EnableTexture(false); - di->SetStencil(0, SOP_Increment, SF_ColorMaskOff); - di->Draw(DT_TriangleFan, state, fnode->vertexindex, 4); + state.SetStencil(0, SOP_Increment, SF_ColorMaskOff); + state.Draw(DT_TriangleFan,fnode->vertexindex, 4); // Draw projected plane into stencil state.EnableTexture(true); state.SetEffect(EFF_NONE); - di->SetStencil(1, SOP_Keep, SF_DepthMaskOff | SF_DepthTestOff); - di->Draw(DT_TriangleFan, state, fnode->vertexindex + 4, 4); + state.SetStencil(1, SOP_Keep, SF_DepthMaskOff | SF_DepthTestOff); + state.Draw(DT_TriangleFan,fnode->vertexindex + 4, 4); // clear stencil state.SetEffect(EFF_STENCIL); state.EnableTexture(false); - di->SetStencil(1, SOP_Decrement, SF_ColorMaskOff | SF_DepthMaskOff | SF_DepthTestOff); - di->Draw(DT_TriangleFan, state, fnode->vertexindex, 4); + state.SetStencil(1, SOP_Decrement, SF_ColorMaskOff | SF_DepthMaskOff | SF_DepthTestOff); + state.Draw(DT_TriangleFan,fnode->vertexindex, 4); // restore old stencil op. state.EnableTexture(true); state.SetEffect(EFF_NONE); state.SetDepthBias(0, 0); - di->SetStencil(0, SOP_Keep, SF_AllOn); + state.SetStencil(0, SOP_Keep, SF_AllOn); fnode = fnode->next; } @@ -305,7 +305,7 @@ void GLFlat::DrawFlat(HWDrawInfo *di, FRenderState &state, bool translucent) { state.SetMaterial(gltexture, CLAMP_XY, 0, -1); state.SetLightIndex(dynlightindex); - di->Draw(DT_TriangleFan, state, iboindex, 4); + state.Draw(DT_TriangleFan,iboindex, 4); flatvertices += 4; flatprimitives++; } diff --git a/src/hwrenderer/scene/hw_portal.cpp b/src/hwrenderer/scene/hw_portal.cpp index 183e8ac85..9beecbdf8 100644 --- a/src/hwrenderer/scene/hw_portal.cpp +++ b/src/hwrenderer/scene/hw_portal.cpp @@ -167,7 +167,7 @@ void FPortalSceneState::RenderPortal(HWPortal *p, bool usestencil, HWDrawInfo *o // //----------------------------------------------------------------------------- -void HWPortal::DrawPortalStencil(HWDrawInfo *di, FRenderState &state, int pass) +void HWPortal::DrawPortalStencil(FRenderState &state, int pass) { if (mPrimIndices.Size() == 0) { @@ -181,15 +181,15 @@ void HWPortal::DrawPortalStencil(HWDrawInfo *di, FRenderState &state, int pass) } for (unsigned int i = 0; i < mPrimIndices.Size(); i += 2) { - di->Draw(DT_TriangleFan, state, mPrimIndices[i], mPrimIndices[i + 1], i == 0); + state.Draw(DT_TriangleFan, 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); + if (pass == STP_DepthRestore) state.SetDepthRange(1, 1); + state.Draw(DT_TriangleFan, FFlatVertexBuffer::STENCILTOP_INDEX, 4); + state.Draw(DT_TriangleFan, FFlatVertexBuffer::STENCILBOTTOM_INDEX, 4); + if (pass == STP_DepthRestore) state.SetDepthRange(0, 1); } } @@ -213,32 +213,32 @@ void HWPortal::SetupStencil(HWDrawInfo *di, FRenderState &state, bool usestencil if (NeedDepthBuffer()) { - di->SetStencil(0, SOP_Increment, SF_ColorMaskOff | SF_DepthMaskOff); - di->SetDepthFunc(DF_Less); - DrawPortalStencil(di, state, STP_Stencil); + state.SetStencil(0, SOP_Increment, SF_ColorMaskOff | SF_DepthMaskOff); + state.SetDepthFunc(DF_Less); + DrawPortalStencil(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); + state.SetStencil(1, SOP_Keep, SF_ColorMaskOff); + state.SetDepthRange(1, 1); + state.SetDepthFunc(DF_Always); + DrawPortalStencil(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.SetStencil(1, SOP_Keep, SF_AllOn); + state.SetDepthRange(0, 1); + state.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); + state.SetStencil(0, SOP_Increment, SF_ColorMaskOff); + state.SetDepthFunc(DF_Less); + DrawPortalStencil(state, STP_AllInOne); - di->SetStencil(1, SOP_Keep, SF_DepthTestOff | SF_DepthMaskOff); + state.SetStencil(1, SOP_Keep, SF_DepthTestOff | SF_DepthMaskOff); state.EnableTexture(true); state.SetEffect(EFF_NONE); } @@ -249,7 +249,7 @@ void HWPortal::SetupStencil(HWDrawInfo *di, FRenderState &state, bool usestencil { if (!NeedDepthBuffer()) { - di->SetStencil(0, SOP_Keep, SF_DepthTestOff | SF_DepthMaskOff); + state.SetStencil(0, SOP_Keep, SF_DepthTestOff | SF_DepthMaskOff); } } @@ -275,17 +275,17 @@ void HWPortal::RemoveStencil(HWDrawInfo *di, FRenderState &state, bool usestenci 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); + state.SetStencil(0, SOP_Keep, SF_ColorMaskOff); + state.SetDepthRange(1, 1); // always + state.SetDepthFunc(DF_Always); // write the farthest depth value + DrawPortalStencil(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.SetStencil(0, SOP_Decrement, SF_ColorMaskOff); + state.SetDepthRange(0, 1); + state.SetDepthFunc(DF_LEqual); + DrawPortalStencil(state, STP_DepthRestore); state.EnableTexture(true); state.SetEffect(EFF_NONE); @@ -298,15 +298,15 @@ void HWPortal::RemoveStencil(HWDrawInfo *di, FRenderState &state, bool usestenci 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.SetStencil(0, SOP_Keep, needdepth ? SF_ColorMaskOff | SF_DepthClear : SF_ColorMaskOff); + state.SetDepthRange(0, 1); + state.SetDepthFunc(DF_LEqual); + DrawPortalStencil(state, STP_DepthRestore); state.SetEffect(EFF_NONE); state.EnableTexture(true); } - di->SetStencil(0, SOP_Keep, SF_AllOn); + state.SetStencil(0, SOP_Keep, SF_AllOn); } @@ -403,7 +403,7 @@ int HWLinePortal::ClipPoint(const DVector2 &pos) // //----------------------------------------------------------------------------- -bool HWMirrorPortal::Setup(HWDrawInfo *di, Clipper *clipper) +bool HWMirrorPortal::Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *clipper) { auto state = mOwner->mState; if (state->renderdepth > r_mirror_recursions) @@ -473,7 +473,7 @@ bool HWMirrorPortal::Setup(HWDrawInfo *di, Clipper *clipper) state->MirrorFlag++; di->SetClipLine(linedef); - di->SetupView(vp.Pos.X, vp.Pos.Y, vp.Pos.Z, !!(state->MirrorFlag & 1), !!(state->PlaneMirrorFlag & 1)); + di->SetupView(rstate, vp.Pos.X, vp.Pos.Y, vp.Pos.Z, !!(state->MirrorFlag & 1), !!(state->PlaneMirrorFlag & 1)); clipper->Clear(); @@ -484,7 +484,7 @@ bool HWMirrorPortal::Setup(HWDrawInfo *di, Clipper *clipper) return true; } -void HWMirrorPortal::Shutdown(HWDrawInfo *di) +void HWMirrorPortal::Shutdown(HWDrawInfo *di, FRenderState &rstate) { mOwner->mState->MirrorFlag--; } @@ -506,7 +506,7 @@ const char *HWMirrorPortal::GetName() { return "Mirror"; } // // //----------------------------------------------------------------------------- -bool HWLineToLinePortal::Setup(HWDrawInfo *di, Clipper *clipper) +bool HWLineToLinePortal::Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *clipper) { // TODO: Handle recursion more intelligently auto &state = mOwner->mState; @@ -553,7 +553,7 @@ bool HWLineToLinePortal::Setup(HWDrawInfo *di, Clipper *clipper) vp.ViewActor = nullptr; di->SetClipLine(glport->lines[0]->mDestination); - di->SetupView(vp.Pos.X, vp.Pos.Y, vp.Pos.Z, !!(state->MirrorFlag & 1), !!(state->PlaneMirrorFlag & 1)); + di->SetupView(rstate, vp.Pos.X, vp.Pos.Y, vp.Pos.Z, !!(state->MirrorFlag & 1), !!(state->PlaneMirrorFlag & 1)); ClearClipper(di, clipper); return true; @@ -583,7 +583,7 @@ const char *HWLineToLinePortal::GetName() { return "LineToLine"; } // //----------------------------------------------------------------------------- -bool HWSkyboxPortal::Setup(HWDrawInfo *di, Clipper *clipper) +bool HWSkyboxPortal::Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *clipper) { auto state = mOwner->mState; old_pm = state->PlaneMirrorMode; @@ -602,8 +602,7 @@ bool HWSkyboxPortal::Setup(HWDrawInfo *di, Clipper *clipper) portal->mFlags |= PORTSF_INSKYBOX; vp.extralight = 0; - - oldclamp = di->SetDepthClamp(false); + oldclamp = rstate.SetDepthClamp(false); vp.Pos = origin->InterpolatedPosition(vp.TicFrac); vp.ActorPos = origin->Pos(); vp.Angles.Yaw += (origin->PrevAngles.Yaw + deltaangle(origin->PrevAngles.Yaw, origin->Angles.Yaw) * vp.TicFrac); @@ -616,7 +615,7 @@ bool HWSkyboxPortal::Setup(HWDrawInfo *di, Clipper *clipper) vp.ViewActor = origin; - di->SetupView(vp.Pos.X, vp.Pos.Y, vp.Pos.Z, !!(state->MirrorFlag & 1), !!(state->PlaneMirrorFlag & 1)); + di->SetupView(rstate, vp.Pos.X, vp.Pos.Y, vp.Pos.Z, !!(state->MirrorFlag & 1), !!(state->PlaneMirrorFlag & 1)); di->SetViewArea(); ClearClipper(di, clipper); di->UpdateCurrentMapSection(); @@ -624,11 +623,12 @@ bool HWSkyboxPortal::Setup(HWDrawInfo *di, Clipper *clipper) } -void HWSkyboxPortal::Shutdown(HWDrawInfo *di) +void HWSkyboxPortal::Shutdown(HWDrawInfo *di, FRenderState &rstate) { + rstate.SetDepthClamp(oldclamp); + auto state = mOwner->mState; portal->mFlags &= ~PORTSF_INSKYBOX; - di->SetDepthClamp(oldclamp); state->inskybox = false; state->skyboxrecursion--; state->PlaneMirrorMode = old_pm; @@ -693,7 +693,7 @@ void HWSectorStackPortal::SetupCoverage(HWDrawInfo *di) // GLSectorStackPortal::DrawContents // //----------------------------------------------------------------------------- -bool HWSectorStackPortal::Setup(HWDrawInfo *di, Clipper *clipper) +bool HWSectorStackPortal::Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *clipper) { auto state = mOwner->mState; FSectorPortalGroup *portal = origin; @@ -706,7 +706,7 @@ bool HWSectorStackPortal::Setup(HWDrawInfo *di, Clipper *clipper) // avoid recursions! if (origin->plane != -1) screen->instack[origin->plane]++; - di->SetupView(vp.Pos.X, vp.Pos.Y, vp.Pos.Z, !!(state->MirrorFlag & 1), !!(state->PlaneMirrorFlag & 1)); + di->SetupView(rstate, vp.Pos.X, vp.Pos.Y, vp.Pos.Z, !!(state->MirrorFlag & 1), !!(state->PlaneMirrorFlag & 1)); SetupCoverage(di); ClearClipper(di, clipper); @@ -722,7 +722,7 @@ bool HWSectorStackPortal::Setup(HWDrawInfo *di, Clipper *clipper) } -void HWSectorStackPortal::Shutdown(HWDrawInfo *di) +void HWSectorStackPortal::Shutdown(HWDrawInfo *di, FRenderState &rstate) { if (origin->plane != -1) screen->instack[origin->plane]--; } @@ -745,7 +745,7 @@ const char *HWSectorStackPortal::GetName() { return "Sectorstack"; } // //----------------------------------------------------------------------------- -bool HWPlaneMirrorPortal::Setup(HWDrawInfo *di, Clipper *clipper) +bool HWPlaneMirrorPortal::Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *clipper) { auto state = mOwner->mState; if (state->renderdepth > r_mirror_recursions) @@ -768,14 +768,14 @@ bool HWPlaneMirrorPortal::Setup(HWDrawInfo *di, Clipper *clipper) state->PlaneMirrorFlag++; di->SetClipHeight(planez, state->PlaneMirrorMode < 0 ? -1.f : 1.f); - di->SetupView(vp.Pos.X, vp.Pos.Y, vp.Pos.Z, !!(state->MirrorFlag & 1), !!(state->PlaneMirrorFlag & 1)); + di->SetupView(rstate, vp.Pos.X, vp.Pos.Y, vp.Pos.Z, !!(state->MirrorFlag & 1), !!(state->PlaneMirrorFlag & 1)); ClearClipper(di, clipper); di->UpdateCurrentMapSection(); return true; } -void HWPlaneMirrorPortal::Shutdown(HWDrawInfo *di) +void HWPlaneMirrorPortal::Shutdown(HWDrawInfo *di, FRenderState &rstate) { auto state = mOwner->mState; state->PlaneMirrorFlag--; @@ -876,7 +876,7 @@ void HWHorizonPortal::DrawContents(HWDrawInfo *di, FRenderState &state) gltexture = FMaterial::ValidateTexture(sp->texture, false, true); if (!gltexture) { - di->ClearScreen(); + state.ClearScreen(); return; } di->SetCameraPos(vp.Pos); @@ -905,9 +905,9 @@ void HWHorizonPortal::DrawContents(HWDrawInfo *di, FRenderState &state) for (unsigned i = 0; i < vcount; i += 4) { - di->Draw(DT_TriangleStrip, state, voffset + i, 4, true);// i == 0); + state.Draw(DT_TriangleStrip, voffset + i, 4, true);// i == 0); } - di->Draw(DT_TriangleStrip, state, voffset + vcount, 10, false); + state.Draw(DT_TriangleStrip, voffset + vcount, 10, false); state.EnableTextureMatrix(false); } diff --git a/src/hwrenderer/scene/hw_portal.h b/src/hwrenderer/scene/hw_portal.h index 099d09092..50369f232 100644 --- a/src/hwrenderer/scene/hw_portal.h +++ b/src/hwrenderer/scene/hw_portal.h @@ -5,6 +5,7 @@ #include "hw_drawinfo.h" #include "hw_drawstructs.h" #include "hwrenderer/textures/hw_material.h" +#include "hwrenderer/scene/hw_renderstate.h" class FSkyVertexBuffer; @@ -55,7 +56,7 @@ class HWPortal ActorRenderFlags savedvisibility; TArray mPrimIndices; - void DrawPortalStencil(HWDrawInfo *di, FRenderState &state, int pass); + void DrawPortalStencil(FRenderState &state, int pass); public: FPortalSceneState * mState; @@ -142,8 +143,8 @@ public: virtual void * GetSource() const = 0; // GetSource MUST be implemented! virtual const char *GetName() = 0; - virtual bool Setup(HWDrawInfo *di, Clipper *clipper) = 0; - virtual void Shutdown(HWDrawInfo *di) {} + virtual bool Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *clipper) = 0; + virtual void Shutdown(HWDrawInfo *di, FRenderState &rstate) {} virtual void RenderAttached(HWDrawInfo *di) {} }; @@ -204,8 +205,8 @@ struct HWMirrorPortal : public HWLinePortal line_t * linedef; protected: - bool Setup(HWDrawInfo *di, Clipper *clipper) override; - void Shutdown(HWDrawInfo *di) override; + bool Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *clipper) override; + void Shutdown(HWDrawInfo *di, FRenderState &rstate) override; void * GetSource() const override { return linedef; } const char *GetName() override; @@ -223,7 +224,7 @@ struct HWLineToLinePortal : public HWLinePortal { FLinePortalSpan *glport; protected: - bool Setup(HWDrawInfo *di, Clipper *clipper) override; + bool Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *clipper) override; virtual void * GetSource() const override { return glport; } virtual const char *GetName() override; virtual line_t *ClipLine() override { return line(); } @@ -246,8 +247,8 @@ struct HWSkyboxPortal : public HWScenePortalBase FSectorPortal * portal; protected: - bool Setup(HWDrawInfo *di, Clipper *clipper) override; - void Shutdown(HWDrawInfo *di) override; + bool Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *clipper) override; + void Shutdown(HWDrawInfo *di, FRenderState &rstate) override; virtual void * GetSource() const { return portal; } virtual bool IsSky() { return true; } virtual const char *GetName(); @@ -267,8 +268,8 @@ struct HWSectorStackPortal : public HWScenePortalBase { TArray subsectors; protected: - bool Setup(HWDrawInfo *di, Clipper *clipper) override; - void Shutdown(HWDrawInfo *di) override; + bool Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *clipper) override; + void Shutdown(HWDrawInfo *di, FRenderState &rstate) override; virtual void * GetSource() const { return origin; } virtual bool IsSky() { return true; } // although this isn't a real sky it can be handled as one. virtual const char *GetName(); @@ -292,8 +293,8 @@ struct HWPlaneMirrorPortal : public HWScenePortalBase { int old_pm; protected: - bool Setup(HWDrawInfo *di, Clipper *clipper) override; - void Shutdown(HWDrawInfo *di) override; + bool Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *clipper) override; + void Shutdown(HWDrawInfo *di, FRenderState &rstate) override; virtual void * GetSource() const { return origin; } virtual const char *GetName(); secplane_t * origin; @@ -325,12 +326,12 @@ public: virtual bool NeedDepthBuffer() { return true; } virtual void DrawContents(HWDrawInfo *di, FRenderState &state) { - if (mScene->Setup(di, di->mClipper)) + if (mScene->Setup(di, state, di->mClipper)) { di->DrawScene(DM_PORTAL); - mScene->Shutdown(di); + mScene->Shutdown(di, state); } - else di->ClearScreen(); + else state.ClearScreen(); } virtual void RenderAttached(HWDrawInfo *di) { return mScene->RenderAttached(di); } }; diff --git a/src/hwrenderer/scene/hw_renderstate.h b/src/hwrenderer/scene/hw_renderstate.h index dcba861ba..49d85188a 100644 --- a/src/hwrenderer/scene/hw_renderstate.h +++ b/src/hwrenderer/scene/hw_renderstate.h @@ -4,6 +4,7 @@ #include "vectors.h" #include "g_levellocals.h" #include "hw_drawstructs.h" +#include "hw_drawlist.h" #include "r_data/matrix.h" #include "hwrenderer/textures/hw_material.h" @@ -422,5 +423,23 @@ public: void SetColor(int sectorlightlevel, int rellight, bool fullbright, const FColormap &cm, float alpha, bool weapon = false); void SetFog(int lightlevel, int rellight, bool fullbright, const FColormap *cmap, bool isadditive); + + // API-dependent render interface + + // Draw commands + virtual void ClearScreen() = 0; + virtual void Draw(int dt, int index, int count, bool apply = true) = 0; + virtual void DrawIndexed(int dt, int index, int count, bool apply = true) = 0; + + // Immediate render state change commands. These only change infrequently and should not clutter the render state. + virtual bool SetDepthClamp(bool on) = 0; + 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; + virtual void SetCulling(int mode) = 0; + virtual void EnableClipDistance(int num, bool state) = 0; + }; diff --git a/src/hwrenderer/scene/hw_skyportal.cpp b/src/hwrenderer/scene/hw_skyportal.cpp index 431bac275..2b0e07629 100644 --- a/src/hwrenderer/scene/hw_skyportal.cpp +++ b/src/hwrenderer/scene/hw_skyportal.cpp @@ -41,7 +41,7 @@ void HWSkyPortal::RenderRow(HWDrawInfo *di, FRenderState &state, EDrawType prim, int row, bool apply) { - di->Draw(prim, state, vertexBuffer->mPrimStart[row], vertexBuffer->mPrimStart[row + 1] - vertexBuffer->mPrimStart[row]); + state.Draw(prim, vertexBuffer->mPrimStart[row], vertexBuffer->mPrimStart[row + 1] - vertexBuffer->mPrimStart[row]); } //----------------------------------------------------------------------------- @@ -115,40 +115,40 @@ void HWSkyPortal::RenderBox(HWDrawInfo *di, FRenderState &state, FTextureID texn // north tex = FMaterial::ValidateTexture(sb->faces[0], false); state.SetMaterial(tex, CLAMP_XY, 0, -1); - di->Draw(DT_TriangleStrip, state, vertexBuffer->FaceStart(0), 4); + state.Draw(DT_TriangleStrip, vertexBuffer->FaceStart(0), 4); // east tex = FMaterial::ValidateTexture(sb->faces[1], false); state.SetMaterial(tex, CLAMP_XY, 0, -1); - di->Draw(DT_TriangleStrip, state, vertexBuffer->FaceStart(1), 4); + state.Draw(DT_TriangleStrip, vertexBuffer->FaceStart(1), 4); // south tex = FMaterial::ValidateTexture(sb->faces[2], false); state.SetMaterial(tex, CLAMP_XY, 0, -1); - di->Draw(DT_TriangleStrip, state, vertexBuffer->FaceStart(2), 4); + state.Draw(DT_TriangleStrip, vertexBuffer->FaceStart(2), 4); // west tex = FMaterial::ValidateTexture(sb->faces[3], false); state.SetMaterial(tex, CLAMP_XY, 0, -1); - di->Draw(DT_TriangleStrip, state, vertexBuffer->FaceStart(3), 4); + state.Draw(DT_TriangleStrip, vertexBuffer->FaceStart(3), 4); } else { faces=1; tex = FMaterial::ValidateTexture(sb->faces[0], false); state.SetMaterial(tex, CLAMP_XY, 0, -1); - di->Draw(DT_TriangleStrip, state, vertexBuffer->FaceStart(-1), 10); + state.Draw(DT_TriangleStrip, vertexBuffer->FaceStart(-1), 10); } // top tex = FMaterial::ValidateTexture(sb->faces[faces], false); state.SetMaterial(tex, CLAMP_XY, 0, -1); - di->Draw(DT_TriangleStrip, state, vertexBuffer->FaceStart(sb->fliptop ? 6 : 5), 4); + state.Draw(DT_TriangleStrip, vertexBuffer->FaceStart(sb->fliptop ? 6 : 5), 4); // bottom tex = FMaterial::ValidateTexture(sb->faces[faces+1], false); state.SetMaterial(tex, CLAMP_XY, 0, -1); - di->Draw(DT_TriangleStrip, state, vertexBuffer->FaceStart(4), 4); + state.Draw(DT_TriangleStrip, vertexBuffer->FaceStart(4), 4); state.EnableModelMatrix(false); } @@ -176,9 +176,9 @@ void HWSkyPortal::DrawContents(HWDrawInfo *di, FRenderState &state) state.EnableFog(false); state.AlphaFunc(Alpha_GEqual, 0.f); state.SetRenderStyle(STYLE_Translucent); - bool oldClamp = di->SetDepthClamp(true); + bool oldClamp = state.SetDepthClamp(true); - di->SetupView(0, 0, 0, !!(mState->MirrorFlag & 1), !!(mState->PlaneMirrorFlag & 1)); + di->SetupView(state, 0, 0, 0, !!(mState->MirrorFlag & 1), !!(mState->PlaneMirrorFlag & 1)); vertexBuffer->Bind(state); if (origin->texture[0] && origin->texture[0]->tex->bSkybox) @@ -210,13 +210,13 @@ void HWSkyPortal::DrawContents(HWDrawInfo *di, FRenderState &state) state.EnableTexture(false); state.SetObjectColor(FadeColor); - di->Draw(DT_Triangles, state, 0, 12); + state.Draw(DT_Triangles, 0, 12); state.EnableTexture(true); state.SetObjectColor(0xffffffff); } } ::level.lightmode = oldlightmode; - di->SetDepthClamp(oldClamp); + state.SetDepthClamp(oldClamp); } const char *HWSkyPortal::GetName() { return "Sky"; } diff --git a/src/hwrenderer/scene/hw_sprites.cpp b/src/hwrenderer/scene/hw_sprites.cpp index 637fe886c..8309dee0d 100644 --- a/src/hwrenderer/scene/hw_sprites.cpp +++ b/src/hwrenderer/scene/hw_sprites.cpp @@ -255,7 +255,7 @@ void GLSprite::DrawSprite(HWDrawInfo *di, FRenderState &state, bool translucent) state.SetDepthBias(-1, -128); } state.SetLightIndex(-1); - di->Draw(DT_TriangleStrip, state, vertexindex, 4); + state.Draw(DT_TriangleStrip, vertexindex, 4); if (foglayer) { @@ -263,7 +263,7 @@ void GLSprite::DrawSprite(HWDrawInfo *di, FRenderState &state, bool translucent) state.SetFog(foglevel, rel, false, &Colormap, additivefog); state.SetTextureMode(TM_FOGLAYER); state.SetRenderStyle(STYLE_Translucent); - di->Draw(DT_TriangleStrip, state, vertexindex, 4); + state.Draw(DT_TriangleStrip, vertexindex, 4); state.SetTextureMode(TM_NORMAL); } } diff --git a/src/hwrenderer/scene/hw_walls.cpp b/src/hwrenderer/scene/hw_walls.cpp index 232d1ec7d..31ccd9c25 100644 --- a/src/hwrenderer/scene/hw_walls.cpp +++ b/src/hwrenderer/scene/hw_walls.cpp @@ -53,7 +53,7 @@ void GLWall::RenderWall(HWDrawInfo *di, FRenderState &state, int textured) { assert(vertcount > 0); state.SetLightIndex(dynlightindex); - di->Draw(DT_TriangleFan, state, vertindex, vertcount); + state.Draw(DT_TriangleFan, vertindex, vertcount); vertexcount += vertcount; } @@ -68,7 +68,7 @@ void GLWall::RenderFogBoundary(HWDrawInfo *di, FRenderState &state) if (gl_fogmode && !di->isFullbrightScene()) { int rel = rellight + getExtraLight(); - di->EnableDrawBufferAttachments(false); + state.EnableDrawBufferAttachments(false); state.SetFog(lightlevel, rel, false, &Colormap, false); state.SetEffect(EFF_FOGBOUNDARY); state.AlphaFunc(Alpha_GEqual, 0.f); @@ -76,7 +76,7 @@ void GLWall::RenderFogBoundary(HWDrawInfo *di, FRenderState &state) RenderWall(di, state, GLWall::RWF_BLANK); state.ClearDepthBias(); state.SetEffect(EFF_NONE); - di->EnableDrawBufferAttachments(true); + state.EnableDrawBufferAttachments(true); } } @@ -90,7 +90,7 @@ void GLWall::RenderMirrorSurface(HWDrawInfo *di, FRenderState &state) { if (!TexMan.mirrorTexture.isValid()) return; - di->SetDepthFunc(DF_LEqual); + state.SetDepthFunc(DF_LEqual); // we use texture coordinates and texture matrix to pass the normal stuff to the shader so that the default vertex buffer format can be used as is. state.EnableTextureMatrix(true); @@ -112,7 +112,7 @@ void GLWall::RenderMirrorSurface(HWDrawInfo *di, FRenderState &state) state.SetEffect(EFF_NONE); state.AlphaFunc(Alpha_GEqual, gl_mask_sprite_threshold); - di->SetDepthFunc(DF_Less); + state.SetDepthFunc(DF_Less); // This is drawn in the translucent pass which is done after the decal pass // As a result the decals have to be drawn here, right after the wall they are on, diff --git a/src/hwrenderer/scene/hw_weapon.cpp b/src/hwrenderer/scene/hw_weapon.cpp index e0dfe13e5..ad5d6e7cf 100644 --- a/src/hwrenderer/scene/hw_weapon.cpp +++ b/src/hwrenderer/scene/hw_weapon.cpp @@ -88,7 +88,7 @@ void HWDrawInfo::DrawPSprite(HUDSprite *huds, FRenderState &state) float thresh = (huds->tex->tex->GetTranslucency() || huds->OverrideShader != -1) ? 0.f : gl_mask_sprite_threshold; state.AlphaFunc(Alpha_GEqual, thresh); state.SetMaterial(huds->tex, CLAMP_XY_NOMIP, 0, huds->OverrideShader); - Draw(DT_TriangleStrip, state, huds->mx, 4); + state.Draw(DT_TriangleStrip, huds->mx, 4); } state.SetTextureMode(TM_NORMAL);