Index: binaries/data/mods/public/shaders/effects/dummy.xml =================================================================== --- binaries/data/mods/public/shaders/effects/dummy.xml +++ binaries/data/mods/public/shaders/effects/dummy.xml @@ -1,11 +1,11 @@ - - - - - - - - + + + + + + + + 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 @@ -2,6 +2,22 @@ + + + + + + + + + + + + + + + + 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 @@ -1,83 +1,132 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Index: binaries/data/mods/public/shaders/effects/terrain_base.xml =================================================================== --- binaries/data/mods/public/shaders/effects/terrain_base.xml +++ binaries/data/mods/public/shaders/effects/terrain_base.xml @@ -1,14 +1,30 @@ - - - - + + + + + + + - - - - + + + + + + + + + + + + + + + + + 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 @@ -1,14 +1,30 @@ - - - - + + + + + + + - - - - + + + + + + + + + + + + + + + + + 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 @@ -1,14 +1,30 @@ - - - - + + + + + + + - - - - + + + + + + + + + + + + + + + + + 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 @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Index: source/graphics/ShaderManager.cpp =================================================================== --- source/graphics/ShaderManager.cpp +++ source/graphics/ShaderManager.cpp @@ -352,6 +352,7 @@ #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 @@ AT(constant); AT(context); AT(dst); + AT(front_face); AT(func); + AT(mode); AT(op); AT(shader); AT(shaders); @@ -491,6 +494,19 @@ LOGERROR("Failed to parse blend constant: %s", Element.GetAttributes().GetNamedItem(at_constant).c_str()); } + } + } + 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) Index: source/ps/CStrInternStatic.h =================================================================== --- source/ps/CStrInternStatic.h +++ source/ps/CStrInternStatic.h @@ -56,6 +56,9 @@ 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(solid) X(sunColor) X(sunDir) +X(terrain_solid) X(tex) X(texSize) X(textureTransform) Index: source/renderer/DebugRenderer.cpp =================================================================== --- source/renderer/DebugRenderer.cpp +++ source/renderer/DebugRenderer.cpp @@ -55,6 +55,7 @@ } else pipelineStateDesc.blendState.enabled = false; + pipelineStateDesc.rasterizationState.cullMode = Renderer::Backend::CullMode::NONE; deviceCommandContext->SetGraphicsPipelineState(pipelineStateDesc); } Index: source/renderer/PatchRData.cpp =================================================================== --- source/renderer/PatchRData.cpp +++ source/renderer/PatchRData.cpp @@ -1133,8 +1133,6 @@ { PROFILE3("render terrain sides"); - glDisable(GL_CULL_FACE); - CVertexBuffer* lastVB = nullptr; for (CPatchRData* patch : patches) { @@ -1161,8 +1159,6 @@ } CVertexBuffer::Unbind(); - - glEnable(GL_CULL_FACE); } void CPatchRData::RenderPriorities(CTextRenderer& textRenderer) Index: source/renderer/SceneRenderer.h =================================================================== --- source/renderer/SceneRenderer.h +++ source/renderer/SceneRenderer.h @@ -208,7 +208,7 @@ 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, Index: source/renderer/SceneRenderer.cpp =================================================================== --- source/renderer/SceneRenderer.cpp +++ source/renderer/SceneRenderer.cpp @@ -308,7 +308,10 @@ 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 @@ 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 @@ { 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 @@ 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::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 @@ } #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 @@ 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 @@ 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 @@ } 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 @@ 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 @@ { 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 @@ 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 @@ 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 @@ #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 @@ 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 Index: source/renderer/ShadowMap.cpp =================================================================== --- source/renderer/ShadowMap.cpp +++ source/renderer/ShadowMap.cpp @@ -727,7 +727,6 @@ 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 @@ g_Renderer.GetDebugRenderer().DrawBrushOutline(frustumBrush, CColor(1.0f, 0.0f, 0.0f, 0.5f)); } - glEnable(GL_CULL_FACE); glDepthMask(1); ogl_WarnIfError(); Index: source/renderer/SilhouetteRenderer.cpp =================================================================== --- source/renderer/SilhouetteRenderer.cpp +++ source/renderer/SilhouetteRenderer.cpp @@ -451,7 +451,6 @@ 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 @@ 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 @@ shaderTech->EndPass(); - glEnable(GL_CULL_FACE); glDepthMask(1); } Index: source/renderer/TerrainOverlay.h =================================================================== --- source/renderer/TerrainOverlay.h +++ source/renderer/TerrainOverlay.h @@ -136,38 +136,38 @@ * 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 Index: source/renderer/TerrainOverlay.cpp =================================================================== --- source/renderer/TerrainOverlay.cpp +++ source/renderer/TerrainOverlay.cpp @@ -151,7 +151,6 @@ 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::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 @@ 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,24 +257,22 @@ 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 @@ -289,8 +286,8 @@ 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 @@ 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 @@ overlayTech->EndPass(); - if (line_width != 1) + if (lineWidth != 1) glLineWidth(1.0f); #endif } Index: source/renderer/TerrainRenderer.h =================================================================== --- source/renderer/TerrainRenderer.h +++ source/renderer/TerrainRenderer.h @@ -115,7 +115,8 @@ */ 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. Index: source/renderer/TerrainRenderer.cpp =================================================================== --- source/renderer/TerrainRenderer.cpp +++ source/renderer/TerrainRenderer.cpp @@ -265,8 +265,10 @@ // 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 @@ // 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); @@ -313,17 +315,17 @@ #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 +605,13 @@ 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 +620,6 @@ data->RenderWaterShore(dummyShader); dummyTech->EndPass(); - glEnable(GL_CULL_FACE); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); } Index: source/renderer/backend/PipelineState.h =================================================================== --- source/renderer/backend/PipelineState.h +++ source/renderer/backend/PipelineState.h @@ -74,10 +74,30 @@ CColor constant; }; +enum class CullMode +{ + NONE, + FRONT, + BACK +}; + +enum class FrontFace +{ + COUNTER_CLOCKWISE, + CLOCKWISE +}; + +struct RasterizationStateDesc +{ + CullMode cullMode; + FrontFace frontFace; +}; + // TODO: Add a shader program to the graphics pipeline state. struct GraphicsPipelineStateDesc { BlendStateDesc blendState; + RasterizationStateDesc rasterizationState; }; // We don't provide additional helpers intentionally because all custom states @@ -86,6 +106,9 @@ BlendFactor ParseBlendFactor(const CStr& str); BlendOp ParseBlendOp(const CStr& str); + +CullMode ParseCullMode(const CStr& str); +FrontFace ParseFrontFace(const CStr& str); } // namespace Backend Index: source/renderer/backend/PipelineState.cpp =================================================================== --- source/renderer/backend/PipelineState.cpp +++ source/renderer/backend/PipelineState.cpp @@ -28,6 +28,7 @@ GraphicsPipelineStateDesc MakeDefaultGraphicsPipelineStateDesc() { GraphicsPipelineStateDesc desc{}; + desc.blendState.enabled = false; desc.blendState.srcColorBlendFactor = desc.blendState.srcAlphaBlendFactor = BlendFactor::ONE; @@ -35,6 +36,9 @@ BlendFactor::ZERO; desc.blendState.colorBlendOp = desc.blendState.alphaBlendOp = BlendOp::ADD; desc.blendState.constant = CColor(0.0f, 0.0f, 0.0f, 0.0f); + + desc.rasterizationState.cullMode = CullMode::BACK; + desc.rasterizationState.frontFace = FrontFace::COUNTER_CLOCKWISE; return desc; } @@ -77,6 +81,22 @@ #undef CASE debug_warn("Invalid blend op"); return BlendOp::ADD; +} + +CullMode ParseCullMode(const CStr& str) +{ + if (str == "NONE") + return CullMode::NONE; + else if (str == "FRONT") + return CullMode::FRONT; + return CullMode::BACK; +} + +FrontFace ParseFrontFace(const CStr& str) +{ + if (str == "CLOCKWISE") + return FrontFace::CLOCKWISE; + return FrontFace::COUNTER_CLOCKWISE; } } // namespace Backend Index: source/renderer/backend/gl/Device.cpp =================================================================== --- source/renderer/backend/gl/Device.cpp +++ source/renderer/backend/gl/Device.cpp @@ -199,9 +199,6 @@ // Setup default state. glDepthFunc(GL_LEQUAL); glEnable(GL_DEPTH_TEST); - glCullFace(GL_BACK); - glFrontFace(GL_CCW); - glEnable(GL_CULL_FACE); return device; } Index: source/renderer/backend/gl/DeviceCommandContext.cpp =================================================================== --- source/renderer/backend/gl/DeviceCommandContext.cpp +++ source/renderer/backend/gl/DeviceCommandContext.cpp @@ -194,6 +194,33 @@ 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; }