- preparations for using clip planes on line portals.

This commit is contained in:
Christoph Oelckers 2016-04-29 01:48:06 +02:00
parent e3fad118d2
commit 21283b18f4
12 changed files with 133 additions and 70 deletions

View file

@ -84,6 +84,7 @@
FGLRenderer::FGLRenderer(OpenGLFrameBuffer *fb)
{
framebuffer = fb;
mClipPortal = NULL;
mCurrentPortal = NULL;
mMirrorCount = 0;
mPlaneMirrorCount = 0;

View file

@ -59,6 +59,7 @@ class FGLRenderer
public:
OpenGLFrameBuffer *framebuffer;
GLPortal *mClipPortal;
GLPortal *mCurrentPortal;
int mMirrorCount;
int mPlaneMirrorCount;

View file

@ -69,7 +69,7 @@ TArray<VSMatrix> 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)

View file

@ -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;

View file

@ -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;

View file

@ -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;i<sub->numlines;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;i<sub->numlines;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);

View file

@ -107,7 +107,8 @@ private:
area_t savedviewarea;
bool savedshowviewer;
DVector3 savedviewpath[2];
GLPortal *NextPortal;
GLPortal *PrevPortal;
GLPortal *PrevClipPortal;
TArray<BYTE> savedmapsection;
TArray<unsigned int> 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:

View file

@ -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.

View file

@ -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;
}

View file

@ -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");

View file

@ -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();

View file

@ -8,6 +8,7 @@ uniform vec4 uCameraPos;
uniform int uTextureMode;
uniform float uClipHeight, uClipHeightDirection;
uniform vec2 uClipSplit;
uniform vec4 uClipLine;
uniform float uAlphaThreshold;