Index: binaries/data/mods/mod/shaders/effects/canvas2d.xml =================================================================== --- binaries/data/mods/mod/shaders/effects/canvas2d.xml +++ binaries/data/mods/mod/shaders/effects/canvas2d.xml @@ -4,6 +4,7 @@ + @@ -11,6 +12,7 @@ + Index: binaries/data/mods/public/shaders/effects/bloom.xml =================================================================== --- binaries/data/mods/public/shaders/effects/bloom.xml +++ binaries/data/mods/public/shaders/effects/bloom.xml @@ -1,9 +1,11 @@ - - - - + + + + + + Index: binaries/data/mods/public/shaders/effects/cas.xml =================================================================== --- binaries/data/mods/public/shaders/effects/cas.xml +++ binaries/data/mods/public/shaders/effects/cas.xml @@ -1,7 +1,9 @@ - - - - + + + + + + Index: binaries/data/mods/public/shaders/effects/debug_overlay.xml =================================================================== --- binaries/data/mods/public/shaders/effects/debug_overlay.xml +++ binaries/data/mods/public/shaders/effects/debug_overlay.xml @@ -5,6 +5,7 @@ + @@ -13,6 +14,7 @@ + Index: binaries/data/mods/public/shaders/effects/fxaa.xml =================================================================== --- binaries/data/mods/public/shaders/effects/fxaa.xml +++ binaries/data/mods/public/shaders/effects/fxaa.xml @@ -1,7 +1,9 @@ - - - - + + + + + + Index: binaries/data/mods/public/shaders/effects/model.xml =================================================================== --- binaries/data/mods/public/shaders/effects/model.xml +++ binaries/data/mods/public/shaders/effects/model.xml @@ -20,13 +20,17 @@ - + + + - + + + @@ -47,6 +51,7 @@ + @@ -55,6 +60,7 @@ + Index: binaries/data/mods/public/shaders/effects/model_transparent.xml =================================================================== --- binaries/data/mods/public/shaders/effects/model_transparent.xml +++ binaries/data/mods/public/shaders/effects/model_transparent.xml @@ -8,6 +8,7 @@ + @@ -18,6 +19,7 @@ + @@ -27,13 +29,30 @@ make it obviously buggy if CRenderer is changed to render these models. --> - + + + + + + + + + + + + + + + + + + - + Index: binaries/data/mods/public/shaders/effects/postproc/DOF.xml =================================================================== --- binaries/data/mods/public/shaders/effects/postproc/DOF.xml +++ binaries/data/mods/public/shaders/effects/postproc/DOF.xml @@ -1,10 +1,13 @@ - - + + + - - + + + + Index: binaries/data/mods/public/shaders/effects/postproc/hdr.xml =================================================================== --- binaries/data/mods/public/shaders/effects/postproc/hdr.xml +++ binaries/data/mods/public/shaders/effects/postproc/hdr.xml @@ -1,9 +1,11 @@ - - - - + + + + + + Index: binaries/data/mods/public/shaders/effects/sky_simple.xml =================================================================== --- binaries/data/mods/public/shaders/effects/sky_simple.xml +++ binaries/data/mods/public/shaders/effects/sky_simple.xml @@ -1,14 +1,18 @@ - - - - + + + + + + - - - - + + + + + + Index: binaries/data/mods/public/shaders/effects/terrain_blend.xml =================================================================== --- binaries/data/mods/public/shaders/effects/terrain_blend.xml +++ binaries/data/mods/public/shaders/effects/terrain_blend.xml @@ -5,6 +5,7 @@ + @@ -13,18 +14,23 @@ + - + + + - + + + Index: binaries/data/mods/public/shaders/effects/terrain_decal.xml =================================================================== --- binaries/data/mods/public/shaders/effects/terrain_decal.xml +++ binaries/data/mods/public/shaders/effects/terrain_decal.xml @@ -5,6 +5,7 @@ + @@ -13,18 +14,23 @@ + - + + + - + + + Index: binaries/data/mods/public/shaders/effects/terrain_solid.xml =================================================================== --- binaries/data/mods/public/shaders/effects/terrain_solid.xml +++ binaries/data/mods/public/shaders/effects/terrain_solid.xml @@ -7,6 +7,7 @@ + @@ -19,6 +20,7 @@ terrain (so silhouettes will still display when behind hills). --> + Index: binaries/data/mods/public/shaders/effects/water_waves.xml =================================================================== --- binaries/data/mods/public/shaders/effects/water_waves.xml +++ binaries/data/mods/public/shaders/effects/water_waves.xml @@ -3,6 +3,7 @@ + Index: source/graphics/MiniMapTexture.cpp =================================================================== --- source/graphics/MiniMapTexture.cpp +++ source/graphics/MiniMapTexture.cpp @@ -387,8 +387,11 @@ Renderer::Backend::BlendFactor::ONE_MINUS_SRC_ALPHA; pipelineStateDesc.blendState.colorBlendOp = pipelineStateDesc.blendState.alphaBlendOp = Renderer::Backend::BlendOp::ADD; + pipelineStateDesc.blendState.colorWriteMask = + Renderer::Backend::ColorWriteMask::RED | + Renderer::Backend::ColorWriteMask::GREEN | + Renderer::Backend::ColorWriteMask::BLUE; deviceCommandContext->SetGraphicsPipelineState(pipelineStateDesc); - glColorMask(1, 1, 1, 0); // Draw territory boundaries CTerritoryTexture& territoryTexture = g_Game->GetView()->GetTerritoryTexture(); @@ -400,8 +403,9 @@ DrawTexture(shader); pipelineStateDesc.blendState.enabled = false; + pipelineStateDesc.blendState.colorWriteMask = + Renderer::Backend::ColorWriteMask::ALPHA; deviceCommandContext->SetGraphicsPipelineState(pipelineStateDesc); - glColorMask(0, 0, 0, 1); shader->BindTexture(str_baseTex, losTexture.GetTexture()); shader->Uniform(str_transform, baseTransform); @@ -410,8 +414,6 @@ DrawTexture(shader); tech->EndPass(); - - glColorMask(1, 1, 1, 1); CShaderDefines pointDefines; pointDefines.Add(str_MINIMAP_POINT, str_1); Index: source/graphics/ShaderManager.cpp =================================================================== --- source/graphics/ShaderManager.cpp +++ source/graphics/ShaderManager.cpp @@ -272,28 +272,6 @@ return true; } -static GLenum ParseComparisonFunc(const CStr& str) -{ - if (str == "never") - return GL_NEVER; - if (str == "always") - return GL_ALWAYS; - if (str == "less") - return GL_LESS; - if (str == "lequal") - return GL_LEQUAL; - if (str == "equal") - return GL_EQUAL; - if (str == "gequal") - return GL_GEQUAL; - if (str == "greater") - return GL_GREATER; - if (str == "notequal") - return GL_NOTEQUAL; - debug_warn("Invalid comparison func"); - return GL_ALWAYS; -} - size_t CShaderManager::EffectCacheKeyHash::operator()(const EffectCacheKey& key) const { size_t hash = 0; @@ -348,6 +326,7 @@ #define EL(x) int el_##x = XeroFile.GetElementID(#x) #define AT(x) int at_##x = XeroFile.GetAttributeID(#x) EL(blend); + EL(color); EL(cull); EL(define); EL(depth); @@ -359,13 +338,17 @@ AT(dst); AT(front_face); AT(func); + AT(mask); + AT(mask_red); + AT(mask_green); + AT(mask_blue); + AT(mask_alpha); AT(mode); + AT(name); AT(op); AT(shader); AT(shaders); AT(src); - AT(mask); - AT(name); AT(value); #undef AT #undef EL @@ -483,6 +466,19 @@ } } } + else if (Element.GetNodeName() == el_color) + { + passPipelineStateDesc.blendState.colorWriteMask = 0; + #define MASK_CHANNEL(ATTRIBUTE, VALUE) \ + if (Element.GetAttributes().GetNamedItem(ATTRIBUTE) == "TRUE") \ + passPipelineStateDesc.blendState.colorWriteMask |= Renderer::Backend::ColorWriteMask::VALUE + + MASK_CHANNEL(at_mask_red, RED); + MASK_CHANNEL(at_mask_green, GREEN); + MASK_CHANNEL(at_mask_blue, BLUE); + MASK_CHANNEL(at_mask_alpha, ALPHA); + #undef MASK_CHANNEL + } else if (Element.GetNodeName() == el_cull) { if (!Element.GetAttributes().GetNamedItem(at_mode).empty()) @@ -499,10 +495,16 @@ else if (Element.GetNodeName() == el_depth) { if (!Element.GetAttributes().GetNamedItem(at_func).empty()) - pass.DepthFunc(ParseComparisonFunc(Element.GetAttributes().GetNamedItem(at_func))); + { + passPipelineStateDesc.depthStencilState.depthCompareOp = + Renderer::Backend::ParseCompareOp(Element.GetAttributes().GetNamedItem(at_func)); + } if (!Element.GetAttributes().GetNamedItem(at_mask).empty()) - pass.DepthMask(Element.GetAttributes().GetNamedItem(at_mask) == "true" ? 1 : 0); + { + passPipelineStateDesc.depthStencilState.depthWriteEnabled = + Element.GetAttributes().GetNamedItem(at_mask) == "true"; + } } } Index: source/graphics/ShaderTechnique.h =================================================================== --- source/graphics/ShaderTechnique.h +++ source/graphics/ShaderTechnique.h @@ -39,10 +39,6 @@ */ void SetShader(const CShaderProgramPtr& shader) { m_Shader = shader; } - // Add various bits of GL state to the pass: - void ColorMask(GLboolean r, GLboolean g, GLboolean b, GLboolean a); - void DepthMask(GLboolean mask); - void DepthFunc(GLenum func); void SetPipelineStateDesc( const Renderer::Backend::GraphicsPipelineStateDesc& pipelineStateDesc); @@ -65,18 +61,6 @@ CShaderProgramPtr m_Shader; Renderer::Backend::GraphicsPipelineStateDesc m_PipelineStateDesc{}; - - bool m_HasColorMask = false; - GLboolean m_ColorMaskR; - GLboolean m_ColorMaskG; - GLboolean m_ColorMaskB; - GLboolean m_ColorMaskA; - - bool m_HasDepthMask = false; - GLboolean m_DepthMask; - - bool m_HasDepthFunc = false; - GLenum m_DepthFunc; }; /** Index: source/graphics/ShaderTechnique.cpp =================================================================== --- source/graphics/ShaderTechnique.cpp +++ source/graphics/ShaderTechnique.cpp @@ -26,50 +26,11 @@ void CShaderPass::Bind() { m_Shader->Bind(); - - if (m_HasColorMask) - glColorMask(m_ColorMaskR, m_ColorMaskG, m_ColorMaskB, m_ColorMaskA); - - if (m_HasDepthMask) - glDepthMask(m_DepthMask); - - if (m_HasDepthFunc) - glDepthFunc(m_DepthFunc); } void CShaderPass::Unbind() { m_Shader->Unbind(); - - if (m_HasColorMask) - glColorMask(1, 1, 1, 1); - - if (m_HasDepthMask) - glDepthMask(1); - - if (m_HasDepthFunc) - glDepthFunc(GL_LEQUAL); -} - -void CShaderPass::ColorMask(GLboolean r, GLboolean g, GLboolean b, GLboolean a) -{ - m_HasColorMask = true; - m_ColorMaskR = r; - m_ColorMaskG = g; - m_ColorMaskB = b; - m_ColorMaskA = a; -} - -void CShaderPass::DepthMask(GLboolean mask) -{ - m_HasDepthMask = true; - m_DepthMask = mask; -} - -void CShaderPass::DepthFunc(GLenum func) -{ - m_HasDepthFunc = true; - m_DepthFunc = func; } void CShaderPass::SetPipelineStateDesc( Index: source/renderer/OverlayRenderer.cpp =================================================================== --- source/renderer/OverlayRenderer.cpp +++ source/renderer/OverlayRenderer.cpp @@ -378,10 +378,6 @@ #if CONFIG2_GLES #warning TODO: implement OverlayRenderer::RenderOverlaysBeforeWater for GLES #else - // Ignore z so that we draw behind terrain (but don't disable GL_DEPTH_TEST - // since we still want to write to the z buffer) - glDepthFunc(GL_ALWAYS); - for (SOverlayLine* line : m->lines) { if (line->m_Coords.empty()) @@ -389,8 +385,6 @@ g_Renderer.GetDebugRenderer().DrawLine(line->m_Coords, line->m_Color, static_cast(line->m_Thickness)); } - - glDepthFunc(GL_LEQUAL); #endif } @@ -416,7 +410,6 @@ ogl_WarnIfError(); glActiveTextureARB(GL_TEXTURE0); - glDepthMask(0); CLOSTexture& los = g_Renderer.GetSceneRenderer().GetScene().GetLOSTexture(); @@ -427,6 +420,7 @@ { Renderer::Backend::GraphicsPipelineStateDesc pipelineStateDesc = shaderTechTexLineNormal->GetGraphicsPipelineStateDesc(); + pipelineStateDesc.depthStencilState.depthWriteEnabled = false; pipelineStateDesc.blendState.enabled = true; pipelineStateDesc.blendState.srcColorBlendFactor = pipelineStateDesc.blendState.srcAlphaBlendFactor = Renderer::Backend::BlendFactor::SRC_ALPHA; @@ -457,6 +451,7 @@ { Renderer::Backend::GraphicsPipelineStateDesc pipelineStateDesc = shaderTechTexLineAlwaysVisible->GetGraphicsPipelineStateDesc(); + pipelineStateDesc.depthStencilState.depthWriteEnabled = false; pipelineStateDesc.blendState.enabled = true; pipelineStateDesc.blendState.srcColorBlendFactor = pipelineStateDesc.blendState.srcAlphaBlendFactor = Renderer::Backend::BlendFactor::SRC_ALPHA; @@ -488,8 +483,6 @@ g_Renderer.BindTexture(0, 0); CVertexBuffer::Unbind(); - - glDepthMask(1); } void OverlayRenderer::RenderTexturedOverlayLines(const CShaderProgramPtr& shader, bool alwaysVisible) @@ -532,6 +525,7 @@ Renderer::Backend::GraphicsPipelineStateDesc pipelineStateDesc = shaderTech->GetGraphicsPipelineStateDesc(); + pipelineStateDesc.depthStencilState.depthWriteEnabled = false; pipelineStateDesc.blendState.enabled = true; pipelineStateDesc.blendState.srcColorBlendFactor = pipelineStateDesc.blendState.srcAlphaBlendFactor = Renderer::Backend::BlendFactor::SRC_ALPHA; @@ -550,7 +544,6 @@ #endif glActiveTextureARB(GL_TEXTURE0); - glDepthMask(0); CLOSTexture& los = g_Renderer.GetSceneRenderer().GetScene().GetLOSTexture(); @@ -608,8 +601,6 @@ CVertexBuffer::Unbind(); - glDepthMask(1); - #if !CONFIG2_GLES if (g_Renderer.GetSceneRenderer().GetOverlayRenderMode() == WIREFRAME) glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); @@ -762,14 +753,13 @@ if (m->spheres.empty()) return; - glDepthMask(0); - CShaderProgramPtr shader; CShaderTechniquePtr tech; tech = g_Renderer.GetShaderManager().LoadEffect(str_overlay_solid); Renderer::Backend::GraphicsPipelineStateDesc pipelineStateDesc = tech->GetGraphicsPipelineStateDesc(); + pipelineStateDesc.depthStencilState.depthWriteEnabled = false; pipelineStateDesc.blendState.enabled = true; pipelineStateDesc.blendState.srcColorBlendFactor = pipelineStateDesc.blendState.srcAlphaBlendFactor = Renderer::Backend::BlendFactor::SRC_ALPHA; @@ -807,7 +797,5 @@ } tech->EndPass(); - - glDepthMask(1); #endif } Index: source/renderer/PostprocManager.h =================================================================== --- source/renderer/PostprocManager.h +++ source/renderer/PostprocManager.h @@ -75,7 +75,7 @@ // Blits the final postprocessed texture to the system framebuffer. The system framebuffer // is selected as the output buffer. Should be called before silhouette rendering. // @note CPostprocManager must be initialized first - void ReleaseRenderOutput(); + void ReleaseRenderOutput(Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext); // Returns true if we render main scene in the MSAA framebuffer. bool IsMultisampleEnabled() const; Index: source/renderer/PostprocManager.cpp =================================================================== --- source/renderer/PostprocManager.cpp +++ source/renderer/PostprocManager.cpp @@ -392,10 +392,14 @@ } -void CPostprocManager::ReleaseRenderOutput() +void CPostprocManager::ReleaseRenderOutput( + Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext) { ENSURE(m_IsInitialized); + const Renderer::Backend::GraphicsPipelineStateDesc pipelineStateDesc = + Renderer::Backend::MakeDefaultGraphicsPipelineStateDesc(); + deviceCommandContext->SetGraphicsPipelineState(pipelineStateDesc); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); @@ -424,7 +428,6 @@ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_PongFbo); glDisable(GL_DEPTH_TEST); - glDepthMask(GL_FALSE); shaderTech1->BeginPass(pass); deviceCommandContext->SetGraphicsPipelineState( @@ -484,7 +487,6 @@ shaderTech1->EndPass(pass); - glDepthMask(GL_TRUE); glEnable(GL_DEPTH_TEST); m_WhichBuffer = !m_WhichBuffer; @@ -834,7 +836,8 @@ { } -void CPostprocManager::ReleaseRenderOutput() +void CPostprocManager::ReleaseRenderOutput( + Renderer::Backend::GL::CDeviceCommandContext* UNUSED(deviceCommandContext)) { } Index: source/renderer/SceneRenderer.cpp =================================================================== --- source/renderer/SceneRenderer.cpp +++ source/renderer/SceneRenderer.cpp @@ -638,6 +638,9 @@ // try binding the framebuffer glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, wm.m_ReflectionFbo); + const Renderer::Backend::GraphicsPipelineStateDesc pipelineStateDesc = + Renderer::Backend::MakeDefaultGraphicsPipelineStateDesc(); + deviceCommandContext->SetGraphicsPipelineState(pipelineStateDesc); glClearColor(0.5f, 0.5f, 1.0f, 0.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); @@ -718,6 +721,9 @@ // try binding the framebuffer glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, wm.m_RefractionFbo); + const Renderer::Backend::GraphicsPipelineStateDesc pipelineStateDesc = + Renderer::Backend::MakeDefaultGraphicsPipelineStateDesc(); + deviceCommandContext->SetGraphicsPipelineState(pipelineStateDesc); glClearColor(1.0f, 0.0f, 0.0f, 0.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); @@ -760,8 +766,6 @@ glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); - glColorMask(0, 0, 0, 0); - // Render occluders: { @@ -779,9 +783,6 @@ m->CallTranspModelRenderers(deviceCommandContext, contextOccluder, CULL_SILHOUETTE_OCCLUDER, 0); } - glDepthFunc(GL_GEQUAL); - glColorMask(1, 1, 1, 1); - // Since we can't sort, we'll use the stencil buffer to ensure we only draw // a pixel once (using the color of whatever model happens to be drawn first). glEnable(GL_STENCIL_TEST); @@ -799,7 +800,6 @@ } // Restore state - glDepthFunc(GL_LEQUAL); glDisable(GL_STENCIL_TEST); } @@ -980,7 +980,7 @@ g_Renderer.GetPostprocManager().ResolveMultisampleFramebuffer(); postprocManager.ApplyPostproc(deviceCommandContext); - postprocManager.ReleaseRenderOutput(); + postprocManager.ReleaseRenderOutput(deviceCommandContext); } if (g_RenderingOptions.GetSilhouettes()) @@ -1031,15 +1031,11 @@ #if CONFIG2_GLES #warning TODO: implement CSceneRenderer::DisplayFrustum for GLES #else - glDepthMask(0); - g_Renderer.GetDebugRenderer().DrawCameraFrustum(m_CullCamera, CColor(1.0f, 1.0f, 1.0f, 0.25f), 2); glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); g_Renderer.GetDebugRenderer().DrawCameraFrustum(m_CullCamera, CColor(1.0f, 1.0f, 1.0f, 1.0f), 2); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); - - glDepthMask(1); #endif ogl_WarnIfError(); Index: source/renderer/ShadowMap.cpp =================================================================== --- source/renderer/ShadowMap.cpp +++ source/renderer/ShadowMap.cpp @@ -626,10 +626,7 @@ // color buffer too, else Mali 400 drivers get confused. // Might as well clear stencil too for completeness. if (g_RenderingOptions.GetShadowAlphaFix()) - { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); - glColorMask(0, 0, 0, 0); - } else glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); } @@ -671,9 +668,6 @@ const SViewPort vp = { 0, 0, g_Renderer.GetWidth(), g_Renderer.GetHeight() }; g_Renderer.SetViewport(vp); - - if (g_RenderingOptions.GetShadowAlphaFix()) - glColorMask(1, 1, 1, 1); } void ShadowMap::BindTo(const CShaderProgramPtr& shader) const @@ -726,8 +720,6 @@ void ShadowMap::RenderDebugBounds() { - glDepthMask(0); - // Render various shadow bounds: // Yellow = bounds of objects in view frustum that receive shadows // Red = culling frustum used to find potential shadow casters @@ -754,8 +746,6 @@ g_Renderer.GetDebugRenderer().DrawBrushOutline(frustumBrush, CColor(1.0f, 0.0f, 0.0f, 0.5f)); } - glDepthMask(1); - ogl_WarnIfError(); } @@ -765,8 +755,6 @@ if (!m->Texture) return; - glDepthMask(0); - glDisable(GL_DEPTH_TEST); #if !CONFIG2_GLES @@ -812,7 +800,6 @@ #endif glEnable(GL_DEPTH_TEST); - glDepthMask(1); ogl_WarnIfError(); } Index: source/renderer/SilhouetteRenderer.cpp =================================================================== --- source/renderer/SilhouetteRenderer.cpp +++ source/renderer/SilhouetteRenderer.cpp @@ -450,8 +450,6 @@ if (m_DebugBounds.empty() && m_DebugRects.empty()) return; - glDepthMask(0); - for (size_t i = 0; i < m_DebugBounds.size(); ++i) g_Renderer.GetDebugRenderer().DrawBoundingBoxOutline(m_DebugBounds[i].bounds, m_DebugBounds[i].color); @@ -492,8 +490,6 @@ } shaderTech->EndPass(); - - glDepthMask(1); } void SilhouetteRenderer::EndFrame() Index: source/renderer/SkyManager.cpp =================================================================== --- source/renderer/SkyManager.cpp +++ source/renderer/SkyManager.cpp @@ -207,8 +207,6 @@ if (m_SkySet.empty() || !m_SkyCubeMap) return; - glDepthMask(GL_FALSE); - const CCamera& camera = g_Renderer.GetSceneRenderer().GetViewCamera(); CShaderTechniquePtr skytech = @@ -294,8 +292,6 @@ glDrawArrays(GL_QUADS, 0, 6 * 4); skytech->EndPass(); - - glDepthMask(GL_TRUE); #endif } Index: source/renderer/TerrainOverlay.cpp =================================================================== --- source/renderer/TerrainOverlay.cpp +++ source/renderer/TerrainOverlay.cpp @@ -121,7 +121,6 @@ UNUSED2(deviceCommandContext); #warning TODO: implement TerrainOverlay::RenderOverlays for GLES #else - glDepthMask(GL_FALSE); // To ensure that outlines are drawn on top of the terrain correctly (and // don't Z-fight and flicker nastily), draw them as QUADS with the LINE // PolygonMode, and use PolygonOffset to pull them towards the camera. @@ -155,7 +154,6 @@ //glDisable(GL_POLYGON_OFFSET_LINE); glDisable(GL_POLYGON_OFFSET_FILL); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); - glDepthMask(GL_TRUE); #endif } Index: source/renderer/TerrainRenderer.cpp =================================================================== --- source/renderer/TerrainRenderer.cpp +++ source/renderer/TerrainRenderer.cpp @@ -174,7 +174,6 @@ std::vector& visiblePatches = m->visiblePatches[cullGroup]; - glDepthMask(0); glDisable(GL_DEPTH_TEST); CShaderTechniquePtr debugOverlayTech = @@ -216,8 +215,6 @@ } debugOverlayTech->EndPass(); - - glDepthMask(1); #endif } @@ -280,9 +277,6 @@ CPatchRData::RenderBases(deviceCommandContext, visiblePatches, context, shadow); - // no need to write to the depth buffer a second time - glDepthMask(0); - // render blend passes for each patch CPatchRData::RenderBlends(deviceCommandContext, visiblePatches, context, shadow); @@ -292,8 +286,6 @@ g_Renderer.BindTexture(1, 0); g_Renderer.BindTexture(2, 0); g_Renderer.BindTexture(3, 0); - - glDepthMask(1); } @@ -416,7 +408,6 @@ const float repeatPeriod = waterManager.m_RepeatPeriod; glEnable(GL_DEPTH_TEST); - glDepthFunc(GL_LEQUAL); #if !CONFIG2_GLES if (g_Renderer.GetSceneRenderer().GetWaterRenderMode() == WIREFRAME) @@ -518,8 +509,6 @@ glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); #endif - glDepthFunc(GL_LEQUAL); - return true; } @@ -538,7 +527,6 @@ CLOSTexture& losTexture = g_Game->GetView()->GetLOSTexture(); glEnable(GL_DEPTH_TEST); - glDepthFunc(GL_LEQUAL); if (g_Renderer.GetSceneRenderer().GetWaterRenderMode() == WIREFRAME) glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); @@ -604,7 +592,6 @@ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, waterManager.m_FancyEffectsFBO); glEnable(GL_DEPTH_TEST); - glDepthFunc(GL_LEQUAL); // Overwrite waves that would be behind the ground. CShaderTechniquePtr dummyTech = g_Renderer.GetShaderManager().LoadEffect(str_solid); Index: source/renderer/WaterManager.cpp =================================================================== --- source/renderer/WaterManager.cpp +++ source/renderer/WaterManager.cpp @@ -817,7 +817,6 @@ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glEnable(GL_DEPTH_TEST); - glDepthFunc(GL_ALWAYS); CShaderTechniquePtr tech = g_Renderer.GetShaderManager().LoadEffect(str_water_waves); tech->BeginPass(); @@ -868,8 +867,6 @@ } tech->EndPass(); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); - - glDepthFunc(GL_LEQUAL); #endif } Index: source/renderer/backend/PipelineState.h =================================================================== --- source/renderer/backend/PipelineState.h +++ source/renderer/backend/PipelineState.h @@ -28,6 +28,32 @@ namespace Backend { +enum class CompareOp +{ + // Never passes the comparison. + NEVER, + // Passes if the source value is less than the destination value. + LESS, + // Passes if the source depth value is equal to the destination value. + EQUAL, + // Passes if the source depth value is less than or equal to the destination value. + LESS_OR_EQUAL, + // Passes if the source depth value is greater than the destination value. + GREATER, + // Passes if the source depth value is not equal to the destination value. + NOT_EQUAL, + // Passes if the source depth value is greater than or equal to the destination value. + GREATER_OR_EQUAL, + // Always passes the comparison. + ALWAYS +}; + +struct DepthStencilStateDesc +{ + CompareOp depthCompareOp; + bool depthWriteEnabled; +}; + // TODO: add per constant description. enum class BlendFactor @@ -62,6 +88,16 @@ MAX }; +// Using a namespace instead of a enum allows using the same syntax while +// avoiding adding operator overrides and additional checks on casts. +namespace ColorWriteMask +{ +constexpr uint8_t RED = 0x01; +constexpr uint8_t GREEN = 0x02; +constexpr uint8_t BLUE = 0x04; +constexpr uint8_t ALPHA = 0x08; +} // namespace ColorWriteMask + struct BlendStateDesc { bool enabled; @@ -72,6 +108,7 @@ BlendFactor dstAlphaBlendFactor; BlendOp alphaBlendOp; CColor constant; + uint8_t colorWriteMask; }; enum class CullMode @@ -96,6 +133,7 @@ // TODO: Add a shader program to the graphics pipeline state. struct GraphicsPipelineStateDesc { + DepthStencilStateDesc depthStencilState; BlendStateDesc blendState; RasterizationStateDesc rasterizationState; }; @@ -103,6 +141,8 @@ // We don't provide additional helpers intentionally because all custom states // should be described with a related shader and should be switched together. GraphicsPipelineStateDesc MakeDefaultGraphicsPipelineStateDesc(); + +CompareOp ParseCompareOp(const CStr& str); BlendFactor ParseBlendFactor(const CStr& str); BlendOp ParseBlendOp(const CStr& str); Index: source/renderer/backend/PipelineState.cpp =================================================================== --- source/renderer/backend/PipelineState.cpp +++ source/renderer/backend/PipelineState.cpp @@ -29,6 +29,9 @@ { GraphicsPipelineStateDesc desc{}; + desc.depthStencilState.depthCompareOp = CompareOp::LESS_OR_EQUAL; + desc.depthStencilState.depthWriteEnabled = true; + desc.blendState.enabled = false; desc.blendState.srcColorBlendFactor = desc.blendState.srcAlphaBlendFactor = BlendFactor::ONE; @@ -36,10 +39,29 @@ BlendFactor::ZERO; desc.blendState.colorBlendOp = desc.blendState.alphaBlendOp = BlendOp::ADD; desc.blendState.constant = CColor(0.0f, 0.0f, 0.0f, 0.0f); + desc.blendState.colorWriteMask = + ColorWriteMask::RED | ColorWriteMask::GREEN | ColorWriteMask::BLUE | ColorWriteMask::ALPHA; desc.rasterizationState.cullMode = CullMode::BACK; desc.rasterizationState.frontFace = FrontFace::COUNTER_CLOCKWISE; return desc; +} + +CompareOp ParseCompareOp(const CStr& str) +{ + // TODO: it might make sense to use upper case in XML for consistency. +#define CASE(NAME, VALUE) if (str == NAME) return CompareOp::VALUE + CASE("never", NEVER); + CASE("less", LESS); + CASE("equal", EQUAL); + CASE("lequal", LESS_OR_EQUAL); + CASE("greater", GREATER); + CASE("notequal", NOT_EQUAL); + CASE("gequal", GREATER_OR_EQUAL); + CASE("always", ALWAYS); +#undef CASE + debug_warn("Invalid compare op"); + return CompareOp::NEVER; } BlendFactor ParseBlendFactor(const CStr& str) Index: source/renderer/backend/gl/Device.cpp =================================================================== --- source/renderer/backend/gl/Device.cpp +++ source/renderer/backend/gl/Device.cpp @@ -197,7 +197,6 @@ glPixelStorei(GL_UNPACK_ALIGNMENT, 1); // Setup default state. - glDepthFunc(GL_LEQUAL); glEnable(GL_DEPTH_TEST); return device; Index: source/renderer/backend/gl/DeviceCommandContext.cpp =================================================================== --- source/renderer/backend/gl/DeviceCommandContext.cpp +++ source/renderer/backend/gl/DeviceCommandContext.cpp @@ -136,6 +136,17 @@ void CDeviceCommandContext::SetGraphicsPipelineStateImpl( const GraphicsPipelineStateDesc& pipelineStateDesc, const bool force) { + const DepthStencilStateDesc& currentDepthStencilStateDesc = m_GraphicsPipelineStateDesc.depthStencilState; + const DepthStencilStateDesc& nextDepthStencilStateDesc = pipelineStateDesc.depthStencilState; + if (force || currentDepthStencilStateDesc.depthCompareOp != nextDepthStencilStateDesc.depthCompareOp) + { + glDepthFunc(Mapping::DepthFuncFromCompareOp(nextDepthStencilStateDesc.depthCompareOp)); + } + if (force || currentDepthStencilStateDesc.depthWriteEnabled != nextDepthStencilStateDesc.depthWriteEnabled) + { + glDepthMask(nextDepthStencilStateDesc.depthWriteEnabled ? GL_TRUE : GL_FALSE); + } + const BlendStateDesc& currentBlendStateDesc = m_GraphicsPipelineStateDesc.blendState; const BlendStateDesc& nextBlendStateDesc = pipelineStateDesc.blendState; if (force || currentBlendStateDesc.enabled != nextBlendStateDesc.enabled) @@ -192,6 +203,16 @@ nextBlendStateDesc.constant.g, nextBlendStateDesc.constant.b, nextBlendStateDesc.constant.a); + } + + if (force || + currentBlendStateDesc.colorWriteMask != nextBlendStateDesc.colorWriteMask) + { + glColorMask( + (nextBlendStateDesc.colorWriteMask & ColorWriteMask::RED) != 0 ? GL_TRUE : GL_FALSE, + (nextBlendStateDesc.colorWriteMask & ColorWriteMask::GREEN) != 0 ? GL_TRUE : GL_FALSE, + (nextBlendStateDesc.colorWriteMask & ColorWriteMask::BLUE) != 0 ? GL_TRUE : GL_FALSE, + (nextBlendStateDesc.colorWriteMask & ColorWriteMask::ALPHA) != 0 ? GL_TRUE : GL_FALSE); } const RasterizationStateDesc& currentRasterizationStateDesc = m_GraphicsPipelineStateDesc.rasterizationState; Index: source/renderer/backend/gl/Mapping.h =================================================================== --- source/renderer/backend/gl/Mapping.h +++ source/renderer/backend/gl/Mapping.h @@ -33,9 +33,11 @@ namespace Mapping { -GLenum FromBlendFactor(BlendFactor blendFactor); +GLenum DepthFuncFromCompareOp(const CompareOp compareOp); -GLenum FromBlendOp(BlendOp blendOp); +GLenum FromBlendFactor(const BlendFactor blendFactor); + +GLenum FromBlendOp(const BlendOp blendOp); } // namespace Mapping Index: source/renderer/backend/gl/Mapping.cpp =================================================================== --- source/renderer/backend/gl/Mapping.cpp +++ source/renderer/backend/gl/Mapping.cpp @@ -34,7 +34,26 @@ namespace Mapping { -GLenum FromBlendFactor(BlendFactor blendFactor) +GLenum DepthFuncFromCompareOp(const CompareOp compareOp) +{ + GLenum detphFunc = GL_NEVER; + switch (compareOp) + { +#define CASE(NAME, GL_NAME) case CompareOp::NAME: detphFunc = GL_NAME; break + CASE(NEVER, GL_NEVER); + CASE(LESS, GL_LESS); + CASE(EQUAL, GL_EQUAL); + CASE(LESS_OR_EQUAL, GL_LEQUAL); + CASE(GREATER, GL_GREATER); + CASE(NOT_EQUAL, GL_NOTEQUAL); + CASE(GREATER_OR_EQUAL, GL_GEQUAL); + CASE(ALWAYS, GL_ALWAYS); +#undef CASE + } + return detphFunc; +} + +GLenum FromBlendFactor(const BlendFactor blendFactor) { GLenum factor = GL_ZERO; switch (blendFactor) @@ -67,7 +86,7 @@ return factor; } -GLenum FromBlendOp(BlendOp blendOp) +GLenum FromBlendOp(const BlendOp blendOp) { GLenum mode = GL_FUNC_ADD; switch (blendOp)