diff --git a/src/gl/renderer/gl_renderer.cpp b/src/gl/renderer/gl_renderer.cpp index cca2e9b2b..e3b9b0a8b 100644 --- a/src/gl/renderer/gl_renderer.cpp +++ b/src/gl/renderer/gl_renderer.cpp @@ -84,6 +84,7 @@ FGLRenderer::FGLRenderer(OpenGLFrameBuffer *fb) { framebuffer = fb; + mClipPortal = NULL; mCurrentPortal = NULL; mMirrorCount = 0; mPlaneMirrorCount = 0; diff --git a/src/gl/renderer/gl_renderer.h b/src/gl/renderer/gl_renderer.h index d09ac1948..52ce5b2fa 100644 --- a/src/gl/renderer/gl_renderer.h +++ b/src/gl/renderer/gl_renderer.h @@ -59,6 +59,7 @@ class FGLRenderer public: OpenGLFrameBuffer *framebuffer; + GLPortal *mClipPortal; GLPortal *mCurrentPortal; int mMirrorCount; int mPlaneMirrorCount; diff --git a/src/gl/renderer/gl_renderstate.cpp b/src/gl/renderer/gl_renderstate.cpp index fdb0e3cc5..15a575e79 100644 --- a/src/gl/renderer/gl_renderstate.cpp +++ b/src/gl/renderer/gl_renderstate.cpp @@ -69,7 +69,7 @@ TArray gl_MatrixStack; void FRenderState::Reset() { mTextureEnabled = true; - mSplitEnabled = mBrightmapEnabled = mFogEnabled = mGlowEnabled = false; + mClipLineEnabled = mSplitEnabled = mBrightmapEnabled = mFogEnabled = mGlowEnabled = false; mColorMask[0] = mColorMask[1] = mColorMask[2] = mColorMask[3] = true; currentColorMask[0] = currentColorMask[1] = currentColorMask[2] = currentColorMask[3] = true; mFogColor.d = -1; @@ -171,10 +171,22 @@ bool FRenderState::ApplyShader() activeShader->muSplitBottomPlane.Set(mSplitBottomPlane.vec); activeShader->currentsplitstate = 1; } - else + else if (activeShader->currentsplitstate) { activeShader->muSplitTopPlane.Set(nulvec); activeShader->muSplitBottomPlane.Set(nulvec); + activeShader->currentsplitstate = 0; + } + + if (mClipLineEnabled) + { + activeShader->muClipLine.Set(mClipLine.vec); + activeShader->currentcliplinestate = 1; + } + else if (activeShader->currentcliplinestate) + { + activeShader->muClipLine.Set(-10000000.0, 0, 0, 0); + activeShader->currentcliplinestate = 0; } if (mColormapState != activeShader->currentfixedcolormap) diff --git a/src/gl/renderer/gl_renderstate.h b/src/gl/renderer/gl_renderstate.h index ca240c398..829edeec0 100644 --- a/src/gl/renderer/gl_renderstate.h +++ b/src/gl/renderer/gl_renderstate.h @@ -47,6 +47,7 @@ class FRenderState bool mFogEnabled; bool mGlowEnabled; bool mSplitEnabled; + bool mClipLineEnabled; bool mBrightmapEnabled; bool mColorMask[4]; bool currentColorMask[4]; @@ -73,6 +74,7 @@ class FRenderState FStateVec4 mGlowTop, mGlowBottom; FStateVec4 mGlowTopPlane, mGlowBottomPlane; FStateVec4 mSplitTopPlane, mSplitBottomPlane; + FStateVec4 mClipLine; PalEntry mFogColor; PalEntry mObjectColor; FStateVec4 mDynColor; @@ -145,6 +147,16 @@ public: return mClipHeightDirection; } + FStateVec4 &GetClipLine() + { + return mClipLine; + } + + bool GetClipLineState() + { + return mClipLineEnabled; + } + void SetClipHeight(float height, float direction); void SetColor(float r, float g, float b, float a = 1.f, int desat = 0) @@ -241,6 +253,27 @@ public: } } + void SetClipLine(line_t *line) + { + mClipLine.Set(line->v1->fX(), line->v1->fY(), line->Delta().X, line->Delta().Y); + } + + void EnableClipLine(bool on) + { + if (gl.glslversion >= 1.3f) + { + mClipLineEnabled = on; + if (on) + { + glEnable(GL_CLIP_DISTANCE0); + } + else + { + glDisable(GL_CLIP_DISTANCE0); + } + } + } + void SetLightIndex(int n) { mLightIndex = n; diff --git a/src/gl/scene/gl_bsp.cpp b/src/gl/scene/gl_bsp.cpp index 98053784c..b9915dd72 100644 --- a/src/gl/scene/gl_bsp.cpp +++ b/src/gl/scene/gl_bsp.cpp @@ -111,7 +111,7 @@ static void AddLine (seg_t *seg, bool portalclip) if (portalclip) { - int clipres = GLRenderer->mCurrentPortal->ClipSeg(seg); + int clipres = GLRenderer->mClipPortal->ClipSeg(seg); if (clipres == GLPortal::PClip_InFront) return; } @@ -218,7 +218,7 @@ static void PolySubsector(subsector_t * sub) { if (line->linedef) { - AddLine (line, GLRenderer->mCurrentPortal != NULL); + AddLine (line, GLRenderer->mClipPortal != NULL); } line++; } @@ -313,11 +313,11 @@ static inline void AddLines(subsector_t * sub, sector_t * sector) { if (seg->linedef == NULL) { - if (!(sub->flags & SSECF_DRAWN)) AddLine (seg, GLRenderer->mCurrentPortal != NULL); + if (!(sub->flags & SSECF_DRAWN)) AddLine (seg, GLRenderer->mClipPortal != NULL); } else if (!(seg->sidedef->Flags & WALLF_POLYOBJ)) { - AddLine (seg, GLRenderer->mCurrentPortal != NULL); + AddLine (seg, GLRenderer->mClipPortal != NULL); } seg++; } @@ -447,12 +447,12 @@ static void DoSubsector(subsector_t * sub) fakesector=gl_FakeFlat(sector, &fake, false); - if (GLRenderer->mCurrentPortal) + if (GLRenderer->mClipPortal) { - int clipres = GLRenderer->mCurrentPortal->ClipSubsector(sub); + int clipres = GLRenderer->mClipPortal->ClipSubsector(sub); if (clipres == GLPortal::PClip_InFront) { - line_t *line = GLRenderer->mCurrentPortal->ClipLine(); + line_t *line = GLRenderer->mClipPortal->ClipLine(); // The subsector is out of range, but we still have to check lines that lie directly on the boundary and may expose their upper or lower parts. if (line) AddSpecialPortalLines(sub, fakesector, line); return; diff --git a/src/gl/scene/gl_portal.cpp b/src/gl/scene/gl_portal.cpp index 93f25f28e..f165de630 100644 --- a/src/gl/scene/gl_portal.cpp +++ b/src/gl/scene/gl_portal.cpp @@ -300,9 +300,6 @@ bool GLPortal::Start(bool usestencil, bool doquery) glDisable(GL_DEPTH_TEST); } } - planestack.Push(gl_RenderState.GetClipHeight()); - planestack.Push(gl_RenderState.GetClipHeightDirection()); - gl_RenderState.SetClipHeight(0., 0.); // save viewpoint savedViewPos = ViewPos; @@ -313,8 +310,12 @@ bool GLPortal::Start(bool usestencil, bool doquery) savedviewpath[0] = ViewPath[0]; savedviewpath[1] = ViewPath[1]; - NextPortal = GLRenderer->mCurrentPortal; - GLRenderer->mCurrentPortal = NULL; // Portals which need this have to set it themselves + PrevPortal = GLRenderer->mCurrentPortal; + PrevClipPortal = GLRenderer->mClipPortal; + GLRenderer->mClipPortal = NULL; // Portals which need this have to set it themselves + GLRenderer->mCurrentPortal = this; + + if (PrevPortal != NULL) PrevPortal->PushState(); PortalAll.Unclock(); return true; } @@ -359,12 +360,9 @@ void GLPortal::End(bool usestencil) bool needdepth = NeedDepthBuffer(); PortalAll.Clock(); - GLRenderer->mCurrentPortal = NextPortal; - - float f, d; - planestack.Pop(d); - planestack.Pop(f); - gl_RenderState.SetClipHeight(f, d); + if (PrevPortal != NULL) PrevPortal->PopState(); + GLRenderer->mCurrentPortal = PrevPortal; + GLRenderer->mClipPortal = PrevClipPortal; if (usestencil) { @@ -806,14 +804,59 @@ void GLPlaneMirrorPortal::DrawContents() PlaneMirrorMode=old_pm; } +void GLPlaneMirrorPortal::PushState() +{ + planestack.Push(gl_RenderState.GetClipHeight()); + planestack.Push(gl_RenderState.GetClipHeightDirection()); + gl_RenderState.SetClipHeight(0.f, 0.f); +} + +void GLPlaneMirrorPortal::PopState() +{ + float d, f; + planestack.Pop(d); + planestack.Pop(f); + gl_RenderState.SetClipHeight(f, d); +} + //----------------------------------------------------------------------------- // -// GLPlaneMirrorPortal::DrawContents +// Common code for line to line and mirror portals // //----------------------------------------------------------------------------- +int GLLinePortal::ClipSeg(seg_t *seg) +{ + line_t *linedef = seg->linedef; + if (!linedef) + { + return PClip_Inside; // should be handled properly. + } + return P_ClipLineToPortal(linedef, line(), ViewPos) ? PClip_InFront : PClip_Inside; +} + +int GLLinePortal::ClipSubsector(subsector_t *sub) +{ + // this seg is completely behind the mirror! + for(unsigned int i=0;inumlines;i++) + { + if (P_PointOnLineSidePrecise(sub->firstline[i].v1->fPos(), line()) == 0) return PClip_Inside; + } + return PClip_InFront; +} + +int GLLinePortal::ClipPoint(const DVector2 &pos) +{ + if (P_PointOnLineSidePrecise(pos, line())) + { + return PClip_InFront; + } + return PClip_Inside; +} + + //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // @@ -837,7 +880,7 @@ void GLMirrorPortal::DrawContents() return; } - GLRenderer->mCurrentPortal = this; + GLRenderer->mClipPortal = this; DAngle StartAngle = ViewAngle; DVector3 StartPos = ViewPos; @@ -910,37 +953,6 @@ void GLMirrorPortal::DrawContents() MirrorFlag--; } - -int GLLinePortal::ClipSeg(seg_t *seg) -{ - line_t *linedef = seg->linedef; - if (!linedef) - { - return PClip_Inside; // should be handled properly. - } - return P_ClipLineToPortal(linedef, line(), ViewPos) ? PClip_InFront : PClip_Inside; -} - -int GLLinePortal::ClipSubsector(subsector_t *sub) -{ - // this seg is completely behind the mirror! - for(unsigned int i=0;inumlines;i++) - { - if (P_PointOnLineSidePrecise(sub->firstline[i].v1->fPos(), line()) == 0) return PClip_Inside; - } - return PClip_InFront; -} - -int GLLinePortal::ClipPoint(const DVector2 &pos) -{ - if (P_PointOnLineSidePrecise(pos, line())) - { - return PClip_InFront; - } - return PClip_Inside; -} - - //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // @@ -965,7 +977,7 @@ void GLLineToLinePortal::DrawContents() return; } - GLRenderer->mCurrentPortal = this; + GLRenderer->mClipPortal = this; line_t *origin = glport->reference->mOrigin; P_TranslatePortalXY(origin, ViewPos.X, ViewPos.Y); diff --git a/src/gl/scene/gl_portal.h b/src/gl/scene/gl_portal.h index 8fe54c5b1..870009845 100644 --- a/src/gl/scene/gl_portal.h +++ b/src/gl/scene/gl_portal.h @@ -107,7 +107,8 @@ private: area_t savedviewarea; bool savedshowviewer; DVector3 savedviewpath[2]; - GLPortal *NextPortal; + GLPortal *PrevPortal; + GLPortal *PrevClipPortal; TArray savedmapsection; TArray mPrimIndices; @@ -130,6 +131,8 @@ protected: virtual const char *GetName() = 0; void SaveMapSection(); void RestoreMapSection(); + virtual void PushState() {} + virtual void PopState() {} public: @@ -341,6 +344,8 @@ protected: virtual void DrawContents(); virtual void * GetSource() const { return origin; } virtual const char *GetName(); + virtual void PushState(); + virtual void PopState(); secplane_t * origin; public: diff --git a/src/gl/scene/gl_scene.cpp b/src/gl/scene/gl_scene.cpp index f09343f44..1b6b8e87f 100644 --- a/src/gl/scene/gl_scene.cpp +++ b/src/gl/scene/gl_scene.cpp @@ -503,7 +503,7 @@ void FGLRenderer::DrawScene(bool toscreen) static int recursion=0; CreateScene(); - GLRenderer->mCurrentPortal = NULL; // this must be reset before any portal recursion takes place. + GLRenderer->mClipPortal = NULL; // this must be reset before any portal recursion takes place. // Up to this point in the main draw call no rendering is performed so we can wait // with swapping the render buffer until now. diff --git a/src/gl/scene/gl_sprite.cpp b/src/gl/scene/gl_sprite.cpp index 942a2e555..63a4f9c8c 100644 --- a/src/gl/scene/gl_sprite.cpp +++ b/src/gl/scene/gl_sprite.cpp @@ -581,9 +581,9 @@ void GLSprite::Process(AActor* thing, sector_t * sector, bool thruportal) thing->flags7 |= MF7_FLYCHEAT; // do this only once for the very first frame, but not if it gets into range again. } - if (GLRenderer->mCurrentPortal) + if (GLRenderer->mClipPortal) { - int clipres = GLRenderer->mCurrentPortal->ClipPoint(thingpos); + int clipres = GLRenderer->mClipPortal->ClipPoint(thingpos); if (clipres == GLPortal::PClip_InFront) return; } @@ -894,9 +894,9 @@ void GLSprite::Process(AActor* thing, sector_t * sector, bool thruportal) void GLSprite::ProcessParticle (particle_t *particle, sector_t *sector)//, int shade, int fakeside) { - if (GLRenderer->mCurrentPortal) + if (GLRenderer->mClipPortal) { - int clipres = GLRenderer->mCurrentPortal->ClipPoint(particle->Pos); + int clipres = GLRenderer->mClipPortal->ClipPoint(particle->Pos); if (clipres == GLPortal::PClip_InFront) return; } diff --git a/src/gl/shaders/gl_shader.cpp b/src/gl/shaders/gl_shader.cpp index a86c57101..ea8f5aa92 100644 --- a/src/gl/shaders/gl_shader.cpp +++ b/src/gl/shaders/gl_shader.cpp @@ -278,6 +278,7 @@ bool FShader::Load(const char * name, const char * vert_prog_lump, const char * muGlowTopPlane.Init(hShader, "uGlowTopPlane"); muSplitBottomPlane.Init(hShader, "uSplitBottomPlane"); muSplitTopPlane.Init(hShader, "uSplitTopPlane"); + muClipLine.Init(hShader, "uClipLine"); muFixedColormap.Init(hShader, "uFixedColormap"); muInterpolationFactor.Init(hShader, "uInterpolationFactor"); muClipHeight.Init(hShader, "uClipHeight"); diff --git a/src/gl/shaders/gl_shader.h b/src/gl/shaders/gl_shader.h index a7f7e4277..ca534c31d 100644 --- a/src/gl/shaders/gl_shader.h +++ b/src/gl/shaders/gl_shader.h @@ -220,6 +220,7 @@ class FShader FUniform4f muGlowTopPlane; FUniform4f muSplitBottomPlane; FUniform4f muSplitTopPlane; + FUniform4f muClipLine; FBufferedUniform1f muInterpolationFactor; FBufferedUniform1f muClipHeight; FBufferedUniform1f muClipHeightDirection; @@ -234,22 +235,18 @@ class FShader public: int fakevb_index; private: - int currentglowstate; - int currentsplitstate; - int currentfixedcolormap; - bool currentTextureMatrixState; - bool currentModelMatrixState; + int currentglowstate = 0; + int currentsplitstate = 0; + int currentcliplinestate = 0; + int currentfixedcolormap = 0; + bool currentTextureMatrixState = true;// by setting the matrix state to 'true' it is guaranteed to be set the first time the render state gets applied. + bool currentModelMatrixState = true; public: FShader(const char *name) : mName(name) { hShader = hVertProg = hFragProg = 0; - currentglowstate = 0; - currentsplitstate = 0; - currentfixedcolormap = 0; - currentTextureMatrixState = true; // by setting the matrix state to 'true' it is guaranteed to be set the first time the render state gets applied. - currentModelMatrixState = true; } ~FShader(); diff --git a/wadsrc/static/shaders/glsl/shaderdefs.i b/wadsrc/static/shaders/glsl/shaderdefs.i index 5259bb5fd..7500a0cfc 100644 --- a/wadsrc/static/shaders/glsl/shaderdefs.i +++ b/wadsrc/static/shaders/glsl/shaderdefs.i @@ -8,6 +8,7 @@ uniform vec4 uCameraPos; uniform int uTextureMode; uniform float uClipHeight, uClipHeightDirection; uniform vec2 uClipSplit; +uniform vec4 uClipLine; uniform float uAlphaThreshold;