- started with an abstract render interface, most importantly handle the stencil for plane flooding through the render state object instead of changing GL state directly.

This commit is contained in:
Christoph Oelckers 2018-10-20 21:08:24 +02:00
parent 510aa600dd
commit 3c3be0d349
7 changed files with 152 additions and 29 deletions

View File

@ -38,6 +38,8 @@
#include "gl/renderer/gl_renderbuffers.h"
#include "gl/textures/gl_hwtexture.h"
static int op2gl[] = { GL_KEEP, GL_INCR, GL_DECR };
FGLRenderState gl_RenderState;
CVAR(Bool, gl_direct_state_change, true, 0)
@ -226,6 +228,22 @@ void FGLRenderState::Apply()
}
}
if (mStencil.mChanged)
{
int recursion = GLRenderer->mPortalState.GetRecursion();
glStencilFunc(GL_EQUAL, recursion + mStencil.mOffsVal, ~0); // draw sky into stencil
glStencilOp(GL_KEEP, GL_KEEP, op2gl[mStencil.mOperation]); // this stage doesn't modify the stencil
bool cmon = !(mStencil.mFlags & SF_ColorMaskOff);
glColorMask(cmon, cmon, cmon, cmon); // don't write to the graphics buffer
glDepthMask(!(mStencil.mFlags & SF_DepthMaskOff));
if (mStencil.mFlags & SF_DepthTestOff)
glDisable(GL_DEPTH_TEST);
else
glEnable(GL_DEPTH_TEST);
}
if (mVertexBuffer != mCurrentVertexBuffer)
{
if (mVertexBuffer == NULL) glBindBuffer(GL_ARRAY_BUFFER, 0);

View File

@ -233,6 +233,14 @@ public:
return mPassType == GBUFFER_PASS ? 3 : 1;
}
void ApplyMaterial()
{
if (mMaterial.mChanged)
{
SetMaterial(mMaterial.mMaterial, mMaterial.mClampMode, mMaterial.mTranslation, mMaterial.mOverrideShader, false);
mMaterial.mChanged = false;
}
}
};
extern FGLRenderState gl_RenderState;

View File

@ -273,5 +273,33 @@ 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.ApplyMaterial();
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.ApplyMaterial();
gl_RenderState.Apply();
}
drawcalls.Clock();
glDrawElements(dt2gl[dt], count, GL_UNSIGNED_INT, GLRenderer->mVBO->GetIndexPointer() + index);
drawcalls.Unclock();
}

View File

@ -52,6 +52,9 @@ struct FDrawInfo : public HWDrawInfo
std::pair<FFlatVertex *, unsigned int> AllocVertices(unsigned int count) override;
int UploadLights(FDynLightData &data) override;
void Draw(EDrawType dt, FRenderState &state, int index, int count, bool apply = true);
void DrawIndexed(EDrawType dt, FRenderState &state, int index, int count, bool apply = true);
void DrawDecal(GLDecal *gldecal);
void DrawDecals();
void DrawDecalsForMirror(GLWall *wall);

View File

@ -69,9 +69,7 @@ void FDrawInfo::DrawSubsectors(GLFlat *flat, int pass, bool istrans)
gl_RenderState.ApplyLightIndex(flat->dynlightindex);
if (vcount > 0 && !ClipLineShouldBeActive())
{
drawcalls.Clock();
glDrawElements(GL_TRIANGLES, vcount, GL_UNSIGNED_INT, GLRenderer->mVBO->GetIndexPointer() + iboindex);
drawcalls.Unclock();
DrawIndexed(DT_Triangles, gl_RenderState, iboindex, vcount);
flatvertices += vcount;
flatprimitives++;
}
@ -85,8 +83,7 @@ void FDrawInfo::DrawSubsectors(GLFlat *flat, int pass, bool istrans)
if (ss_renderflags[sub->Index()] & flat->renderflags || istrans)
{
drawcalls.Clock();
glDrawElements(GL_TRIANGLES, (sub->numlines - 2) * 3, GL_UNSIGNED_INT, GLRenderer->mVBO->GetIndexPointer() + index);
DrawIndexed(DT_Triangles, gl_RenderState, index, (sub->numlines - 2) * 3, false);
drawcalls.Unclock();
flatvertices += sub->numlines;
flatprimitives++;
@ -108,7 +105,7 @@ void FDrawInfo::DrawSubsectors(GLFlat *flat, int pass, bool istrans)
auto num = node->sub->numlines;
flatvertices += num;
flatprimitives++;
glDrawArrays(GL_TRIANGLE_FAN, node->vertexindex, num);
Draw(DT_TriangleFan, gl_RenderState, node->vertexindex, num);
node = node->next;
}
// Flood gaps with the back side's ceiling/floor texture
@ -130,7 +127,7 @@ void FDrawInfo::DrawSubsectors(GLFlat *flat, int pass, bool istrans)
glPolygonOffset(1.0f, 128.0f);
SetupFloodStencil(fnode->vertexindex);
glDrawArrays(GL_TRIANGLE_FAN, fnode->vertexindex + 4, 4);
Draw(DT_TriangleFan, gl_RenderState, fnode->vertexindex + 4, 4);
ClearFloodStencil(fnode->vertexindex);
glPolygonOffset(0.0f, 0.0f);
@ -156,21 +153,12 @@ void FDrawInfo::SetupFloodStencil(int vindex)
gl_RenderState.EnableTexture(false);
gl_RenderState.Apply();
glStencilFunc(GL_EQUAL, recursion, ~0); // create stencil
glStencilOp(GL_KEEP, GL_KEEP, GL_INCR); // increment stencil of valid pixels
glColorMask(0, 0, 0, 0); // don't write to the graphics buffer
glEnable(GL_DEPTH_TEST);
glDepthMask(true);
gl_RenderState.SetStencil(0, SOP_Increment, SF_ColorMaskOff);
glDrawArrays(GL_TRIANGLE_FAN, vindex, 4);
Draw(DT_TriangleFan, gl_RenderState, vindex, 4);
glStencilFunc(GL_EQUAL, recursion + 1, ~0); // draw sky into stencil
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); // this stage doesn't modify the stencil
gl_RenderState.SetStencil(1, SOP_Keep, SF_DepthMaskOff | SF_DepthTestOff);
glColorMask(1, 1, 1, 1); // don't write to the graphics buffer
glDisable(GL_DEPTH_TEST);
glDepthMask(false);
gl_RenderState.EnableTexture(true);
gl_RenderState.SetEffect(EFF_NONE);
gl_RenderState.Apply();
@ -183,18 +171,13 @@ void FDrawInfo::ClearFloodStencil(int vindex)
gl_RenderState.SetEffect(EFF_STENCIL);
gl_RenderState.EnableTexture(false);
gl_RenderState.Apply();
glStencilOp(GL_KEEP, GL_KEEP, GL_DECR);
// Use revertible color mask, to avoid stomping on anaglyph 3D state
glColorMask(0, 0, 0, 0); // don't write to the graphics buffer
glDrawArrays(GL_TRIANGLE_FAN, vindex, 4);
gl_RenderState.SetStencil(1, SOP_Decrement, SF_ColorMaskOff | SF_DepthMaskOff | SF_DepthTestOff);
Draw(DT_TriangleFan, gl_RenderState, vindex, 4);
// restore old stencil op.
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
glStencilFunc(GL_EQUAL, recursion, ~0);
glColorMask(1, 1, 1, 1);
glEnable(GL_DEPTH_TEST);
glDepthMask(true);
gl_RenderState.SetStencil(0, SOP_Keep, SF_AllOn);
gl_RenderState.EnableTexture(true);
gl_RenderState.SetEffect(EFF_NONE);
}

View File

@ -7,6 +7,14 @@
#include "hw_viewpointuniforms.h"
#include "v_video.h"
enum EDrawType
{
DT_Points = 0,
DT_Lines = 1,
DT_Triangles = 2,
DT_TriangleFan = 3,
DT_TriangleStrip = 4
};
struct FSectorPortalGroup;
struct FLinePortalSpan;
@ -24,6 +32,7 @@ class IPortal;
class FFlatVertexGenerator;
class IRenderQueue;
class HWScenePortalBase;
class FRenderState;
//==========================================================================
//
@ -295,5 +304,9 @@ public:
virtual GLDecal *AddDecal(bool onmirror) = 0;
virtual std::pair<FFlatVertex *, unsigned int> AllocVertices(unsigned int count) = 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;
};

View File

@ -4,6 +4,7 @@
#include "vectors.h"
#include "g_levellocals.h"
#include "r_data/matrix.h"
#include "hwrenderer/textures/hw_material.h"
struct FColormap;
@ -18,12 +19,27 @@ enum EEffect
MAX_EFFECTS
};
enum
enum EAlphaFunc
{
Alpha_GEqual = 0,
Alpha_Greater = 1
};
enum EStencilOp
{
SOP_Keep = 0,
SOP_Increment = 1,
SOP_Decrement = 2
};
enum EStencilFlags
{
SF_AllOn = 0,
SF_ColorMaskOff = 1,
SF_DepthMaskOff = 2,
SF_DepthTestOff = 4
};
struct FStateVec4
{
float vec[4];
@ -37,6 +53,40 @@ struct FStateVec4
}
};
struct FMaterialState
{
FMaterial *mMaterial;
int mClampMode;
int mTranslation;
int mOverrideShader;
bool mChanged;
void Reset()
{
mMaterial = nullptr;
mTranslation = 0;
mClampMode = CLAMP_NONE;
mOverrideShader = -1;
mChanged = false;
}
};
struct FStencilState
{
int mOffsVal;
int mOperation;
int mFlags;
bool mChanged;
void Reset()
{
mOffsVal = 0;
mOperation = SOP_Keep;
mFlags = SF_AllOn;
mChanged = false;
}
};
class FRenderState
{
protected:
@ -66,6 +116,8 @@ protected:
PalEntry mObjectColor2;
FStateVec4 mDynColor;
FMaterialState mMaterial;
FStencilState mStencil;
// fixed function state
float mBias[2];
@ -95,6 +147,7 @@ public:
mSpecialEffect = EFF_NONE;
mLightIndex = -1;
mBiasOn = false;
mMaterial.Reset();
mColor.Set(1.0f, 1.0f, 1.0f, 1.0f);
mGlowTop.Set(0.0f, 0.0f, 0.0f, 0.0f);
@ -283,6 +336,23 @@ public:
mBiasOn = false;
}
void SetMaterial(FMaterial *mat, int clampmode, int translation, int overrideshader)
{
mMaterial.mMaterial = mat;
mMaterial.mClampMode = clampmode;
mMaterial.mTranslation = translation;
mMaterial.mOverrideShader = overrideshader;
mMaterial.mChanged = true;
}
void SetStencil(int offs, int op, int flags)
{
mStencil.mOffsVal = offs;
mStencil.mOperation = op;
mStencil.mFlags = flags;
mStencil.mChanged = true;
}
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);