From d4abb8fc49f7bd5f2b621800013e4f34a9ef9082 Mon Sep 17 00:00:00 2001 From: Lynix Date: Fri, 6 Sep 2013 18:17:58 +0200 Subject: [PATCH] Made stencil per face side Former-commit-id: 093f2125886d47ebc79f97aaecfad3a5216f399a --- include/Nazara/Renderer/RenderStates.hpp | 18 ++- include/Nazara/Renderer/RenderStates.inl | 20 ++- include/Nazara/Renderer/Renderer.hpp | 12 +- src/Nazara/Renderer/OpenGL.cpp | 67 +++++---- src/Nazara/Renderer/Renderer.cpp | 168 ++++++++++++++++++++--- 5 files changed, 214 insertions(+), 71 deletions(-) diff --git a/include/Nazara/Renderer/RenderStates.hpp b/include/Nazara/Renderer/RenderStates.hpp index 827ca6250..e2b3d0574 100644 --- a/include/Nazara/Renderer/RenderStates.hpp +++ b/include/Nazara/Renderer/RenderStates.hpp @@ -17,20 +17,26 @@ struct NzRenderStates 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 srcBlend; nzFaceFilling faceFilling; nzFaceSide faceCulling; nzRendererComparison depthFunc; - nzRendererComparison stencilCompare; - nzStencilOperation stencilFail; - nzStencilOperation stencilPass; - nzStencilOperation stencilZFail; - nzUInt32 stencilMask; bool parameters[nzRendererParameter_Max+1]; float lineWidth; float pointSize; - unsigned int stencilReference; }; #include diff --git a/include/Nazara/Renderer/RenderStates.inl b/include/Nazara/Renderer/RenderStates.inl index 360982526..d49ad1858 100644 --- a/include/Nazara/Renderer/RenderStates.inl +++ b/include/Nazara/Renderer/RenderStates.inl @@ -11,14 +11,8 @@ srcBlend(nzBlendFunc_One), faceFilling(nzFaceFilling_Fill), faceCulling(nzFaceSide_Back), depthFunc(nzRendererComparison_Less), -stencilCompare(nzRendererComparison_Always), -stencilFail(nzStencilOperation_Keep), -stencilPass(nzStencilOperation_Keep), -stencilZFail(nzStencilOperation_Keep), -stencilMask(0xFFFFFFFF), lineWidth(1.f), -pointSize(1.f), -stencilReference(0) +pointSize(1.f) { parameters[nzRendererParameter_Blend] = false; parameters[nzRendererParameter_ColorWrite] = true; @@ -27,6 +21,18 @@ stencilReference(0) parameters[nzRendererParameter_FaceCulling] = false; parameters[nzRendererParameter_ScissorTest] = 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) diff --git a/include/Nazara/Renderer/Renderer.hpp b/include/Nazara/Renderer/Renderer.hpp index e7b8f34b4..30a9fbc8d 100644 --- a/include/Nazara/Renderer/Renderer.hpp +++ b/include/Nazara/Renderer/Renderer.hpp @@ -88,12 +88,12 @@ class NAZARA_API NzRenderer static void SetRenderStates(const NzRenderStates& states); static void SetScissorRect(const NzRecti& rect); static void SetShaderProgram(const NzShaderProgram* shader); - static void SetStencilCompareFunction(nzRendererComparison compareFunc); - static void SetStencilFailOperation(nzStencilOperation failOperation); - static void SetStencilMask(nzUInt32 mask); - static void SetStencilPassOperation(nzStencilOperation passOperation); - static void SetStencilReferenceValue(unsigned int refValue); - static void SetStencilZFailOperation(nzStencilOperation zfailOperation); + static void SetStencilCompareFunction(nzRendererComparison compareFunc, nzFaceSide faceSide = nzFaceSide_FrontAndBack); + static void SetStencilFailOperation(nzStencilOperation failOperation, nzFaceSide faceSide = nzFaceSide_FrontAndBack); + static void SetStencilMask(nzUInt32 mask, nzFaceSide faceSide = nzFaceSide_FrontAndBack); + static void SetStencilPassOperation(nzStencilOperation passOperation, nzFaceSide faceSide = nzFaceSide_FrontAndBack); + static void SetStencilReferenceValue(unsigned int refValue, nzFaceSide faceSide = nzFaceSide_FrontAndBack); + static void SetStencilZFailOperation(nzStencilOperation zfailOperation, nzFaceSide faceSide = nzFaceSide_FrontAndBack); static bool SetTarget(const NzRenderTarget* target); static void SetTexture(nzUInt8 unit, const NzTexture* texture); static void SetTextureSampler(nzUInt8 textureUnit, const NzTextureSampler& sampler); diff --git a/src/Nazara/Renderer/OpenGL.cpp b/src/Nazara/Renderer/OpenGL.cpp index 5355ecf49..a96c98950 100644 --- a/src/Nazara/Renderer/OpenGL.cpp +++ b/src/Nazara/Renderer/OpenGL.cpp @@ -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é if (states.parameters[nzRendererParameter_StencilTest]) { - if (currentRenderStates.stencilCompare != states.stencilCompare || - currentRenderStates.stencilMask != states.stencilMask || - currentRenderStates.stencilReference != states.stencilReference) + for (unsigned int i = 0; i < 2; ++i) { - glStencilFunc(RendererComparison[states.stencilCompare], states.stencilReference, states.stencilMask); - currentRenderStates.stencilCompare = states.stencilCompare; - currentRenderStates.stencilMask = states.stencilMask; - currentRenderStates.stencilReference = states.stencilReference; - } + GLenum face = (i == 0) ? GL_BACK : GL_FRONT; + const NzRenderStates::Face& srcStates = (i == 0) ? states.backFace : states.frontFace; + NzRenderStates::Face& dstStates = (i == 0) ? currentRenderStates.backFace : currentRenderStates.frontFace; - // Ici encore, ça ne sert à rien de se soucier des fonctions de stencil sans qu'il soit activé - if (currentRenderStates.stencilFail != states.stencilFail || - currentRenderStates.stencilPass != states.stencilPass || - currentRenderStates.stencilZFail != states.stencilZFail) - { - glStencilOp(StencilOperation[states.stencilFail], StencilOperation[states.stencilZFail], StencilOperation[states.stencilPass]); - currentRenderStates.stencilFail = states.stencilFail; - currentRenderStates.stencilPass = states.stencilPass; - currentRenderStates.stencilZFail = states.stencilZFail; + if (dstStates.stencilCompare != srcStates.stencilCompare || + dstStates.stencilMask != srcStates.stencilMask || + dstStates.stencilReference != srcStates.stencilReference) + { + glStencilFuncSeparate(face, RendererComparison[srcStates.stencilCompare], srcStates.stencilReference, srcStates.stencilMask); + dstStates.stencilCompare = srcStates.stencilCompare; + dstStates.stencilMask = srcStates.stencilMask; + dstStates.stencilReference = srcStates.stencilReference; + } + + // 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; } -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) { #ifdef NAZARA_DEBUG @@ -1285,6 +1279,19 @@ void NzOpenGL::SetScissorBox(const NzRecti& 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) { #ifdef NAZARA_DEBUG diff --git a/src/Nazara/Renderer/Renderer.cpp b/src/Nazara/Renderer/Renderer.cpp index c1a06248f..df9b67a2a 100644 --- a/src/Nazara/Renderer/Renderer.cpp +++ b/src/Nazara/Renderer/Renderer.cpp @@ -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 if (compareFunc > nzRendererComparison_Max) @@ -1059,12 +1059,32 @@ void NzRenderer::SetStencilCompareFunction(nzRendererComparison compareFunc) NazaraError("Renderer comparison out of enum"); return; } + + if (faceSide > nzFaceSide_Max) + { + NazaraError("Face side out of enum"); + return; + } #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 if (failOperation > nzStencilOperation_Max) @@ -1072,17 +1092,59 @@ void NzRenderer::SetStencilFailOperation(nzStencilOperation failOperation) NazaraError("Stencil fail operation out of enum"); return; } + + if (faceSide > nzFaceSide_Max) + { + NazaraError("Face side out of enum"); + return; + } #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 if (passOperation > nzStencilOperation_Max) @@ -1090,27 +1152,89 @@ void NzRenderer::SetStencilPassOperation(nzStencilOperation passOperation) NazaraError("Stencil pass operation out of enum"); return; } - #endif - s_states.stencilPass = passOperation; -} - -void NzRenderer::SetStencilReferenceValue(unsigned int refValue) -{ - s_states.stencilReference = refValue; -} - -void NzRenderer::SetStencilZFailOperation(nzStencilOperation zfailOperation) -{ - #ifdef NAZARA_DEBUG - if (zfailOperation > nzStencilOperation_Max) + if (faceSide > nzFaceSide_Max) { - NazaraError("Stencil zfail operation out of enum"); + NazaraError("Face side out of enum"); return; } #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)