mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-11 07:11:54 +00:00
- 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:
parent
510aa600dd
commit
3c3be0d349
7 changed files with 152 additions and 29 deletions
|
@ -38,6 +38,8 @@
|
||||||
#include "gl/renderer/gl_renderbuffers.h"
|
#include "gl/renderer/gl_renderbuffers.h"
|
||||||
#include "gl/textures/gl_hwtexture.h"
|
#include "gl/textures/gl_hwtexture.h"
|
||||||
|
|
||||||
|
static int op2gl[] = { GL_KEEP, GL_INCR, GL_DECR };
|
||||||
|
|
||||||
FGLRenderState gl_RenderState;
|
FGLRenderState gl_RenderState;
|
||||||
|
|
||||||
CVAR(Bool, gl_direct_state_change, true, 0)
|
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 != mCurrentVertexBuffer)
|
||||||
{
|
{
|
||||||
if (mVertexBuffer == NULL) glBindBuffer(GL_ARRAY_BUFFER, 0);
|
if (mVertexBuffer == NULL) glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||||
|
|
|
@ -233,6 +233,14 @@ public:
|
||||||
return mPassType == GBUFFER_PASS ? 3 : 1;
|
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;
|
extern FGLRenderState gl_RenderState;
|
||||||
|
|
|
@ -273,5 +273,33 @@ bool FDrawInfo::SetDepthClamp(bool on)
|
||||||
return gl_RenderState.SetDepthClamp(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();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -52,6 +52,9 @@ struct FDrawInfo : public HWDrawInfo
|
||||||
std::pair<FFlatVertex *, unsigned int> AllocVertices(unsigned int count) override;
|
std::pair<FFlatVertex *, unsigned int> AllocVertices(unsigned int count) override;
|
||||||
int UploadLights(FDynLightData &data) 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 DrawDecal(GLDecal *gldecal);
|
||||||
void DrawDecals();
|
void DrawDecals();
|
||||||
void DrawDecalsForMirror(GLWall *wall);
|
void DrawDecalsForMirror(GLWall *wall);
|
||||||
|
|
|
@ -69,9 +69,7 @@ void FDrawInfo::DrawSubsectors(GLFlat *flat, int pass, bool istrans)
|
||||||
gl_RenderState.ApplyLightIndex(flat->dynlightindex);
|
gl_RenderState.ApplyLightIndex(flat->dynlightindex);
|
||||||
if (vcount > 0 && !ClipLineShouldBeActive())
|
if (vcount > 0 && !ClipLineShouldBeActive())
|
||||||
{
|
{
|
||||||
drawcalls.Clock();
|
DrawIndexed(DT_Triangles, gl_RenderState, iboindex, vcount);
|
||||||
glDrawElements(GL_TRIANGLES, vcount, GL_UNSIGNED_INT, GLRenderer->mVBO->GetIndexPointer() + iboindex);
|
|
||||||
drawcalls.Unclock();
|
|
||||||
flatvertices += vcount;
|
flatvertices += vcount;
|
||||||
flatprimitives++;
|
flatprimitives++;
|
||||||
}
|
}
|
||||||
|
@ -85,8 +83,7 @@ void FDrawInfo::DrawSubsectors(GLFlat *flat, int pass, bool istrans)
|
||||||
|
|
||||||
if (ss_renderflags[sub->Index()] & flat->renderflags || istrans)
|
if (ss_renderflags[sub->Index()] & flat->renderflags || istrans)
|
||||||
{
|
{
|
||||||
drawcalls.Clock();
|
DrawIndexed(DT_Triangles, gl_RenderState, index, (sub->numlines - 2) * 3, false);
|
||||||
glDrawElements(GL_TRIANGLES, (sub->numlines - 2) * 3, GL_UNSIGNED_INT, GLRenderer->mVBO->GetIndexPointer() + index);
|
|
||||||
drawcalls.Unclock();
|
drawcalls.Unclock();
|
||||||
flatvertices += sub->numlines;
|
flatvertices += sub->numlines;
|
||||||
flatprimitives++;
|
flatprimitives++;
|
||||||
|
@ -108,7 +105,7 @@ void FDrawInfo::DrawSubsectors(GLFlat *flat, int pass, bool istrans)
|
||||||
auto num = node->sub->numlines;
|
auto num = node->sub->numlines;
|
||||||
flatvertices += num;
|
flatvertices += num;
|
||||||
flatprimitives++;
|
flatprimitives++;
|
||||||
glDrawArrays(GL_TRIANGLE_FAN, node->vertexindex, num);
|
Draw(DT_TriangleFan, gl_RenderState, node->vertexindex, num);
|
||||||
node = node->next;
|
node = node->next;
|
||||||
}
|
}
|
||||||
// Flood gaps with the back side's ceiling/floor texture
|
// 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);
|
glPolygonOffset(1.0f, 128.0f);
|
||||||
|
|
||||||
SetupFloodStencil(fnode->vertexindex);
|
SetupFloodStencil(fnode->vertexindex);
|
||||||
glDrawArrays(GL_TRIANGLE_FAN, fnode->vertexindex + 4, 4);
|
Draw(DT_TriangleFan, gl_RenderState, fnode->vertexindex + 4, 4);
|
||||||
ClearFloodStencil(fnode->vertexindex);
|
ClearFloodStencil(fnode->vertexindex);
|
||||||
|
|
||||||
glPolygonOffset(0.0f, 0.0f);
|
glPolygonOffset(0.0f, 0.0f);
|
||||||
|
@ -156,21 +153,12 @@ void FDrawInfo::SetupFloodStencil(int vindex)
|
||||||
gl_RenderState.EnableTexture(false);
|
gl_RenderState.EnableTexture(false);
|
||||||
gl_RenderState.Apply();
|
gl_RenderState.Apply();
|
||||||
|
|
||||||
glStencilFunc(GL_EQUAL, recursion, ~0); // create stencil
|
gl_RenderState.SetStencil(0, SOP_Increment, SF_ColorMaskOff);
|
||||||
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);
|
|
||||||
|
|
||||||
glDrawArrays(GL_TRIANGLE_FAN, vindex, 4);
|
Draw(DT_TriangleFan, gl_RenderState, vindex, 4);
|
||||||
|
|
||||||
glStencilFunc(GL_EQUAL, recursion + 1, ~0); // draw sky into stencil
|
gl_RenderState.SetStencil(1, SOP_Keep, SF_DepthMaskOff | SF_DepthTestOff);
|
||||||
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); // this stage doesn't modify the stencil
|
|
||||||
|
|
||||||
glColorMask(1, 1, 1, 1); // don't write to the graphics buffer
|
|
||||||
glDisable(GL_DEPTH_TEST);
|
|
||||||
glDepthMask(false);
|
|
||||||
gl_RenderState.EnableTexture(true);
|
gl_RenderState.EnableTexture(true);
|
||||||
gl_RenderState.SetEffect(EFF_NONE);
|
gl_RenderState.SetEffect(EFF_NONE);
|
||||||
gl_RenderState.Apply();
|
gl_RenderState.Apply();
|
||||||
|
@ -183,18 +171,13 @@ void FDrawInfo::ClearFloodStencil(int vindex)
|
||||||
gl_RenderState.SetEffect(EFF_STENCIL);
|
gl_RenderState.SetEffect(EFF_STENCIL);
|
||||||
gl_RenderState.EnableTexture(false);
|
gl_RenderState.EnableTexture(false);
|
||||||
gl_RenderState.Apply();
|
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.
|
// restore old stencil op.
|
||||||
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
|
gl_RenderState.SetStencil(0, SOP_Keep, SF_AllOn);
|
||||||
glStencilFunc(GL_EQUAL, recursion, ~0);
|
|
||||||
glColorMask(1, 1, 1, 1);
|
|
||||||
glEnable(GL_DEPTH_TEST);
|
|
||||||
glDepthMask(true);
|
|
||||||
gl_RenderState.EnableTexture(true);
|
gl_RenderState.EnableTexture(true);
|
||||||
gl_RenderState.SetEffect(EFF_NONE);
|
gl_RenderState.SetEffect(EFF_NONE);
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,14 @@
|
||||||
#include "hw_viewpointuniforms.h"
|
#include "hw_viewpointuniforms.h"
|
||||||
#include "v_video.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 FSectorPortalGroup;
|
||||||
struct FLinePortalSpan;
|
struct FLinePortalSpan;
|
||||||
|
@ -24,6 +32,7 @@ class IPortal;
|
||||||
class FFlatVertexGenerator;
|
class FFlatVertexGenerator;
|
||||||
class IRenderQueue;
|
class IRenderQueue;
|
||||||
class HWScenePortalBase;
|
class HWScenePortalBase;
|
||||||
|
class FRenderState;
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
|
@ -295,5 +304,9 @@ public:
|
||||||
|
|
||||||
virtual GLDecal *AddDecal(bool onmirror) = 0;
|
virtual GLDecal *AddDecal(bool onmirror) = 0;
|
||||||
virtual std::pair<FFlatVertex *, unsigned int> AllocVertices(unsigned int count) = 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;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#include "vectors.h"
|
#include "vectors.h"
|
||||||
#include "g_levellocals.h"
|
#include "g_levellocals.h"
|
||||||
#include "r_data/matrix.h"
|
#include "r_data/matrix.h"
|
||||||
|
#include "hwrenderer/textures/hw_material.h"
|
||||||
|
|
||||||
struct FColormap;
|
struct FColormap;
|
||||||
|
|
||||||
|
@ -18,12 +19,27 @@ enum EEffect
|
||||||
MAX_EFFECTS
|
MAX_EFFECTS
|
||||||
};
|
};
|
||||||
|
|
||||||
enum
|
enum EAlphaFunc
|
||||||
{
|
{
|
||||||
Alpha_GEqual = 0,
|
Alpha_GEqual = 0,
|
||||||
Alpha_Greater = 1
|
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
|
struct FStateVec4
|
||||||
{
|
{
|
||||||
float vec[4];
|
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
|
class FRenderState
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
|
@ -66,6 +116,8 @@ protected:
|
||||||
PalEntry mObjectColor2;
|
PalEntry mObjectColor2;
|
||||||
FStateVec4 mDynColor;
|
FStateVec4 mDynColor;
|
||||||
|
|
||||||
|
FMaterialState mMaterial;
|
||||||
|
FStencilState mStencil;
|
||||||
|
|
||||||
// fixed function state
|
// fixed function state
|
||||||
float mBias[2];
|
float mBias[2];
|
||||||
|
@ -95,6 +147,7 @@ public:
|
||||||
mSpecialEffect = EFF_NONE;
|
mSpecialEffect = EFF_NONE;
|
||||||
mLightIndex = -1;
|
mLightIndex = -1;
|
||||||
mBiasOn = false;
|
mBiasOn = false;
|
||||||
|
mMaterial.Reset();
|
||||||
|
|
||||||
mColor.Set(1.0f, 1.0f, 1.0f, 1.0f);
|
mColor.Set(1.0f, 1.0f, 1.0f, 1.0f);
|
||||||
mGlowTop.Set(0.0f, 0.0f, 0.0f, 0.0f);
|
mGlowTop.Set(0.0f, 0.0f, 0.0f, 0.0f);
|
||||||
|
@ -283,6 +336,23 @@ public:
|
||||||
mBiasOn = false;
|
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 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);
|
void SetFog(int lightlevel, int rellight, bool fullbright, const FColormap *cmap, bool isadditive);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue