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;
}