Made stencil per face side

Former-commit-id: 093f2125886d47ebc79f97aaecfad3a5216f399a
This commit is contained in:
Lynix 2013-09-06 18:17:58 +02:00
parent 1ed8ea8ad5
commit d4abb8fc49
5 changed files with 214 additions and 71 deletions

View File

@ -17,20 +17,26 @@ struct NzRenderStates
NzRenderStates& operator=(const NzRenderStates& states); NzRenderStates& operator=(const NzRenderStates& states);
struct Face
{
nzRendererComparison stencilCompare;
nzStencilOperation stencilFail;
nzStencilOperation stencilPass;
nzStencilOperation stencilZFail;
nzUInt32 stencilMask;
unsigned int stencilReference;
};
Face backFace;
Face frontFace;
nzBlendFunc dstBlend; nzBlendFunc dstBlend;
nzBlendFunc srcBlend; nzBlendFunc srcBlend;
nzFaceFilling faceFilling; nzFaceFilling faceFilling;
nzFaceSide faceCulling; nzFaceSide faceCulling;
nzRendererComparison depthFunc; nzRendererComparison depthFunc;
nzRendererComparison stencilCompare;
nzStencilOperation stencilFail;
nzStencilOperation stencilPass;
nzStencilOperation stencilZFail;
nzUInt32 stencilMask;
bool parameters[nzRendererParameter_Max+1]; bool parameters[nzRendererParameter_Max+1];
float lineWidth; float lineWidth;
float pointSize; float pointSize;
unsigned int stencilReference;
}; };
#include <Nazara/Renderer/RenderStates.inl> #include <Nazara/Renderer/RenderStates.inl>

View File

@ -11,14 +11,8 @@ srcBlend(nzBlendFunc_One),
faceFilling(nzFaceFilling_Fill), faceFilling(nzFaceFilling_Fill),
faceCulling(nzFaceSide_Back), faceCulling(nzFaceSide_Back),
depthFunc(nzRendererComparison_Less), depthFunc(nzRendererComparison_Less),
stencilCompare(nzRendererComparison_Always),
stencilFail(nzStencilOperation_Keep),
stencilPass(nzStencilOperation_Keep),
stencilZFail(nzStencilOperation_Keep),
stencilMask(0xFFFFFFFF),
lineWidth(1.f), lineWidth(1.f),
pointSize(1.f), pointSize(1.f)
stencilReference(0)
{ {
parameters[nzRendererParameter_Blend] = false; parameters[nzRendererParameter_Blend] = false;
parameters[nzRendererParameter_ColorWrite] = true; parameters[nzRendererParameter_ColorWrite] = true;
@ -27,6 +21,18 @@ stencilReference(0)
parameters[nzRendererParameter_FaceCulling] = false; parameters[nzRendererParameter_FaceCulling] = false;
parameters[nzRendererParameter_ScissorTest] = false; parameters[nzRendererParameter_ScissorTest] = false;
parameters[nzRendererParameter_StencilTest] = false; parameters[nzRendererParameter_StencilTest] = false;
for (unsigned int i = 0; i < 2; ++i)
{
Face& face = (i == 0) ? backFace : frontFace;
face.stencilCompare = nzRendererComparison_Always;
face.stencilFail = nzStencilOperation_Keep;
face.stencilMask = 0xFFFFFFFF;
face.stencilPass = nzStencilOperation_Keep;
face.stencilReference = 0;
face.stencilZFail = nzStencilOperation_Keep;
}
} }
inline NzRenderStates::NzRenderStates(const NzRenderStates& states) inline NzRenderStates::NzRenderStates(const NzRenderStates& states)

View File

@ -88,12 +88,12 @@ class NAZARA_API NzRenderer
static void SetRenderStates(const NzRenderStates& states); static void SetRenderStates(const NzRenderStates& states);
static void SetScissorRect(const NzRecti& rect); static void SetScissorRect(const NzRecti& rect);
static void SetShaderProgram(const NzShaderProgram* shader); static void SetShaderProgram(const NzShaderProgram* shader);
static void SetStencilCompareFunction(nzRendererComparison compareFunc); static void SetStencilCompareFunction(nzRendererComparison compareFunc, nzFaceSide faceSide = nzFaceSide_FrontAndBack);
static void SetStencilFailOperation(nzStencilOperation failOperation); static void SetStencilFailOperation(nzStencilOperation failOperation, nzFaceSide faceSide = nzFaceSide_FrontAndBack);
static void SetStencilMask(nzUInt32 mask); static void SetStencilMask(nzUInt32 mask, nzFaceSide faceSide = nzFaceSide_FrontAndBack);
static void SetStencilPassOperation(nzStencilOperation passOperation); static void SetStencilPassOperation(nzStencilOperation passOperation, nzFaceSide faceSide = nzFaceSide_FrontAndBack);
static void SetStencilReferenceValue(unsigned int refValue); static void SetStencilReferenceValue(unsigned int refValue, nzFaceSide faceSide = nzFaceSide_FrontAndBack);
static void SetStencilZFailOperation(nzStencilOperation zfailOperation); static void SetStencilZFailOperation(nzStencilOperation zfailOperation, nzFaceSide faceSide = nzFaceSide_FrontAndBack);
static bool SetTarget(const NzRenderTarget* target); static bool SetTarget(const NzRenderTarget* target);
static void SetTexture(nzUInt8 unit, const NzTexture* texture); static void SetTexture(nzUInt8 unit, const NzTexture* texture);
static void SetTextureSampler(nzUInt8 textureUnit, const NzTextureSampler& sampler); static void SetTextureSampler(nzUInt8 textureUnit, const NzTextureSampler& sampler);

View File

@ -191,25 +191,32 @@ void NzOpenGL::ApplyStates(const NzRenderStates& states)
// Ici encore, ça ne sert à rien de se soucier des fonctions de stencil sans qu'il soit activé // Ici encore, ça ne sert à rien de se soucier des fonctions de stencil sans qu'il soit activé
if (states.parameters[nzRendererParameter_StencilTest]) if (states.parameters[nzRendererParameter_StencilTest])
{ {
if (currentRenderStates.stencilCompare != states.stencilCompare || for (unsigned int i = 0; i < 2; ++i)
currentRenderStates.stencilMask != states.stencilMask ||
currentRenderStates.stencilReference != states.stencilReference)
{ {
glStencilFunc(RendererComparison[states.stencilCompare], states.stencilReference, states.stencilMask); GLenum face = (i == 0) ? GL_BACK : GL_FRONT;
currentRenderStates.stencilCompare = states.stencilCompare; const NzRenderStates::Face& srcStates = (i == 0) ? states.backFace : states.frontFace;
currentRenderStates.stencilMask = states.stencilMask; NzRenderStates::Face& dstStates = (i == 0) ? currentRenderStates.backFace : currentRenderStates.frontFace;
currentRenderStates.stencilReference = states.stencilReference;
}
// Ici encore, ça ne sert à rien de se soucier des fonctions de stencil sans qu'il soit activé if (dstStates.stencilCompare != srcStates.stencilCompare ||
if (currentRenderStates.stencilFail != states.stencilFail || dstStates.stencilMask != srcStates.stencilMask ||
currentRenderStates.stencilPass != states.stencilPass || dstStates.stencilReference != srcStates.stencilReference)
currentRenderStates.stencilZFail != states.stencilZFail) {
{ glStencilFuncSeparate(face, RendererComparison[srcStates.stencilCompare], srcStates.stencilReference, srcStates.stencilMask);
glStencilOp(StencilOperation[states.stencilFail], StencilOperation[states.stencilZFail], StencilOperation[states.stencilPass]); dstStates.stencilCompare = srcStates.stencilCompare;
currentRenderStates.stencilFail = states.stencilFail; dstStates.stencilMask = srcStates.stencilMask;
currentRenderStates.stencilPass = states.stencilPass; dstStates.stencilReference = srcStates.stencilReference;
currentRenderStates.stencilZFail = states.stencilZFail; }
// Ici encore, ça ne sert à rien de se soucier des fonctions de stencil sans qu'il soit activé
if (dstStates.stencilFail != srcStates.stencilFail ||
dstStates.stencilPass != srcStates.stencilPass ||
dstStates.stencilZFail != srcStates.stencilZFail)
{
glStencilOpSeparate(face, StencilOperation[srcStates.stencilFail], StencilOperation[srcStates.stencilZFail], StencilOperation[srcStates.stencilPass]);
dstStates.stencilFail = srcStates.stencilFail;
dstStates.stencilPass = srcStates.stencilPass;
dstStates.stencilZFail = srcStates.stencilZFail;
}
} }
} }
@ -1259,19 +1266,6 @@ void NzOpenGL::SetBuffer(nzBufferType type, GLuint id)
s_contextStates->buffersBinding[type] = id; s_contextStates->buffersBinding[type] = id;
} }
void NzOpenGL::SetProgram(GLuint id)
{
#ifdef NAZARA_DEBUG
if (!s_contextStates)
{
NazaraError("No context activated");
return;
}
#endif
s_contextStates->currentProgram = id;
}
void NzOpenGL::SetScissorBox(const NzRecti& scissorBox) void NzOpenGL::SetScissorBox(const NzRecti& scissorBox)
{ {
#ifdef NAZARA_DEBUG #ifdef NAZARA_DEBUG
@ -1285,6 +1279,19 @@ void NzOpenGL::SetScissorBox(const NzRecti& scissorBox)
s_contextStates->currentScissorBox = scissorBox; s_contextStates->currentScissorBox = scissorBox;
} }
void NzOpenGL::SetProgram(GLuint id)
{
#ifdef NAZARA_DEBUG
if (!s_contextStates)
{
NazaraError("No context activated");
return;
}
#endif
s_contextStates->currentProgram = id;
}
void NzOpenGL::SetTarget(const NzRenderTarget* renderTarget) void NzOpenGL::SetTarget(const NzRenderTarget* renderTarget)
{ {
#ifdef NAZARA_DEBUG #ifdef NAZARA_DEBUG

View File

@ -1051,7 +1051,7 @@ void NzRenderer::SetShaderProgram(const NzShaderProgram* program)
} }
} }
void NzRenderer::SetStencilCompareFunction(nzRendererComparison compareFunc) void NzRenderer::SetStencilCompareFunction(nzRendererComparison compareFunc, nzFaceSide faceSide)
{ {
#ifdef NAZARA_DEBUG #ifdef NAZARA_DEBUG
if (compareFunc > nzRendererComparison_Max) if (compareFunc > nzRendererComparison_Max)
@ -1059,12 +1059,32 @@ void NzRenderer::SetStencilCompareFunction(nzRendererComparison compareFunc)
NazaraError("Renderer comparison out of enum"); NazaraError("Renderer comparison out of enum");
return; return;
} }
if (faceSide > nzFaceSide_Max)
{
NazaraError("Face side out of enum");
return;
}
#endif #endif
s_states.stencilCompare = compareFunc; switch (faceSide)
{
case nzFaceSide_Back:
s_states.backFace.stencilCompare = compareFunc;
break;
case nzFaceSide_Front:
s_states.frontFace.stencilCompare = compareFunc;
break;
case nzFaceSide_FrontAndBack:
s_states.backFace.stencilCompare = compareFunc;
s_states.frontFace.stencilCompare = compareFunc;
break;
}
} }
void NzRenderer::SetStencilFailOperation(nzStencilOperation failOperation) void NzRenderer::SetStencilFailOperation(nzStencilOperation failOperation, nzFaceSide faceSide)
{ {
#ifdef NAZARA_DEBUG #ifdef NAZARA_DEBUG
if (failOperation > nzStencilOperation_Max) if (failOperation > nzStencilOperation_Max)
@ -1072,17 +1092,59 @@ void NzRenderer::SetStencilFailOperation(nzStencilOperation failOperation)
NazaraError("Stencil fail operation out of enum"); NazaraError("Stencil fail operation out of enum");
return; return;
} }
if (faceSide > nzFaceSide_Max)
{
NazaraError("Face side out of enum");
return;
}
#endif #endif
s_states.stencilFail = failOperation; switch (faceSide)
{
case nzFaceSide_Back:
s_states.backFace.stencilFail = failOperation;
break;
case nzFaceSide_Front:
s_states.frontFace.stencilFail = failOperation;
break;
case nzFaceSide_FrontAndBack:
s_states.backFace.stencilFail = failOperation;
s_states.frontFace.stencilFail = failOperation;
break;
}
} }
void NzRenderer::SetStencilMask(nzUInt32 mask) void NzRenderer::SetStencilMask(nzUInt32 mask, nzFaceSide faceSide)
{ {
s_states.stencilMask = mask; #ifdef NAZARA_DEBUG
if (faceSide > nzFaceSide_Max)
{
NazaraError("Face side out of enum");
return;
}
#endif
switch (faceSide)
{
case nzFaceSide_Back:
s_states.backFace.stencilMask = mask;
break;
case nzFaceSide_Front:
s_states.frontFace.stencilMask = mask;
break;
case nzFaceSide_FrontAndBack:
s_states.backFace.stencilMask = mask;
s_states.frontFace.stencilMask = mask;
break;
}
} }
void NzRenderer::SetStencilPassOperation(nzStencilOperation passOperation) void NzRenderer::SetStencilPassOperation(nzStencilOperation passOperation, nzFaceSide faceSide)
{ {
#ifdef NAZARA_DEBUG #ifdef NAZARA_DEBUG
if (passOperation > nzStencilOperation_Max) if (passOperation > nzStencilOperation_Max)
@ -1090,27 +1152,89 @@ void NzRenderer::SetStencilPassOperation(nzStencilOperation passOperation)
NazaraError("Stencil pass operation out of enum"); NazaraError("Stencil pass operation out of enum");
return; return;
} }
#endif
s_states.stencilPass = passOperation; if (faceSide > nzFaceSide_Max)
}
void NzRenderer::SetStencilReferenceValue(unsigned int refValue)
{
s_states.stencilReference = refValue;
}
void NzRenderer::SetStencilZFailOperation(nzStencilOperation zfailOperation)
{
#ifdef NAZARA_DEBUG
if (zfailOperation > nzStencilOperation_Max)
{ {
NazaraError("Stencil zfail operation out of enum"); NazaraError("Face side out of enum");
return; return;
} }
#endif #endif
s_states.stencilZFail = zfailOperation; switch (faceSide)
{
case nzFaceSide_Back:
s_states.backFace.stencilPass = passOperation;
break;
case nzFaceSide_Front:
s_states.frontFace.stencilPass = passOperation;
break;
case nzFaceSide_FrontAndBack:
s_states.backFace.stencilPass = passOperation;
s_states.frontFace.stencilPass = passOperation;
break;
}
}
void NzRenderer::SetStencilReferenceValue(unsigned int refValue, nzFaceSide faceSide)
{
#ifdef NAZARA_DEBUG
if (faceSide > nzFaceSide_Max)
{
NazaraError("Face side out of enum");
return;
}
#endif
switch (faceSide)
{
case nzFaceSide_Back:
s_states.backFace.stencilReference = refValue;
break;
case nzFaceSide_Front:
s_states.frontFace.stencilReference = refValue;
break;
case nzFaceSide_FrontAndBack:
s_states.backFace.stencilReference = refValue;
s_states.frontFace.stencilReference = refValue;
break;
}
}
void NzRenderer::SetStencilZFailOperation(nzStencilOperation zfailOperation, nzFaceSide faceSide)
{
#ifdef NAZARA_DEBUG
if (zfailOperation > nzStencilOperation_Max)
{
NazaraError("Stencil pass operation out of enum");
return;
}
if (faceSide > nzFaceSide_Max)
{
NazaraError("Face side out of enum");
return;
}
#endif
switch (faceSide)
{
case nzFaceSide_Back:
s_states.backFace.stencilZFail = zfailOperation;
break;
case nzFaceSide_Front:
s_states.frontFace.stencilZFail = zfailOperation;
break;
case nzFaceSide_FrontAndBack:
s_states.backFace.stencilZFail = zfailOperation;
s_states.frontFace.stencilZFail = zfailOperation;
break;
}
} }
bool NzRenderer::SetTarget(const NzRenderTarget* target) bool NzRenderer::SetTarget(const NzRenderTarget* target)