From d4d1bc039f198fff0d2673f79bfbadf3052cc2e6 Mon Sep 17 00:00:00 2001 From: vladislavbelov Date: Thu, 27 Jan 2022 17:25:37 +0000 Subject: [PATCH] Moves culling mode and front face state management to DeviceCommandContext. Tested By: Langbart Differential Revision: https://code.wildfiregames.com/D4456 This was SVN commit r26259. --- .../mods/public/shaders/effects/dummy.xml | 16 +- .../mods/public/shaders/effects/model.xml | 16 ++ .../shaders/effects/model_transparent.xml | 195 +++++++++++------- .../public/shaders/effects/terrain_base.xml | 32 ++- .../public/shaders/effects/terrain_blend.xml | 32 ++- .../public/shaders/effects/terrain_decal.xml | 32 ++- .../public/shaders/effects/terrain_solid.xml | 34 +++ source/graphics/ShaderManager.cpp | 16 ++ source/ps/CStrInternStatic.h | 4 + source/renderer/DebugRenderer.cpp | 1 + source/renderer/PatchRData.cpp | 4 - source/renderer/SceneRenderer.cpp | 57 ++--- source/renderer/SceneRenderer.h | 2 +- source/renderer/ShadowMap.cpp | 2 - source/renderer/SilhouetteRenderer.cpp | 13 +- source/renderer/TerrainOverlay.cpp | 35 ++-- source/renderer/TerrainOverlay.h | 14 +- source/renderer/TerrainRenderer.cpp | 33 +-- source/renderer/TerrainRenderer.h | 3 +- source/renderer/backend/gl/Device.cpp | 3 - .../backend/gl/DeviceCommandContext.cpp | 26 +++ 21 files changed, 370 insertions(+), 200 deletions(-) create mode 100644 binaries/data/mods/public/shaders/effects/terrain_solid.xml diff --git a/binaries/data/mods/public/shaders/effects/dummy.xml b/binaries/data/mods/public/shaders/effects/dummy.xml index f9219a61ef..f0abcbcbea 100644 --- a/binaries/data/mods/public/shaders/effects/dummy.xml +++ b/binaries/data/mods/public/shaders/effects/dummy.xml @@ -1,11 +1,11 @@ - - - - - - - - + + + + + + + + diff --git a/binaries/data/mods/public/shaders/effects/model.xml b/binaries/data/mods/public/shaders/effects/model.xml index 1319ade3af..13257aec7d 100644 --- a/binaries/data/mods/public/shaders/effects/model.xml +++ b/binaries/data/mods/public/shaders/effects/model.xml @@ -1,6 +1,22 @@ + + + + + + + + + + + + + + + + diff --git a/binaries/data/mods/public/shaders/effects/model_transparent.xml b/binaries/data/mods/public/shaders/effects/model_transparent.xml index c052dc1c82..2c9d209aa7 100644 --- a/binaries/data/mods/public/shaders/effects/model_transparent.xml +++ b/binaries/data/mods/public/shaders/effects/model_transparent.xml @@ -1,83 +1,132 @@ - - - - - - - + + + + + + + + + - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + diff --git a/binaries/data/mods/public/shaders/effects/terrain_base.xml b/binaries/data/mods/public/shaders/effects/terrain_base.xml index 362690c680..bd1f6297d9 100644 --- a/binaries/data/mods/public/shaders/effects/terrain_base.xml +++ b/binaries/data/mods/public/shaders/effects/terrain_base.xml @@ -1,14 +1,30 @@ - - - - + + + + + + + - - - - + + + + + + + + + + + + + + + + + diff --git a/binaries/data/mods/public/shaders/effects/terrain_blend.xml b/binaries/data/mods/public/shaders/effects/terrain_blend.xml index 529af7aad7..bef2b61b06 100644 --- a/binaries/data/mods/public/shaders/effects/terrain_blend.xml +++ b/binaries/data/mods/public/shaders/effects/terrain_blend.xml @@ -1,14 +1,30 @@ - - - - + + + + + + + - - - - + + + + + + + + + + + + + + + + + diff --git a/binaries/data/mods/public/shaders/effects/terrain_decal.xml b/binaries/data/mods/public/shaders/effects/terrain_decal.xml index 5eb5e5a503..19c85473fc 100644 --- a/binaries/data/mods/public/shaders/effects/terrain_decal.xml +++ b/binaries/data/mods/public/shaders/effects/terrain_decal.xml @@ -1,14 +1,30 @@ - - - - + + + + + + + - - - - + + + + + + + + + + + + + + + + + diff --git a/binaries/data/mods/public/shaders/effects/terrain_solid.xml b/binaries/data/mods/public/shaders/effects/terrain_solid.xml new file mode 100644 index 0000000000..8f46a0692e --- /dev/null +++ b/binaries/data/mods/public/shaders/effects/terrain_solid.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/source/graphics/ShaderManager.cpp b/source/graphics/ShaderManager.cpp index 33729a32e5..7eee400a8b 100644 --- a/source/graphics/ShaderManager.cpp +++ b/source/graphics/ShaderManager.cpp @@ -352,6 +352,7 @@ bool CShaderManager::NewEffect(const char* name, const CShaderDefines& baseDefin #define EL(x) int el_##x = XeroFile.GetElementID(#x) #define AT(x) int at_##x = XeroFile.GetAttributeID(#x) EL(blend); + EL(cull); EL(define); EL(depth); EL(pass); @@ -360,7 +361,9 @@ bool CShaderManager::NewEffect(const char* name, const CShaderDefines& baseDefin AT(constant); AT(context); AT(dst); + AT(front_face); AT(func); + AT(mode); AT(op); AT(shader); AT(shaders); @@ -493,6 +496,19 @@ bool CShaderManager::NewEffect(const char* name, const CShaderDefines& baseDefin } } } + else if (Element.GetNodeName() == el_cull) + { + if (!Element.GetAttributes().GetNamedItem(at_mode).empty()) + { + passPipelineStateDesc.rasterizationState.cullMode = + Renderer::Backend::ParseCullMode(Element.GetAttributes().GetNamedItem(at_mode)); + } + if (!Element.GetAttributes().GetNamedItem(at_front_face).empty()) + { + passPipelineStateDesc.rasterizationState.frontFace = + Renderer::Backend::ParseFrontFace(Element.GetAttributes().GetNamedItem(at_front_face)); + } + } else if (Element.GetNodeName() == el_depth) { if (!Element.GetAttributes().GetNamedItem(at_func).empty()) diff --git a/source/ps/CStrInternStatic.h b/source/ps/CStrInternStatic.h index 468e7a1537..2885679f90 100644 --- a/source/ps/CStrInternStatic.h +++ b/source/ps/CStrInternStatic.h @@ -56,6 +56,9 @@ X(MODE_SHADOWCAST) X(MODE_SILHOUETTEDISPLAY) X(MODE_SILHOUETTEOCCLUDER) X(MODE_WIREFRAME) +X(PASS_REFLECTIONS) +X(PASS_REFRACTIONS) +X(PASS_SHADOWS) X(RENDER_DEBUG_MODE) X(RENDER_DEBUG_MODE_AO) X(RENDER_DEBUG_MODE_ALPHA) @@ -165,6 +168,7 @@ X(sky_simple) X(solid) X(sunColor) X(sunDir) +X(terrain_solid) X(tex) X(texSize) X(textureTransform) diff --git a/source/renderer/DebugRenderer.cpp b/source/renderer/DebugRenderer.cpp index b2a9c81528..0a728a23a2 100644 --- a/source/renderer/DebugRenderer.cpp +++ b/source/renderer/DebugRenderer.cpp @@ -55,6 +55,7 @@ void SetGraphicsPipelineStateFromTechAndColor( } else pipelineStateDesc.blendState.enabled = false; + pipelineStateDesc.rasterizationState.cullMode = Renderer::Backend::CullMode::NONE; deviceCommandContext->SetGraphicsPipelineState(pipelineStateDesc); } diff --git a/source/renderer/PatchRData.cpp b/source/renderer/PatchRData.cpp index 1d99ccf10a..5439f6f5f0 100644 --- a/source/renderer/PatchRData.cpp +++ b/source/renderer/PatchRData.cpp @@ -1133,8 +1133,6 @@ void CPatchRData::RenderSides(const std::vector& patches, const CS { PROFILE3("render terrain sides"); - glDisable(GL_CULL_FACE); - CVertexBuffer* lastVB = nullptr; for (CPatchRData* patch : patches) { @@ -1161,8 +1159,6 @@ void CPatchRData::RenderSides(const std::vector& patches, const CS } CVertexBuffer::Unbind(); - - glEnable(GL_CULL_FACE); } void CPatchRData::RenderPriorities(CTextRenderer& textRenderer) diff --git a/source/renderer/SceneRenderer.cpp b/source/renderer/SceneRenderer.cpp index e52691c54b..482c842fad 100644 --- a/source/renderer/SceneRenderer.cpp +++ b/source/renderer/SceneRenderer.cpp @@ -308,7 +308,10 @@ void CSceneRenderer::RenderShadowMap( PROFILE3_GPU("shadow map"); OGL_SCOPED_DEBUG_GROUP("Render shadow map"); - CShaderDefines contextCast = context; + CShaderDefines shadowsContext = context; + shadowsContext.Add(str_PASS_SHADOWS, str_1); + + CShaderDefines contextCast = shadowsContext; contextCast.Add(str_MODE_SHADOWCAST, str_1); m->shadow.BeginRender(); @@ -322,10 +325,7 @@ void CSceneRenderer::RenderShadowMap( const int cullGroup = CULL_SHADOWS_CASCADE_0 + cascade; { PROFILE("render patches"); - glCullFace(GL_FRONT); - glEnable(GL_CULL_FACE); - m->terrainRenderer.RenderPatches(deviceCommandContext, cullGroup); - glCullFace(GL_BACK); + m->terrainRenderer.RenderPatches(deviceCommandContext, cullGroup, shadowsContext); } { @@ -335,10 +335,7 @@ void CSceneRenderer::RenderShadowMap( { PROFILE("render transparent models"); - // disable face-culling for two-sided models - glDisable(GL_CULL_FACE); m->CallTranspModelRenderers(deviceCommandContext, contextCast, cullGroup, MODELFLAG_CASTSHADOWS); - glEnable(GL_CULL_FACE); } } @@ -386,7 +383,7 @@ void CSceneRenderer::RenderPatches( glLineWidth(2.0f); // render tiles edges - m->terrainRenderer.RenderPatches(deviceCommandContext, cullGroup, CColor(0.5f, 0.5f, 1.0f, 1.0f)); + m->terrainRenderer.RenderPatches(deviceCommandContext, cullGroup, context, CColor(0.5f, 0.5f, 1.0f, 1.0f)); glLineWidth(4.0f); @@ -439,7 +436,7 @@ void CSceneRenderer::RenderModels( void CSceneRenderer::RenderTransparentModels( Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext, - const CShaderDefines& context, int cullGroup, ETransparentMode transparentMode, bool disableFaceCulling) + const CShaderDefines& context, int cullGroup, ETransparentMode transparentMode) { PROFILE3_GPU("transparent models"); OGL_SCOPED_DEBUG_GROUP("Render transparent models"); @@ -454,10 +451,6 @@ void CSceneRenderer::RenderTransparentModels( } #endif - // disable face culling for two-sided models in sub-renders - if (disableFaceCulling) - glDisable(GL_CULL_FACE); - CShaderDefines contextOpaque = context; contextOpaque.Add(str_ALPHABLEND_PASS_OPAQUE, str_1); @@ -470,9 +463,6 @@ void CSceneRenderer::RenderTransparentModels( if (transparentMode == TRANSPARENT || transparentMode == TRANSPARENT_BLEND) m->CallTranspModelRenderers(deviceCommandContext, contextBlend, cullGroup, flags); - if (disableFaceCulling) - glEnable(GL_CULL_FACE); - #if !CONFIG2_GLES if (m_ModelRenderMode == WIREFRAME) { @@ -651,8 +641,6 @@ void CSceneRenderer::RenderReflections( glClearColor(0.5f, 0.5f, 1.0f, 0.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - glFrontFace(GL_CW); - if (!g_RenderingOptions.GetWaterReflection()) { m->skyManager.RenderSky(deviceCommandContext); @@ -660,18 +648,19 @@ void CSceneRenderer::RenderReflections( } else { + CShaderDefines reflectionsContext = context; + reflectionsContext.Add(str_PASS_REFLECTIONS, str_1); // Render terrain and models - RenderPatches(deviceCommandContext, context, CULL_REFLECTIONS); + RenderPatches(deviceCommandContext, reflectionsContext, CULL_REFLECTIONS); ogl_WarnIfError(); - RenderModels(deviceCommandContext, context, CULL_REFLECTIONS); + RenderModels(deviceCommandContext, reflectionsContext, CULL_REFLECTIONS); ogl_WarnIfError(); - RenderTransparentModels(deviceCommandContext, context, CULL_REFLECTIONS, TRANSPARENT, true); + RenderTransparentModels(deviceCommandContext, reflectionsContext, CULL_REFLECTIONS, TRANSPARENT); ogl_WarnIfError(); } - glFrontFace(GL_CCW); // Particles are always oriented to face the camera in the vertex shader, - // so they don't need the inverted glFrontFace + // so they don't need the inverted cull face. if (g_RenderingOptions.GetParticles()) { RenderParticles(deviceCommandContext, CULL_REFLECTIONS); @@ -737,7 +726,7 @@ void CSceneRenderer::RenderRefractions( ogl_WarnIfError(); RenderModels(deviceCommandContext, context, CULL_REFRACTIONS); ogl_WarnIfError(); - RenderTransparentModels(deviceCommandContext, context, CULL_REFRACTIONS, TRANSPARENT_OPAQUE, false); + RenderTransparentModels(deviceCommandContext, context, CULL_REFRACTIONS, TRANSPARENT_OPAQUE); ogl_WarnIfError(); glDisable(GL_SCISSOR_TEST); @@ -777,13 +766,7 @@ void CSceneRenderer::RenderSilhouettes( { PROFILE("render patches"); - - // To prevent units displaying silhouettes when parts of their model - // protrude into the ground, only occlude with the back faces of the - // terrain (so silhouettes will still display when behind hills) - glCullFace(GL_FRONT); - m->terrainRenderer.RenderPatches(deviceCommandContext, CULL_SILHOUETTE_OCCLUDER); - glCullFace(GL_BACK); + m->terrainRenderer.RenderPatches(deviceCommandContext, CULL_SILHOUETTE_OCCLUDER, contextOccluder); } { @@ -949,14 +932,14 @@ void CSceneRenderer::RenderSubmissions( if (m->waterManager.WillRenderFancyWater()) { // Render transparent stuff, but only the solid parts that can occlude block water. - RenderTransparentModels(deviceCommandContext, context, cullGroup, TRANSPARENT_OPAQUE, false); + RenderTransparentModels(deviceCommandContext, context, cullGroup, TRANSPARENT_OPAQUE); ogl_WarnIfError(); m->terrainRenderer.RenderWater(deviceCommandContext, context, cullGroup, &m->shadow); ogl_WarnIfError(); // Render transparent stuff again, but only the blended parts that overlap water. - RenderTransparentModels(deviceCommandContext, context, cullGroup, TRANSPARENT_BLEND, false); + RenderTransparentModels(deviceCommandContext, context, cullGroup, TRANSPARENT_BLEND); ogl_WarnIfError(); } else @@ -965,14 +948,14 @@ void CSceneRenderer::RenderSubmissions( ogl_WarnIfError(); // Render transparent stuff, so it can overlap models/terrain. - RenderTransparentModels(deviceCommandContext, context, cullGroup, TRANSPARENT, false); + RenderTransparentModels(deviceCommandContext, context, cullGroup, TRANSPARENT); ogl_WarnIfError(); } } else { // render transparent stuff, so it can overlap models/terrain - RenderTransparentModels(deviceCommandContext, context, cullGroup, TRANSPARENT, false); + RenderTransparentModels(deviceCommandContext, context, cullGroup, TRANSPARENT); ogl_WarnIfError(); } @@ -1049,7 +1032,6 @@ void CSceneRenderer::DisplayFrustum() #warning TODO: implement CSceneRenderer::DisplayFrustum for GLES #else glDepthMask(0); - glDisable(GL_CULL_FACE); g_Renderer.GetDebugRenderer().DrawCameraFrustum(m_CullCamera, CColor(1.0f, 1.0f, 1.0f, 0.25f), 2); @@ -1057,7 +1039,6 @@ void CSceneRenderer::DisplayFrustum() g_Renderer.GetDebugRenderer().DrawCameraFrustum(m_CullCamera, CColor(1.0f, 1.0f, 1.0f, 1.0f), 2); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); - glEnable(GL_CULL_FACE); glDepthMask(1); #endif diff --git a/source/renderer/SceneRenderer.h b/source/renderer/SceneRenderer.h index 56c0c9fee6..ea7926f495 100644 --- a/source/renderer/SceneRenderer.h +++ b/source/renderer/SceneRenderer.h @@ -208,7 +208,7 @@ protected: const CShaderDefines& context, int cullGroup); void RenderTransparentModels( Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext, - const CShaderDefines& context, int cullGroup, ETransparentMode transparentMode, bool disableFaceCulling); + const CShaderDefines& context, int cullGroup, ETransparentMode transparentMode); void RenderSilhouettes( Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext, diff --git a/source/renderer/ShadowMap.cpp b/source/renderer/ShadowMap.cpp index 1bc18ca488..4dc2759a10 100644 --- a/source/renderer/ShadowMap.cpp +++ b/source/renderer/ShadowMap.cpp @@ -727,7 +727,6 @@ void ShadowMap::SetDepthTextureBits(int bits) void ShadowMap::RenderDebugBounds() { glDepthMask(0); - glDisable(GL_CULL_FACE); // Render various shadow bounds: // Yellow = bounds of objects in view frustum that receive shadows @@ -755,7 +754,6 @@ void ShadowMap::RenderDebugBounds() g_Renderer.GetDebugRenderer().DrawBrushOutline(frustumBrush, CColor(1.0f, 0.0f, 0.0f, 0.5f)); } - glEnable(GL_CULL_FACE); glDepthMask(1); ogl_WarnIfError(); diff --git a/source/renderer/SilhouetteRenderer.cpp b/source/renderer/SilhouetteRenderer.cpp index 8a6fefc494..3336948a85 100644 --- a/source/renderer/SilhouetteRenderer.cpp +++ b/source/renderer/SilhouetteRenderer.cpp @@ -451,7 +451,6 @@ void SilhouetteRenderer::RenderDebugOverlays( return; glDepthMask(0); - glDisable(GL_CULL_FACE); for (size_t i = 0; i < m_DebugBounds.size(); ++i) g_Renderer.GetDebugRenderer().DrawBoundingBoxOutline(m_DebugBounds[i].bounds, m_DebugBounds[i].color); @@ -468,17 +467,20 @@ void SilhouetteRenderer::RenderDebugOverlays( CShaderTechniquePtr shaderTech = g_Renderer.GetShaderManager().LoadEffect(str_solid); shaderTech->BeginPass(); - deviceCommandContext->SetGraphicsPipelineState( - shaderTech->GetGraphicsPipelineStateDesc()); + Renderer::Backend::GraphicsPipelineStateDesc pipelineStateDesc = + shaderTech->GetGraphicsPipelineStateDesc(); + pipelineStateDesc.rasterizationState.cullMode = Renderer::Backend::CullMode::NONE; + deviceCommandContext->SetGraphicsPipelineState(pipelineStateDesc); - CShaderProgramPtr shader = shaderTech->GetShader(); + const CShaderProgramPtr& shader = shaderTech->GetShader(); shader->Uniform(str_transform, proj); for (size_t i = 0; i < m_DebugRects.size(); ++i) { const DebugRect& r = m_DebugRects[i]; shader->Uniform(str_color, r.color); - u16 verts[] = { + u16 verts[] = + { r.x0, r.y0, r.x1, r.y0, r.x1, r.y1, @@ -491,7 +493,6 @@ void SilhouetteRenderer::RenderDebugOverlays( shaderTech->EndPass(); - glEnable(GL_CULL_FACE); glDepthMask(1); } diff --git a/source/renderer/TerrainOverlay.cpp b/source/renderer/TerrainOverlay.cpp index fa8360720f..c3fa8f3cc8 100644 --- a/source/renderer/TerrainOverlay.cpp +++ b/source/renderer/TerrainOverlay.cpp @@ -151,7 +151,6 @@ void TerrainOverlay::RenderBeforeWater( EndRender(); // Clean up state changes - glEnable(GL_CULL_FACE); glEnable(GL_DEPTH_TEST); //glDisable(GL_POLYGON_OFFSET_LINE); glDisable(GL_POLYGON_OFFSET_FILL); @@ -162,28 +161,26 @@ void TerrainOverlay::RenderBeforeWater( void TerrainOverlay::RenderTile( Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext, - const CColor& color, bool draw_hidden) + const CColor& color, bool drawHidden) { - RenderTile(deviceCommandContext, color, draw_hidden, m_i, m_j); + RenderTile(deviceCommandContext, color, drawHidden, m_i, m_j); } void TerrainOverlay::RenderTile( Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext, - const CColor& color, bool draw_hidden, ssize_t i, ssize_t j) + const CColor& color, bool drawHidden, ssize_t i, ssize_t j) { // TODO: unnecessary computation calls has been removed but we should use // a vertex buffer or a vertex shader with a texture. // Not sure if it's possible on old OpenGL. - if (draw_hidden) + if (drawHidden) { glDisable(GL_DEPTH_TEST); - glDisable(GL_CULL_FACE); } else { glEnable(GL_DEPTH_TEST); - glEnable(GL_CULL_FACE); } #if CONFIG2_GLES @@ -238,6 +235,8 @@ void TerrainOverlay::RenderTile( Renderer::Backend::BlendFactor::ONE_MINUS_SRC_ALPHA; pipelineStateDesc.blendState.colorBlendOp = pipelineStateDesc.blendState.alphaBlendOp = Renderer::Backend::BlendOp::ADD; + pipelineStateDesc.rasterizationState.cullMode = + drawHidden ? Renderer::Backend::CullMode::NONE : Renderer::Backend::CullMode::BACK; overlayTech->BeginPass(); deviceCommandContext->SetGraphicsPipelineState(pipelineStateDesc); @@ -258,30 +257,28 @@ void TerrainOverlay::RenderTile( void TerrainOverlay::RenderTileOutline( Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext, - const CColor& color, int line_width, bool draw_hidden) + const CColor& color, int lineWidth, bool drawHidden) { - RenderTileOutline(deviceCommandContext, color, line_width, draw_hidden, m_i, m_j); + RenderTileOutline(deviceCommandContext, color, lineWidth, drawHidden, m_i, m_j); } void TerrainOverlay::RenderTileOutline( Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext, - const CColor& color, int line_width, bool draw_hidden, ssize_t i, ssize_t j) + const CColor& color, int lineWidth, bool drawHidden, ssize_t i, ssize_t j) { - if (draw_hidden) + if (drawHidden) { glDisable(GL_DEPTH_TEST); - glDisable(GL_CULL_FACE); } else { glEnable(GL_DEPTH_TEST); - glEnable(GL_CULL_FACE); } #if CONFIG2_GLES UNUSED2(deviceCommandContext); UNUSED2(color); - UNUSED2(line_width); + UNUSED2(lineWidth); UNUSED2(i); UNUSED2(j); #warning TODO: implement TerrainOverlay::RenderTileOutline for GLES @@ -289,8 +286,8 @@ void TerrainOverlay::RenderTileOutline( glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); - if (line_width != 1) - glLineWidth((float)line_width); + if (lineWidth != 1) + glLineWidth(static_cast(lineWidth)); std::vector vertices; #define ADD(i, j) \ @@ -317,10 +314,12 @@ void TerrainOverlay::RenderTileOutline( Renderer::Backend::BlendFactor::ONE_MINUS_SRC_ALPHA; pipelineStateDesc.blendState.colorBlendOp = pipelineStateDesc.blendState.alphaBlendOp = Renderer::Backend::BlendOp::ADD; + pipelineStateDesc.rasterizationState.cullMode = + drawHidden ? Renderer::Backend::CullMode::NONE : Renderer::Backend::CullMode::BACK; overlayTech->BeginPass(); deviceCommandContext->SetGraphicsPipelineState(pipelineStateDesc); - CShaderProgramPtr overlayShader = overlayTech->GetShader(); + const CShaderProgramPtr& overlayShader = overlayTech->GetShader(); overlayShader->Uniform(str_transform, g_Renderer.GetSceneRenderer().GetViewCamera().GetViewProjection()); overlayShader->Uniform(str_color, color); @@ -332,7 +331,7 @@ void TerrainOverlay::RenderTileOutline( overlayTech->EndPass(); - if (line_width != 1) + if (lineWidth != 1) glLineWidth(1.0f); #endif } diff --git a/source/renderer/TerrainOverlay.h b/source/renderer/TerrainOverlay.h index 26ff5a0340..5ceb60c637 100644 --- a/source/renderer/TerrainOverlay.h +++ b/source/renderer/TerrainOverlay.h @@ -136,38 +136,38 @@ protected: * Draw a filled quad on top of the current tile. * * @param color color to draw. May be transparent (alpha < 1) - * @param draw_hidden true if hidden tiles (i.e. those behind other tiles) + * @param drawHidden true if hidden tiles (i.e. those behind other tiles) * should be drawn */ void RenderTile( Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext, - const CColor& color, bool draw_hidden); + const CColor& color, bool drawHidden); /** * Draw a filled quad on top of the given tile. */ void RenderTile( Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext, - const CColor& color, bool draw_hidden, ssize_t i, ssize_t j); + const CColor& color, bool drawHidden, ssize_t i, ssize_t j); /** * Draw an outlined quad on top of the current tile. * * @param color color to draw. May be transparent (alpha < 1) - * @param line_width width of lines in pixels. 1 is a sensible value - * @param draw_hidden true if hidden tiles (i.e. those behind other tiles) + * @param lineWidth width of lines in pixels. 1 is a sensible value + * @param drawHidden true if hidden tiles (i.e. those behind other tiles) * should be drawn */ void RenderTileOutline( Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext, - const CColor& color, int line_width, bool draw_hidden); + const CColor& color, int lineWidth, bool drawHidden); /** * Draw an outlined quad on top of the given tile. */ void RenderTileOutline( Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext, - const CColor& color, int line_width, bool draw_hidden, ssize_t i, ssize_t j); + const CColor& color, int lineWidth, bool drawHidden, ssize_t i, ssize_t j); private: // Process all tiles diff --git a/source/renderer/TerrainRenderer.cpp b/source/renderer/TerrainRenderer.cpp index 46d4b00434..dbf34b7f39 100644 --- a/source/renderer/TerrainRenderer.cpp +++ b/source/renderer/TerrainRenderer.cpp @@ -265,8 +265,10 @@ void TerrainRenderer::RenderTerrainShader( // render the solid black sides of the map first CShaderTechniquePtr techSolid = g_Renderer.GetShaderManager().LoadEffect(str_solid); techSolid->BeginPass(); - deviceCommandContext->SetGraphicsPipelineState( - techSolid->GetGraphicsPipelineStateDesc()); + Renderer::Backend::GraphicsPipelineStateDesc solidPipelineStateDesc = + techSolid->GetGraphicsPipelineStateDesc(); + solidPipelineStateDesc.rasterizationState.cullMode = Renderer::Backend::CullMode::NONE; + deviceCommandContext->SetGraphicsPipelineState(solidPipelineStateDesc); const CShaderProgramPtr& shaderSolid = techSolid->GetShader(); shaderSolid->Uniform(str_transform, g_Renderer.GetSceneRenderer().GetViewCamera().GetViewProjection()); @@ -299,7 +301,7 @@ void TerrainRenderer::RenderTerrainShader( // Render un-textured patches as polygons void TerrainRenderer::RenderPatches( Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext, - int cullGroup, const CColor& color) + int cullGroup, const CShaderDefines& defines, const CColor& color) { ENSURE(m->phase == Phase_Render); @@ -309,21 +311,22 @@ void TerrainRenderer::RenderPatches( #if CONFIG2_GLES UNUSED2(deviceCommandContext); + UNUSED2(defines); UNUSED2(color); #warning TODO: implement TerrainRenderer::RenderPatches for GLES #else - CShaderTechniquePtr dummyTech = g_Renderer.GetShaderManager().LoadEffect(str_dummy); - dummyTech->BeginPass(); + CShaderTechniquePtr solidTech = g_Renderer.GetShaderManager().LoadEffect(str_terrain_solid, defines); + solidTech->BeginPass(); deviceCommandContext->SetGraphicsPipelineState( - dummyTech->GetGraphicsPipelineStateDesc()); + solidTech->GetGraphicsPipelineStateDesc()); - const CShaderProgramPtr& dummyShader = dummyTech->GetShader(); - dummyShader->Uniform(str_transform, g_Renderer.GetSceneRenderer().GetViewCamera().GetViewProjection()); - dummyShader->Uniform(str_color, color); + const CShaderProgramPtr& solidShader = solidTech->GetShader(); + solidShader->Uniform(str_transform, g_Renderer.GetSceneRenderer().GetViewCamera().GetViewProjection()); + solidShader->Uniform(str_color, color); - CPatchRData::RenderStreams(visiblePatches, dummyShader, STREAM_POS); - dummyTech->EndPass(); + CPatchRData::RenderStreams(visiblePatches, solidShader, STREAM_POS); + solidTech->EndPass(); #endif } @@ -603,12 +606,13 @@ void TerrainRenderer::RenderWaterFoamOccluders( glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LEQUAL); - glDisable(GL_CULL_FACE); // Overwrite waves that would be behind the ground. CShaderTechniquePtr dummyTech = g_Renderer.GetShaderManager().LoadEffect(str_solid); dummyTech->BeginPass(); - deviceCommandContext->SetGraphicsPipelineState( - dummyTech->GetGraphicsPipelineStateDesc()); + Renderer::Backend::GraphicsPipelineStateDesc pipelineStateDesc = + dummyTech->GetGraphicsPipelineStateDesc(); + pipelineStateDesc.rasterizationState.cullMode = Renderer::Backend::CullMode::NONE; + deviceCommandContext->SetGraphicsPipelineState(pipelineStateDesc); const CShaderProgramPtr& dummyShader = dummyTech->GetShader(); dummyShader->Uniform(str_transform, sceneRenderer.GetViewCamera().GetViewProjection()); @@ -617,7 +621,6 @@ void TerrainRenderer::RenderWaterFoamOccluders( data->RenderWaterShore(dummyShader); dummyTech->EndPass(); - glEnable(GL_CULL_FACE); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); } diff --git a/source/renderer/TerrainRenderer.h b/source/renderer/TerrainRenderer.h index 1572a35123..2a9b148269 100644 --- a/source/renderer/TerrainRenderer.h +++ b/source/renderer/TerrainRenderer.h @@ -115,7 +115,8 @@ public: */ void RenderPatches( Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext, - int cullGroup, const CColor& color = CColor(0.0f, 0.0f, 0.0f, 1.0f)); + int cullGroup, const CShaderDefines& defines, + const CColor& color = CColor(0.0f, 0.0f, 0.0f, 1.0f)); /** * RenderOutlines: Render the outline of patches as lines. diff --git a/source/renderer/backend/gl/Device.cpp b/source/renderer/backend/gl/Device.cpp index e4ca278334..6640a4ac0b 100644 --- a/source/renderer/backend/gl/Device.cpp +++ b/source/renderer/backend/gl/Device.cpp @@ -199,9 +199,6 @@ std::unique_ptr CDevice::Create(SDL_Window* window, const bool arb) // Setup default state. glDepthFunc(GL_LEQUAL); glEnable(GL_DEPTH_TEST); - glCullFace(GL_BACK); - glFrontFace(GL_CCW); - glEnable(GL_CULL_FACE); return device; } diff --git a/source/renderer/backend/gl/DeviceCommandContext.cpp b/source/renderer/backend/gl/DeviceCommandContext.cpp index b62dd59613..df2a9dcac8 100644 --- a/source/renderer/backend/gl/DeviceCommandContext.cpp +++ b/source/renderer/backend/gl/DeviceCommandContext.cpp @@ -194,6 +194,32 @@ void CDeviceCommandContext::SetGraphicsPipelineStateImpl( nextBlendStateDesc.constant.a); } + const RasterizationStateDesc& currentRasterizationStateDesc = m_GraphicsPipelineStateDesc.rasterizationState; + const RasterizationStateDesc& nextRasterizationStateDesc = pipelineStateDesc.rasterizationState; + if (force || + currentRasterizationStateDesc.cullMode != nextRasterizationStateDesc.cullMode) + { + if (nextRasterizationStateDesc.cullMode == CullMode::NONE) + { + glDisable(GL_CULL_FACE); + } + else + { + if (force || currentRasterizationStateDesc.cullMode == CullMode::NONE) + glEnable(GL_CULL_FACE); + glCullFace(nextRasterizationStateDesc.cullMode == CullMode::FRONT ? GL_FRONT : GL_BACK); + } + } + + if (force || + currentRasterizationStateDesc.frontFace != nextRasterizationStateDesc.frontFace) + { + if (nextRasterizationStateDesc.frontFace == FrontFace::CLOCKWISE) + glFrontFace(GL_CW); + else + glFrontFace(GL_CCW); + } + m_GraphicsPipelineStateDesc = pipelineStateDesc; }