Index: ps/trunk/binaries/data/mods/mod/shaders/effects/canvas2d.xml =================================================================== --- ps/trunk/binaries/data/mods/mod/shaders/effects/canvas2d.xml +++ ps/trunk/binaries/data/mods/mod/shaders/effects/canvas2d.xml @@ -4,7 +4,7 @@ - + @@ -12,7 +12,7 @@ - + Index: ps/trunk/binaries/data/mods/public/shaders/effects/bloom.xml =================================================================== --- ps/trunk/binaries/data/mods/public/shaders/effects/bloom.xml +++ ps/trunk/binaries/data/mods/public/shaders/effects/bloom.xml @@ -4,7 +4,7 @@ - + Index: ps/trunk/binaries/data/mods/public/shaders/effects/cas.xml =================================================================== --- ps/trunk/binaries/data/mods/public/shaders/effects/cas.xml +++ ps/trunk/binaries/data/mods/public/shaders/effects/cas.xml @@ -3,7 +3,7 @@ - + Index: ps/trunk/binaries/data/mods/public/shaders/effects/debug_overlay.xml =================================================================== --- ps/trunk/binaries/data/mods/public/shaders/effects/debug_overlay.xml +++ ps/trunk/binaries/data/mods/public/shaders/effects/debug_overlay.xml @@ -5,7 +5,7 @@ - + @@ -14,7 +14,7 @@ - + Index: ps/trunk/binaries/data/mods/public/shaders/effects/fxaa.xml =================================================================== --- ps/trunk/binaries/data/mods/public/shaders/effects/fxaa.xml +++ ps/trunk/binaries/data/mods/public/shaders/effects/fxaa.xml @@ -3,7 +3,7 @@ - + Index: ps/trunk/binaries/data/mods/public/shaders/effects/model.xml =================================================================== --- ps/trunk/binaries/data/mods/public/shaders/effects/model.xml +++ ps/trunk/binaries/data/mods/public/shaders/effects/model.xml @@ -52,6 +52,7 @@ + @@ -61,6 +62,7 @@ + Index: ps/trunk/binaries/data/mods/public/shaders/effects/model_transparent.xml =================================================================== --- ps/trunk/binaries/data/mods/public/shaders/effects/model_transparent.xml +++ ps/trunk/binaries/data/mods/public/shaders/effects/model_transparent.xml @@ -33,6 +33,7 @@ + @@ -41,6 +42,7 @@ + Index: ps/trunk/binaries/data/mods/public/shaders/effects/postproc/DOF.xml =================================================================== --- ps/trunk/binaries/data/mods/public/shaders/effects/postproc/DOF.xml +++ ps/trunk/binaries/data/mods/public/shaders/effects/postproc/DOF.xml @@ -4,10 +4,10 @@ - + - + Index: ps/trunk/binaries/data/mods/public/shaders/effects/postproc/hdr.xml =================================================================== --- ps/trunk/binaries/data/mods/public/shaders/effects/postproc/hdr.xml +++ ps/trunk/binaries/data/mods/public/shaders/effects/postproc/hdr.xml @@ -4,7 +4,7 @@ - + Index: ps/trunk/binaries/data/mods/public/shaders/effects/water_high.xml =================================================================== --- ps/trunk/binaries/data/mods/public/shaders/effects/water_high.xml +++ ps/trunk/binaries/data/mods/public/shaders/effects/water_high.xml @@ -3,6 +3,7 @@ + Index: ps/trunk/binaries/data/mods/public/shaders/effects/water_simple.xml =================================================================== --- ps/trunk/binaries/data/mods/public/shaders/effects/water_simple.xml +++ ps/trunk/binaries/data/mods/public/shaders/effects/water_simple.xml @@ -1,14 +1,18 @@ - - - - + + + + + + - - - - + + + + + + Index: ps/trunk/binaries/data/mods/public/shaders/effects/water_waves.xml =================================================================== --- ps/trunk/binaries/data/mods/public/shaders/effects/water_waves.xml +++ ps/trunk/binaries/data/mods/public/shaders/effects/water_waves.xml @@ -3,7 +3,7 @@ - + Index: ps/trunk/source/graphics/CinemaManager.cpp =================================================================== --- ps/trunk/source/graphics/CinemaManager.cpp +++ ps/trunk/source/graphics/CinemaManager.cpp @@ -22,7 +22,6 @@ #include "graphics/Camera.h" #include "graphics/Color.h" #include "graphics/GameView.h" -#include "lib/ogl.h" #include "maths/MathUtil.h" #include "maths/Quaternion.h" #include "maths/Vector3D.h" @@ -73,8 +72,6 @@ if (!cmpCinemaManager) return; - glDisable(GL_DEPTH_TEST); - for (const std::pair& p : cmpCinemaManager->GetPaths()) { DrawSpline(p.second, CColor(0.2f, 0.2f, 1.f, 0.9f), 128); @@ -86,8 +83,6 @@ DrawSpline(p.second.GetTargetSpline(), CColor(1.f, 0.3f, 0.4f, 0.9f), 128); DrawNodes(p.second.GetTargetSpline(), CColor(1.f, 0.1f, 0.f, 1.f)); } - - glEnable(GL_DEPTH_TEST); } void CCinemaManager::DrawSpline(const RNSpline& spline, const CColor& splineColor, int smoothness) const @@ -105,7 +100,7 @@ const float time = start * i / spline.MaxDistance.ToFloat(); line.emplace_back(spline.GetPosition(time)); } - g_Renderer.GetDebugRenderer().DrawLine(line, splineColor, 0.2f); + g_Renderer.GetDebugRenderer().DrawLine(line, splineColor, 0.2f, false); // Height indicator if (g_Game && g_Game->GetWorld() && g_Game->GetWorld()->GetTerrain()) @@ -115,7 +110,7 @@ const float time = start * i / spline.MaxDistance.ToFloat(); const CVector3D tmp = spline.GetPosition(time); const float groundY = g_Game->GetWorld()->GetTerrain()->GetExactGroundLevel(tmp.X, tmp.Z); - g_Renderer.GetDebugRenderer().DrawLine(tmp, CVector3D(tmp.X, groundY, tmp.Z), splineColor, 0.1f); + g_Renderer.GetDebugRenderer().DrawLine(tmp, CVector3D(tmp.X, groundY, tmp.Z), splineColor, 0.1f, false); } } } Index: ps/trunk/source/graphics/ShaderManager.cpp =================================================================== --- ps/trunk/source/graphics/ShaderManager.cpp +++ ps/trunk/source/graphics/ShaderManager.cpp @@ -333,12 +333,17 @@ EL(pass); EL(require); EL(sort_by_distance); + EL(stencil); + AT(compare); AT(constant); AT(context); + AT(depth_fail); AT(dst); + AT(fail); AT(front_face); AT(func); AT(mask); + AT(mask_read); AT(mask_red); AT(mask_green); AT(mask_blue); @@ -346,9 +351,12 @@ AT(mode); AT(name); AT(op); + AT(pass); + AT(reference); AT(shader); AT(shaders); AT(src); + AT(test); AT(value); #undef AT #undef EL @@ -494,6 +502,12 @@ } else if (Element.GetNodeName() == el_depth) { + if (!Element.GetAttributes().GetNamedItem(at_test).empty()) + { + passPipelineStateDesc.depthStencilState.depthTestEnabled = + Element.GetAttributes().GetNamedItem(at_test) == "TRUE"; + } + if (!Element.GetAttributes().GetNamedItem(at_func).empty()) { passPipelineStateDesc.depthStencilState.depthCompareOp = @@ -506,6 +520,55 @@ Element.GetAttributes().GetNamedItem(at_mask) == "true"; } } + else if (Element.GetNodeName() == el_stencil) + { + if (!Element.GetAttributes().GetNamedItem(at_test).empty()) + { + passPipelineStateDesc.depthStencilState.stencilTestEnabled = + Element.GetAttributes().GetNamedItem(at_test) == "TRUE"; + } + + if (!Element.GetAttributes().GetNamedItem(at_reference).empty()) + { + passPipelineStateDesc.depthStencilState.stencilReference = + Element.GetAttributes().GetNamedItem(at_reference).ToULong(); + } + if (!Element.GetAttributes().GetNamedItem(at_mask_read).empty()) + { + passPipelineStateDesc.depthStencilState.stencilReadMask = + Element.GetAttributes().GetNamedItem(at_mask_read).ToULong(); + } + if (!Element.GetAttributes().GetNamedItem(at_mask).empty()) + { + passPipelineStateDesc.depthStencilState.stencilWriteMask = + Element.GetAttributes().GetNamedItem(at_mask).ToULong(); + } + + if (!Element.GetAttributes().GetNamedItem(at_compare).empty()) + { + passPipelineStateDesc.depthStencilState.stencilFrontFace.compareOp = + passPipelineStateDesc.depthStencilState.stencilBackFace.compareOp = + Renderer::Backend::ParseCompareOp(Element.GetAttributes().GetNamedItem(at_compare)); + } + if (!Element.GetAttributes().GetNamedItem(at_fail).empty()) + { + passPipelineStateDesc.depthStencilState.stencilFrontFace.failOp = + passPipelineStateDesc.depthStencilState.stencilBackFace.failOp = + Renderer::Backend::ParseStencilOp(Element.GetAttributes().GetNamedItem(at_fail)); + } + if (!Element.GetAttributes().GetNamedItem(at_pass).empty()) + { + passPipelineStateDesc.depthStencilState.stencilFrontFace.passOp = + passPipelineStateDesc.depthStencilState.stencilBackFace.passOp = + Renderer::Backend::ParseStencilOp(Element.GetAttributes().GetNamedItem(at_pass)); + } + if (!Element.GetAttributes().GetNamedItem(at_depth_fail).empty()) + { + passPipelineStateDesc.depthStencilState.stencilFrontFace.depthFailOp = + passPipelineStateDesc.depthStencilState.stencilBackFace.depthFailOp = + Renderer::Backend::ParseStencilOp(Element.GetAttributes().GetNamedItem(at_depth_fail)); + } + } } pass.SetPipelineStateDesc(passPipelineStateDesc); Index: ps/trunk/source/renderer/DebugRenderer.h =================================================================== --- ps/trunk/source/renderer/DebugRenderer.h +++ ps/trunk/source/renderer/DebugRenderer.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2021 Wildfire Games. +/* Copyright (C) 2022 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -36,8 +36,10 @@ /** * Render the line in world space. */ - void DrawLine(const CVector3D& from, const CVector3D& to, const CColor& color, const float width); - void DrawLine(const std::vector& line, const CColor& color, const float width); + void DrawLine(const CVector3D& from, const CVector3D& to, + const CColor& color, const float width, const bool depthTestEnabled = true); + void DrawLine(const std::vector& line, + const CColor& color, const float width, const bool depthTestEnabled = true); /** * Render the circle in world space oriented to the view camera. Index: ps/trunk/source/renderer/DebugRenderer.cpp =================================================================== --- ps/trunk/source/renderer/DebugRenderer.cpp +++ ps/trunk/source/renderer/DebugRenderer.cpp @@ -40,9 +40,10 @@ void SetGraphicsPipelineStateFromTechAndColor( Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext, - const CShaderTechniquePtr& tech, const CColor& color) + const CShaderTechniquePtr& tech, const CColor& color, const bool depthTestEnabled = true) { Renderer::Backend::GraphicsPipelineStateDesc pipelineStateDesc = tech->GetGraphicsPipelineStateDesc(); + pipelineStateDesc.depthStencilState.depthTestEnabled = depthTestEnabled; if (color.a != 1.0f) { pipelineStateDesc.blendState.enabled = true; @@ -61,15 +62,19 @@ } // anonymous namespace -void CDebugRenderer::DrawLine(const CVector3D& from, const CVector3D& to, const CColor& color, const float width) +void CDebugRenderer::DrawLine( + const CVector3D& from, const CVector3D& to, const CColor& color, + const float width, const bool depthTestEnabled) { if (from == to) return; - DrawLine({from, to}, color, width); + DrawLine({from, to}, color, width, depthTestEnabled); } -void CDebugRenderer::DrawLine(const std::vector& line, const CColor& color, const float width) +void CDebugRenderer::DrawLine( + const std::vector& line, const CColor& color, + const float width, const bool depthTestEnabled) { #if CONFIG2_GLES UNUSED2(line); UNUSED2(color); UNUSED2(width); @@ -78,7 +83,7 @@ CShaderTechniquePtr debugLineTech = g_Renderer.GetShaderManager().LoadEffect(str_debug_line); debugLineTech->BeginPass(); - SetGraphicsPipelineStateFromTechAndColor(g_Renderer.GetDeviceCommandContext(), debugLineTech, color); + SetGraphicsPipelineStateFromTechAndColor(g_Renderer.GetDeviceCommandContext(), debugLineTech, color, depthTestEnabled); const CCamera& viewCamera = g_Renderer.GetSceneRenderer().GetViewCamera(); Index: ps/trunk/source/renderer/OverlayRenderer.cpp =================================================================== --- ps/trunk/source/renderer/OverlayRenderer.cpp +++ ps/trunk/source/renderer/OverlayRenderer.cpp @@ -622,7 +622,6 @@ glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); glActiveTextureARB(GL_TEXTURE0); - glDisable(GL_DEPTH_TEST); CVector3D right = -viewCamera.GetOrientation().GetLeft(); CVector3D up = viewCamera.GetOrientation().GetUp(); @@ -630,6 +629,7 @@ CShaderTechniquePtr tech = g_Renderer.GetShaderManager().LoadEffect(str_foreground_overlay); Renderer::Backend::GraphicsPipelineStateDesc pipelineStateDesc = tech->GetGraphicsPipelineStateDesc(); + pipelineStateDesc.depthStencilState.depthTestEnabled = false; pipelineStateDesc.blendState.enabled = true; pipelineStateDesc.blendState.srcColorBlendFactor = pipelineStateDesc.blendState.srcAlphaBlendFactor = Renderer::Backend::BlendFactor::SRC_ALPHA; @@ -673,8 +673,6 @@ tech->EndPass(); - glEnable(GL_DEPTH_TEST); - if (g_Renderer.GetSceneRenderer().GetOverlayRenderMode() == WIREFRAME) glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); #endif Index: ps/trunk/source/renderer/PostprocManager.cpp =================================================================== --- ps/trunk/source/renderer/PostprocManager.cpp +++ ps/trunk/source/renderer/PostprocManager.cpp @@ -427,8 +427,6 @@ else glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_PongFbo); - glDisable(GL_DEPTH_TEST); - shaderTech1->BeginPass(pass); deviceCommandContext->SetGraphicsPipelineState( shaderTech1->GetGraphicsPipelineStateDesc(pass)); @@ -487,8 +485,6 @@ shaderTech1->EndPass(pass); - glEnable(GL_DEPTH_TEST); - m_WhichBuffer = !m_WhichBuffer; } Index: ps/trunk/source/renderer/Renderer.cpp =================================================================== --- ps/trunk/source/renderer/Renderer.cpp +++ ps/trunk/source/renderer/Renderer.cpp @@ -517,8 +517,6 @@ ogl_WarnIfError(); } - glDisable(GL_DEPTH_TEST); - if (renderGUI) { OGL_SCOPED_DEBUG_GROUP("Draw GUI"); @@ -549,8 +547,6 @@ g_ProfileViewer.RenderProfile(); ogl_WarnIfError(); - glEnable(GL_DEPTH_TEST); - EndFrame(); const Stats& stats = GetStats(); Index: ps/trunk/source/renderer/SceneRenderer.cpp =================================================================== --- ps/trunk/source/renderer/SceneRenderer.cpp +++ ps/trunk/source/renderer/SceneRenderer.cpp @@ -785,10 +785,6 @@ // 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); - glStencilFunc(GL_NOTEQUAL, 1, (GLuint)-1); - glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); - { PROFILE("render model casters"); m->CallModelRenderers(deviceCommandContext, contextDisplay, CULL_SILHOUETTE_CASTER, 0); @@ -798,9 +794,6 @@ PROFILE("render transparent casters"); m->CallTranspModelRenderers(deviceCommandContext, contextDisplay, CULL_SILHOUETTE_CASTER, 0); } - - // Restore state - glDisable(GL_STENCIL_TEST); } void CSceneRenderer::RenderParticles( Index: ps/trunk/source/renderer/ShadowMap.cpp =================================================================== --- ps/trunk/source/renderer/ShadowMap.cpp +++ ps/trunk/source/renderer/ShadowMap.cpp @@ -755,8 +755,6 @@ if (!m->Texture) return; - glDisable(GL_DEPTH_TEST); - #if !CONFIG2_GLES g_Renderer.BindTexture(0, m->Texture->GetHandle()); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE); @@ -799,8 +797,6 @@ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE); #endif - glEnable(GL_DEPTH_TEST); - ogl_WarnIfError(); } Index: ps/trunk/source/renderer/TerrainOverlay.cpp =================================================================== --- ps/trunk/source/renderer/TerrainOverlay.cpp +++ ps/trunk/source/renderer/TerrainOverlay.cpp @@ -149,8 +149,6 @@ EndRender(); - // Clean up state changes - glEnable(GL_DEPTH_TEST); //glDisable(GL_POLYGON_OFFSET_LINE); glDisable(GL_POLYGON_OFFSET_FILL); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); @@ -172,15 +170,6 @@ // a vertex buffer or a vertex shader with a texture. // Not sure if it's possible on old OpenGL. - if (drawHidden) - { - glDisable(GL_DEPTH_TEST); - } - else - { - glEnable(GL_DEPTH_TEST); - } - #if CONFIG2_GLES UNUSED2(deviceCommandContext); UNUSED2(color); @@ -226,6 +215,7 @@ g_Renderer.GetShaderManager().LoadEffect(str_debug_line); Renderer::Backend::GraphicsPipelineStateDesc pipelineStateDesc = overlayTech->GetGraphicsPipelineStateDesc(); + pipelineStateDesc.depthStencilState.depthTestEnabled = !drawHidden; pipelineStateDesc.blendState.enabled = true; pipelineStateDesc.blendState.srcColorBlendFactor = pipelineStateDesc.blendState.srcAlphaBlendFactor = Renderer::Backend::BlendFactor::SRC_ALPHA; @@ -264,15 +254,6 @@ Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext, const CColor& color, int lineWidth, bool drawHidden, ssize_t i, ssize_t j) { - if (drawHidden) - { - glDisable(GL_DEPTH_TEST); - } - else - { - glEnable(GL_DEPTH_TEST); - } - #if CONFIG2_GLES UNUSED2(deviceCommandContext); UNUSED2(color); @@ -305,6 +286,7 @@ g_Renderer.GetShaderManager().LoadEffect(str_debug_line); Renderer::Backend::GraphicsPipelineStateDesc pipelineStateDesc = overlayTech->GetGraphicsPipelineStateDesc(); + pipelineStateDesc.depthStencilState.depthTestEnabled = !drawHidden; pipelineStateDesc.blendState.enabled = true; pipelineStateDesc.blendState.srcColorBlendFactor = pipelineStateDesc.blendState.srcAlphaBlendFactor = Renderer::Backend::BlendFactor::SRC_ALPHA; Index: ps/trunk/source/renderer/TerrainRenderer.cpp =================================================================== --- ps/trunk/source/renderer/TerrainRenderer.cpp +++ ps/trunk/source/renderer/TerrainRenderer.cpp @@ -174,8 +174,6 @@ std::vector& visiblePatches = m->visiblePatches[cullGroup]; - glDisable(GL_DEPTH_TEST); - CShaderTechniquePtr debugOverlayTech = g_Renderer.GetShaderManager().LoadEffect(str_debug_overlay); debugOverlayTech->BeginPass(); @@ -188,8 +186,6 @@ debugOverlayShader->Uniform(str_textureTransform, textureMatrix); CPatchRData::RenderStreams(visiblePatches, debugOverlayShader, STREAM_POS | STREAM_POSTOUV0); - glEnable(GL_DEPTH_TEST); - // To make the overlay visible over water, render an additional map-sized // water-height patch. CBoundingBoxAligned waterBounds; @@ -407,8 +403,6 @@ const double time = waterManager.m_WaterTexTimer; const float repeatPeriod = waterManager.m_RepeatPeriod; - glEnable(GL_DEPTH_TEST); - #if !CONFIG2_GLES if (g_Renderer.GetSceneRenderer().GetWaterRenderMode() == WIREFRAME) glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); @@ -526,8 +520,6 @@ const WaterManager& waterManager = g_Renderer.GetSceneRenderer().GetWaterManager(); CLOSTexture& losTexture = g_Game->GetView()->GetLOSTexture(); - glEnable(GL_DEPTH_TEST); - if (g_Renderer.GetSceneRenderer().GetWaterRenderMode() == WIREFRAME) glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); @@ -591,13 +583,12 @@ // Render normals and foam to a framebuffer if we're using fancy effects. glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, waterManager.m_FancyEffectsFBO); - glEnable(GL_DEPTH_TEST); - // Overwrite waves that would be behind the ground. CShaderTechniquePtr dummyTech = g_Renderer.GetShaderManager().LoadEffect(str_solid); dummyTech->BeginPass(); Renderer::Backend::GraphicsPipelineStateDesc pipelineStateDesc = dummyTech->GetGraphicsPipelineStateDesc(); + pipelineStateDesc.depthStencilState.depthTestEnabled = true; pipelineStateDesc.rasterizationState.cullMode = Renderer::Backend::CullMode::NONE; deviceCommandContext->SetGraphicsPipelineState(pipelineStateDesc); const CShaderProgramPtr& dummyShader = dummyTech->GetShader(); Index: ps/trunk/source/renderer/WaterManager.cpp =================================================================== --- ps/trunk/source/renderer/WaterManager.cpp +++ ps/trunk/source/renderer/WaterManager.cpp @@ -816,8 +816,6 @@ glClearColor(0.0f,0.0f, 0.0f,0.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - glEnable(GL_DEPTH_TEST); - CShaderTechniquePtr tech = g_Renderer.GetShaderManager().LoadEffect(str_water_waves); tech->BeginPass(); deviceCommandContext->SetGraphicsPipelineState( Index: ps/trunk/source/renderer/backend/PipelineState.h =================================================================== --- ps/trunk/source/renderer/backend/PipelineState.h +++ ps/trunk/source/renderer/backend/PipelineState.h @@ -48,10 +48,48 @@ ALWAYS }; +enum class StencilOp +{ + // Keeps the current value. + KEEP, + // Sets the value to zero. + ZERO, + // Sets the value to reference. + REPLACE, + // Increments the value and clamps to the maximum representable unsigned + // value. + INCREMENT_AND_CLAMP, + // Decrements the value and clamps to zero. + DECREMENT_AND_CLAMP, + // Bitwise inverts the value. + INVERT, + // Increments the value and wraps it to zero when incrementing the maximum + // representable unsigned value. + INCREMENT_AND_WRAP, + // Decrements the value and wraps it to the maximum representable unsigned + // value when decrementing zero. + DECREMENT_AND_WRAP +}; + +struct StencilOpState +{ + StencilOp failOp; + StencilOp passOp; + StencilOp depthFailOp; + CompareOp compareOp; +}; + struct DepthStencilStateDesc { + bool depthTestEnabled; CompareOp depthCompareOp; bool depthWriteEnabled; + bool stencilTestEnabled; + uint32_t stencilReadMask; + uint32_t stencilWriteMask; + uint32_t stencilReference; + StencilOpState stencilFrontFace; + StencilOpState stencilBackFace; }; // TODO: add per constant description. @@ -144,6 +182,8 @@ CompareOp ParseCompareOp(const CStr& str); +StencilOp ParseStencilOp(const CStr& str); + BlendFactor ParseBlendFactor(const CStr& str); BlendOp ParseBlendOp(const CStr& str); Index: ps/trunk/source/renderer/backend/PipelineState.cpp =================================================================== --- ps/trunk/source/renderer/backend/PipelineState.cpp +++ ps/trunk/source/renderer/backend/PipelineState.cpp @@ -19,6 +19,8 @@ #include "PipelineState.h" +#include + namespace Renderer { @@ -29,8 +31,18 @@ { GraphicsPipelineStateDesc desc{}; + desc.depthStencilState.depthTestEnabled = true; desc.depthStencilState.depthCompareOp = CompareOp::LESS_OR_EQUAL; desc.depthStencilState.depthWriteEnabled = true; + desc.depthStencilState.stencilTestEnabled = false; + desc.depthStencilState.stencilFrontFace.failOp = StencilOp::KEEP; + desc.depthStencilState.stencilFrontFace.passOp = StencilOp::KEEP; + desc.depthStencilState.stencilFrontFace.depthFailOp = StencilOp::KEEP; + desc.depthStencilState.stencilFrontFace.compareOp = CompareOp::ALWAYS; + desc.depthStencilState.stencilBackFace = desc.depthStencilState.stencilFrontFace; + desc.depthStencilState.stencilReadMask = desc.depthStencilState.stencilWriteMask = + std::numeric_limits::max(); + desc.depthStencilState.stencilReference = 0; desc.blendState.enabled = false; desc.blendState.srcColorBlendFactor = desc.blendState.srcAlphaBlendFactor = @@ -64,6 +76,22 @@ return CompareOp::NEVER; } +StencilOp ParseStencilOp(const CStr& str) +{ +#define CASE(NAME) if (str == #NAME) return StencilOp::NAME + CASE(KEEP); + CASE(ZERO); + CASE(REPLACE); + CASE(INCREMENT_AND_CLAMP); + CASE(DECREMENT_AND_CLAMP); + CASE(INVERT); + CASE(INCREMENT_AND_WRAP); + CASE(DECREMENT_AND_WRAP); +#undef CASE + debug_warn("Invalid stencil op"); + return StencilOp::KEEP; +} + BlendFactor ParseBlendFactor(const CStr& str) { // TODO: it might make sense to use upper case in XML for consistency. Index: ps/trunk/source/renderer/backend/gl/Device.cpp =================================================================== --- ps/trunk/source/renderer/backend/gl/Device.cpp +++ ps/trunk/source/renderer/backend/gl/Device.cpp @@ -196,9 +196,6 @@ glPixelStorei(GL_PACK_ALIGNMENT, 1); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - // Setup default state. - glEnable(GL_DEPTH_TEST); - return device; } Index: ps/trunk/source/renderer/backend/gl/DeviceCommandContext.cpp =================================================================== --- ps/trunk/source/renderer/backend/gl/DeviceCommandContext.cpp +++ ps/trunk/source/renderer/backend/gl/DeviceCommandContext.cpp @@ -31,6 +31,24 @@ namespace GL { +namespace +{ + +bool operator==(const StencilOpState& lhs, const StencilOpState& rhs) +{ + return + lhs.failOp == rhs.failOp && + lhs.passOp == rhs.passOp && + lhs.depthFailOp == rhs.depthFailOp && + lhs.compareOp == rhs.compareOp; +} +bool operator!=(const StencilOpState& lhs, const StencilOpState& rhs) +{ + return !operator==(lhs, rhs); +} + +} // anonymous namespace + // static std::unique_ptr CDeviceCommandContext::Create() { @@ -138,15 +156,90 @@ { const DepthStencilStateDesc& currentDepthStencilStateDesc = m_GraphicsPipelineStateDesc.depthStencilState; const DepthStencilStateDesc& nextDepthStencilStateDesc = pipelineStateDesc.depthStencilState; + if (force || currentDepthStencilStateDesc.depthTestEnabled != nextDepthStencilStateDesc.depthTestEnabled) + { + if (nextDepthStencilStateDesc.depthTestEnabled) + glEnable(GL_DEPTH_TEST); + else + glDisable(GL_DEPTH_TEST); + } if (force || currentDepthStencilStateDesc.depthCompareOp != nextDepthStencilStateDesc.depthCompareOp) { - glDepthFunc(Mapping::DepthFuncFromCompareOp(nextDepthStencilStateDesc.depthCompareOp)); + glDepthFunc(Mapping::FromCompareOp(nextDepthStencilStateDesc.depthCompareOp)); } if (force || currentDepthStencilStateDesc.depthWriteEnabled != nextDepthStencilStateDesc.depthWriteEnabled) { glDepthMask(nextDepthStencilStateDesc.depthWriteEnabled ? GL_TRUE : GL_FALSE); } + if (force || currentDepthStencilStateDesc.stencilTestEnabled != nextDepthStencilStateDesc.stencilTestEnabled) + { + if (nextDepthStencilStateDesc.stencilTestEnabled) + glEnable(GL_STENCIL_TEST); + else + glDisable(GL_STENCIL_TEST); + } + if (force || + currentDepthStencilStateDesc.stencilFrontFace != nextDepthStencilStateDesc.stencilFrontFace || + currentDepthStencilStateDesc.stencilBackFace != nextDepthStencilStateDesc.stencilBackFace) + { + if (nextDepthStencilStateDesc.stencilFrontFace == nextDepthStencilStateDesc.stencilBackFace) + { + glStencilOp( + Mapping::FromStencilOp(nextDepthStencilStateDesc.stencilFrontFace.failOp), + Mapping::FromStencilOp(nextDepthStencilStateDesc.stencilFrontFace.depthFailOp), + Mapping::FromStencilOp(nextDepthStencilStateDesc.stencilFrontFace.passOp)); + } + else + { + if (force || currentDepthStencilStateDesc.stencilFrontFace != nextDepthStencilStateDesc.stencilFrontFace) + { + glStencilOpSeparate( + GL_FRONT, + Mapping::FromStencilOp(nextDepthStencilStateDesc.stencilFrontFace.failOp), + Mapping::FromStencilOp(nextDepthStencilStateDesc.stencilFrontFace.depthFailOp), + Mapping::FromStencilOp(nextDepthStencilStateDesc.stencilFrontFace.passOp)); + } + if (force || currentDepthStencilStateDesc.stencilBackFace != nextDepthStencilStateDesc.stencilBackFace) + { + glStencilOpSeparate( + GL_BACK, + Mapping::FromStencilOp(nextDepthStencilStateDesc.stencilBackFace.failOp), + Mapping::FromStencilOp(nextDepthStencilStateDesc.stencilBackFace.depthFailOp), + Mapping::FromStencilOp(nextDepthStencilStateDesc.stencilBackFace.passOp)); + } + } + } + if (force || currentDepthStencilStateDesc.stencilWriteMask != nextDepthStencilStateDesc.stencilWriteMask) + { + glStencilMask(nextDepthStencilStateDesc.stencilWriteMask); + } + if (force || + currentDepthStencilStateDesc.stencilReference != nextDepthStencilStateDesc.stencilReference || + currentDepthStencilStateDesc.stencilReadMask != nextDepthStencilStateDesc.stencilReadMask || + currentDepthStencilStateDesc.stencilFrontFace.compareOp != nextDepthStencilStateDesc.stencilFrontFace.compareOp || + currentDepthStencilStateDesc.stencilBackFace.compareOp != nextDepthStencilStateDesc.stencilBackFace.compareOp) + { + if (nextDepthStencilStateDesc.stencilFrontFace.compareOp == nextDepthStencilStateDesc.stencilBackFace.compareOp) + { + glStencilFunc( + Mapping::FromCompareOp(nextDepthStencilStateDesc.stencilFrontFace.compareOp), + nextDepthStencilStateDesc.stencilReference, + nextDepthStencilStateDesc.stencilReadMask); + } + else + { + glStencilFuncSeparate(GL_FRONT, + Mapping::FromCompareOp(nextDepthStencilStateDesc.stencilFrontFace.compareOp), + nextDepthStencilStateDesc.stencilReference, + nextDepthStencilStateDesc.stencilReadMask); + glStencilFuncSeparate(GL_BACK, + Mapping::FromCompareOp(nextDepthStencilStateDesc.stencilBackFace.compareOp), + nextDepthStencilStateDesc.stencilReference, + nextDepthStencilStateDesc.stencilReadMask); + } + } + const BlendStateDesc& currentBlendStateDesc = m_GraphicsPipelineStateDesc.blendState; const BlendStateDesc& nextBlendStateDesc = pipelineStateDesc.blendState; if (force || currentBlendStateDesc.enabled != nextBlendStateDesc.enabled) Index: ps/trunk/source/renderer/backend/gl/Mapping.h =================================================================== --- ps/trunk/source/renderer/backend/gl/Mapping.h +++ ps/trunk/source/renderer/backend/gl/Mapping.h @@ -33,7 +33,9 @@ namespace Mapping { -GLenum DepthFuncFromCompareOp(const CompareOp compareOp); +GLenum FromCompareOp(const CompareOp compareOp); + +GLenum FromStencilOp(const StencilOp stencilOp); GLenum FromBlendFactor(const BlendFactor blendFactor); Index: ps/trunk/source/renderer/backend/gl/Mapping.cpp =================================================================== --- ps/trunk/source/renderer/backend/gl/Mapping.cpp +++ ps/trunk/source/renderer/backend/gl/Mapping.cpp @@ -34,12 +34,12 @@ namespace Mapping { -GLenum DepthFuncFromCompareOp(const CompareOp compareOp) +GLenum FromCompareOp(const CompareOp compareOp) { - GLenum detphFunc = GL_NEVER; + GLenum op = GL_NEVER; switch (compareOp) { -#define CASE(NAME, GL_NAME) case CompareOp::NAME: detphFunc = GL_NAME; break +#define CASE(NAME, GL_NAME) case CompareOp::NAME: op = GL_NAME; break CASE(NEVER, GL_NEVER); CASE(LESS, GL_LESS); CASE(EQUAL, GL_EQUAL); @@ -50,7 +50,26 @@ CASE(ALWAYS, GL_ALWAYS); #undef CASE } - return detphFunc; + return op; +} + +GLenum FromStencilOp(const StencilOp stencilOp) +{ + GLenum op = GL_KEEP; + switch (stencilOp) + { +#define CASE(NAME, GL_NAME) case StencilOp::NAME: op = GL_NAME; break + CASE(KEEP, GL_KEEP); + CASE(ZERO, GL_ZERO); + CASE(REPLACE, GL_REPLACE); + CASE(INCREMENT_AND_CLAMP, GL_INCR); + CASE(DECREMENT_AND_CLAMP, GL_DECR); + CASE(INVERT, GL_INVERT); + CASE(INCREMENT_AND_WRAP, GL_INCR_WRAP); + CASE(DECREMENT_AND_WRAP, GL_DECR_WRAP); +#undef CASE + } + return op; } GLenum FromBlendFactor(const BlendFactor blendFactor) Index: ps/trunk/source/tools/atlas/GameInterface/ActorViewer.cpp =================================================================== --- ps/trunk/source/tools/atlas/GameInterface/ActorViewer.cpp +++ ps/trunk/source/tools/atlas/GameInterface/ActorViewer.cpp @@ -524,10 +524,8 @@ g_Renderer.GetSceneRenderer().RenderScene(g_Renderer.GetDeviceCommandContext(), m); - glDisable(GL_DEPTH_TEST); g_Logger->Render(); g_ProfileViewer.RenderProfile(); - glEnable(GL_DEPTH_TEST); g_Renderer.EndFrame(); Index: ps/trunk/source/tools/atlas/GameInterface/View.cpp =================================================================== --- ps/trunk/source/tools/atlas/GameInterface/View.cpp +++ ps/trunk/source/tools/atlas/GameInterface/View.cpp @@ -247,11 +247,15 @@ const float axisLength = scale / 10.0f; const float lineWidth = scale / 1e3f; - glDisable(GL_DEPTH_TEST); - g_Renderer.GetDebugRenderer().DrawLine(focus, focus + CVector3D(axisLength, 0, 0), CColor(1.0f, 0.0f, 0.0f, 1.0f), lineWidth); - g_Renderer.GetDebugRenderer().DrawLine(focus, focus + CVector3D(0, axisLength, 0), CColor(0.0f, 1.0f, 0.0f, 1.0f), lineWidth); - g_Renderer.GetDebugRenderer().DrawLine(focus, focus + CVector3D(0, 0, axisLength), CColor(0.0f, 0.0f, 1.0f, 1.0f), lineWidth); - glEnable(GL_DEPTH_TEST); + g_Renderer.GetDebugRenderer().DrawLine( + focus, focus + CVector3D(axisLength, 0, 0), + CColor(1.0f, 0.0f, 0.0f, 1.0f), lineWidth, false); + g_Renderer.GetDebugRenderer().DrawLine( + focus, focus + CVector3D(0, axisLength, 0), + CColor(0.0f, 1.0f, 0.0f, 1.0f), lineWidth, false); + g_Renderer.GetDebugRenderer().DrawLine( + focus, focus + CVector3D(0, 0, axisLength), + CColor(0.0f, 0.0f, 1.0f, 1.0f), lineWidth, false); } void AtlasViewGame::DrawOverlays(CCanvas2D& canvas)