[colobot] 372/390: Improved shadow mapping
Didier Raboud
odyx at moszumanska.debian.org
Fri Jun 12 14:22:06 UTC 2015
This is an automated email from the git hooks/post-receive script.
odyx pushed a commit to branch upstream/latest
in repository colobot.
commit 8abdd4b7404e6544bd4d8381d08bfb9488528cef
Author: Tomasz Kapuściński <tomaszkax86 at gmail.com>
Date: Thu May 21 18:18:46 2015 +0200
Improved shadow mapping
---
src/graphics/engine/engine.cpp | 375 ++++++++++++++++++++++-------------------
src/graphics/engine/engine.h | 2 +
2 files changed, 200 insertions(+), 177 deletions(-)
diff --git a/src/graphics/engine/engine.cpp b/src/graphics/engine/engine.cpp
index e839dc0..9f8e129 100644
--- a/src/graphics/engine/engine.cpp
+++ b/src/graphics/engine/engine.cpp
@@ -3239,132 +3239,7 @@ void CEngine::Draw3DScene()
m_lightMan->UpdateDeviceLights(ENG_OBJTYPE_TERRAIN);
- // Enable shadow mapping
- if (m_shadowMapping)
- {
- if (m_qualityShadows)
- {
- if (m_device->GetMaxTextureStageCount() < 6)
- {
- m_qualityShadows = false;
- GetLogger()->Error("Cannot use quality shadow maps, not enough texture units\n");
- GetLogger()->Error("Attempting to use lower quality shadow maps\n");
- }
- else
- {
- // Texture Unit 2
- m_device->SetTextureEnabled(2, true);
- m_device->SetTexture(2, m_shadowMap);
- m_device->SetTransform(TRANSFORM_SHADOW, m_shadowTextureMat);
-
- Math::Matrix identity;
- identity.LoadIdentity();
- m_device->SetTransform(TRANSFORM_WORLD, identity);
-
- float shadowBias = 0.6f;
- float shadowUnbias = 1.0f - shadowBias;
-
- TextureStageParams params;
- params.colorOperation = TEX_MIX_OPER_MODULATE;
- params.colorArg1 = TEX_MIX_ARG_TEXTURE;
- params.colorArg2 = TEX_MIX_ARG_FACTOR;
- params.colorOperation = TEX_MIX_OPER_DEFAULT;
- params.factor = Color(shadowBias, shadowBias, shadowBias, 1.0f);
- params.wrapS = TEX_WRAP_CLAMP_TO_BORDER;
- params.wrapT = TEX_WRAP_CLAMP_TO_BORDER;
-
- m_device->SetTextureStageParams(2, params);
-
- TextureGenerationParams genParams;
-
- for (int i = 0; i < 4; i++)
- {
- genParams.coords[i].mode = TEX_GEN_EYE_LINEAR;
-
- for (int j = 0; j < 4; j++)
- {
- genParams.coords[i].plane[j] = (i == j ? 1.0f : 0.0f);
- }
- }
-
- m_device->SetTextureCoordGeneration(2, genParams);
-
- // Texture Unit 3
- m_device->SetTextureEnabled(3, true);
- m_device->SetTexture(3, m_shadowMap);
-
- params.LoadDefault();
- params.colorOperation = TEX_MIX_OPER_ADD;
- params.colorArg1 = TEX_MIX_ARG_COMPUTED_COLOR;
- params.colorArg2 = TEX_MIX_ARG_FACTOR;
- params.alphaOperation = TEX_MIX_OPER_DEFAULT;
- params.factor = Color(shadowUnbias, shadowUnbias, shadowUnbias, 0.0f);
- params.wrapS = TEX_WRAP_CLAMP_TO_BORDER;
- params.wrapT = TEX_WRAP_CLAMP_TO_BORDER;
-
- m_device->SetTextureStageParams(3, params);
-
- // Texture Unit 4
- m_device->SetTextureEnabled(4, true);
- m_device->SetTexture(4, m_shadowMap);
-
- params.LoadDefault();
- params.colorOperation = TEX_MIX_OPER_MODULATE;
- params.colorArg1 = TEX_MIX_ARG_COMPUTED_COLOR;
- params.colorArg2 = TEX_MIX_ARG_SRC_COLOR;
- params.alphaOperation = TEX_MIX_OPER_DEFAULT;
- params.wrapS = TEX_WRAP_CLAMP_TO_BORDER;
- params.wrapT = TEX_WRAP_CLAMP_TO_BORDER;
-
- m_device->SetTextureStageParams(4, params);
-
- // Texture Unit 5
- m_device->SetTextureEnabled(5, true);
- m_device->SetTexture(5, m_shadowMap);
-
- params.LoadDefault();
- params.colorOperation = TEX_MIX_OPER_MODULATE;
- params.colorArg1 = TEX_MIX_ARG_COMPUTED_COLOR;
- params.colorArg2 = TEX_MIX_ARG_TEXTURE_0;
- params.alphaOperation = TEX_MIX_OPER_DEFAULT;
- params.wrapS = TEX_WRAP_CLAMP_TO_BORDER;
- params.wrapT = TEX_WRAP_CLAMP_TO_BORDER;
-
- m_device->SetTextureStageParams(5, params);
- }
- }
- else // Simpler shadows
- {
- // Texture Unit 2
- m_device->SetTextureEnabled(2, true);
- m_device->SetTexture(2, m_shadowMap);
- m_device->SetTransform(TRANSFORM_SHADOW, m_shadowTextureMat);
-
- Math::Matrix identity;
- identity.LoadIdentity();
- m_device->SetTransform(TRANSFORM_WORLD, identity);
-
- TextureStageParams params;
- params.colorOperation = TEX_MIX_OPER_MODULATE;
- params.wrapS = TEX_WRAP_CLAMP_TO_BORDER;
- params.wrapT = TEX_WRAP_CLAMP_TO_BORDER;
- m_device->SetTextureStageParams(2, params);
-
- TextureGenerationParams genParams;
-
- for (int i = 0; i < 4; i++)
- {
- genParams.coords[i].mode = TEX_GEN_EYE_LINEAR;
-
- for (int j = 0; j < 4; j++)
- {
- genParams.coords[i].plane[j] = (i == j ? 1.0f : 0.0f);
- }
- }
-
- m_device->SetTextureCoordGeneration(2, genParams);
- }
- }
+ UseShadowMapping(true);
for (int objRank = 0; objRank < static_cast<int>(m_objects.size()); objRank++)
{
@@ -3419,35 +3294,7 @@ void CEngine::Draw3DScene()
}
}
- // Disable shadow mapping
- if (m_shadowMapping)
- {
- Math::Matrix identity;
- identity.LoadIdentity();
-
- m_device->SetTexture(2, 0);
- m_device->SetTextureEnabled(2, false);
- m_device->SetTransform(TRANSFORM_SHADOW, identity);
-
- TextureGenerationParams params;
-
- for (int i = 0; i < 4; i++)
- params.coords[i].mode = TEX_GEN_NONE;
-
- m_device->SetTextureCoordGeneration(2, params);
-
- if (m_qualityShadows)
- {
- m_device->SetTexture(3, 0);
- m_device->SetTextureEnabled(3, false);
-
- m_device->SetTexture(4, 0);
- m_device->SetTextureEnabled(4, false);
-
- m_device->SetTexture(5, 0);
- m_device->SetTextureEnabled(5, false);
- }
- }
+ UseShadowMapping(false);
// Draws the shadows , if shadows enabled
if (m_shadowVisible)
@@ -3523,6 +3370,8 @@ void CEngine::Draw3DScene()
}
}
+ UseShadowMapping(false);
+
// Draw transparent objects
if (transparent)
@@ -3609,10 +3458,14 @@ void CEngine::Draw3DScene()
m_app->StopPerformanceCounter(PCNT_RENDER_WATER);
}
+ m_device->SetRenderState(RENDER_STATE_LIGHTING, false);
+
m_app->StartPerformanceCounter(PCNT_RENDER_PARTICLE);
m_particle->DrawParticle(SH_WORLD); // draws the particles of the 3D world
m_app->StopPerformanceCounter(PCNT_RENDER_PARTICLE);
+ m_device->SetRenderState(RENDER_STATE_LIGHTING, true);
+
m_lightning->Draw(); // draws lightning
if (m_lensMode) DrawForegroundImage(); // draws the foreground
@@ -3629,6 +3482,7 @@ void CEngine::RenderShadowMap()
m_shadowMapping = false;
GetLogger()->Error("Cannot use shadow maps, not enough texture units\n");
GetLogger()->Error("Disabling shadow mapping\n");
+ return;
}
m_app->StartPerformanceCounter(PCNT_RENDER_SHADOW_MAP);
@@ -3650,7 +3504,7 @@ void CEngine::RenderShadowMap()
}
else
{
- width = height = 2048;
+ width = height = 1024;
}
}
else
@@ -3678,6 +3532,7 @@ void CEngine::RenderShadowMap()
if (m_offscreenShadowRendering)
{
m_device->SetRenderState(RENDER_STATE_OFFSCREEN_RENDERING, true);
+ m_device->SetRenderTexture(RENDER_TARGET_DEPTH, m_shadowMap.id);
}
m_device->Clear();
@@ -3691,23 +3546,34 @@ void CEngine::RenderShadowMap()
m_device->SetRenderState(RENDER_STATE_FOG, false);
m_device->SetRenderState(RENDER_STATE_CULLING, false);
m_device->SetRenderState(RENDER_STATE_ALPHA_TEST, true);
+ m_device->SetRenderState(RENDER_STATE_DEPTH_BIAS, false);
+ m_device->SetAlphaTestFunc(COMP_FUNC_GREATER, 0.5f);
m_device->SetViewport(0, 0, m_shadowMap.size.x, m_shadowMap.size.y);
// recompute matrices
- Math::Vector worldUp(1.0f, 0.0f, 0.0f);
+ Math::Vector worldUp(0.0f, 1.0f, 0.0f);
+ Math::Vector lightDir = Math::Vector(1.0f, 1.0f, -1.0f);
Math::Vector dir = m_lookatPt - m_eyePt;
dir.Normalize();
- Math::Vector pos = m_lookatPt + 40.0f * dir;
- Math::Vector lightPos = pos + Math::Vector(3.0f, 30.0f, 3.0f);
- Math::Vector lookAt = pos + Math::Vector(0.0, 100.0f, 0.0f);
+ float dist = 50.0f * (log(m_shadowMap.size.x) / log(2.0f) - 6.5f);
+ float depth = 800.0f;
- float dist = 75.0f;
+ Math::Vector pos = m_lookatPt + 0.5f * dist * dir + 0.5f * dist * Math::Vector(1.0f, 0.0f, -1.0f);
- if (m_offscreenShadowRendering) dist = 400.0f;
+ Math::Vector lightPos = pos + Math::Vector(0.0f, 30.0f, 0.0f);
+ Math::Vector lookAt = lightPos + lightDir;
- Math::LoadOrthoProjectionMatrix(m_shadowProjMat, -dist, dist, -dist, dist, -200.0f, 200.0f);
+ lightPos.x = round(lightPos.x);
+ lightPos.y = round(lightPos.y);
+ lightPos.z = round(lightPos.z);
+
+ lookAt.x = round(lookAt.x);
+ lookAt.y = round(lookAt.y);
+ lookAt.z = round(lookAt.z);
+
+ Math::LoadOrthoProjectionMatrix(m_shadowProjMat, -dist, dist, -dist, dist, -depth, depth);
Math::LoadViewMatrix(m_shadowViewMat, lightPos, lookAt, worldUp);
Math::Matrix temporary = Math::MultiplyMatrices(m_shadowProjMat, m_shadowViewMat);
@@ -3719,10 +3585,6 @@ void CEngine::RenderShadowMap()
m_device->SetTexture(0, 0);
m_device->SetTexture(1, 0);
- //m_device->SetCullMode(CULL_CW);
- //m_device->SetRenderState(RENDER_STATE_DEPTH_BIAS, true);
- //m_device->SetDepthBias(2.0f, 4.0f);
-
// render objects into shadow map
for (int objRank = 0; objRank < static_cast<int>(m_objects.size()); objRank++)
{
@@ -3732,9 +3594,6 @@ void CEngine::RenderShadowMap()
if (m_objects[objRank].type == ENG_OBJTYPE_TERRAIN)
continue;
- //if (!m_objects[objRank].drawWorld)
- // continue;
-
m_device->SetTransform(TRANSFORM_WORLD, m_objects[objRank].transform);
// TODO: check proper object filtering
@@ -3770,8 +3629,8 @@ void CEngine::RenderShadowMap()
{
EngineBaseObjDataTier& p4 = p3.next[l4];
- //if (m_objects[objRank].transparency != 0.0f) // transparent ?
- // continue;
+ if (m_objects[objRank].transparency != 0.0f) // transparent ?
+ continue;
DrawObject(p4);
}
@@ -3779,16 +3638,19 @@ void CEngine::RenderShadowMap()
}
}
- //m_device->SetRenderState(RENDER_STATE_DEPTH_BIAS, false);
+ m_device->SetRenderState(RENDER_STATE_DEPTH_BIAS, false);
+ m_device->SetDepthBias(1.0f, 0.0f);
m_device->SetRenderState(RENDER_STATE_ALPHA_TEST, false);
- // copy depth buffer to shadow map
- m_device->CopyFramebufferToTexture(m_shadowMap, 0, 0, 0, 0, m_shadowMap.size.x, m_shadowMap.size.y);
-
- if (m_offscreenShadowRendering)
+ if (m_offscreenShadowRendering) // shadow map texture already have depth information, just unbind it
{
+ m_device->SetRenderTexture(RENDER_TARGET_DEPTH, 0);
m_device->SetRenderState(RENDER_STATE_OFFSCREEN_RENDERING, false);
}
+ else // copy depth buffer to shadow map
+ {
+ m_device->CopyFramebufferToTexture(m_shadowMap, 0, 0, 0, 0, m_shadowMap.size.x, m_shadowMap.size.y);
+ }
// restore default state
m_device->SetViewport(0, 0, m_size.x, m_size.y);
@@ -3801,6 +3663,165 @@ void CEngine::RenderShadowMap()
m_device->SetRenderState(RENDER_STATE_DEPTH_TEST, false);
}
+void CEngine::UseShadowMapping(bool enable)
+{
+ if (!m_shadowMapping) return;
+
+ if (enable) // Enable shadow mapping
+ {
+ if (m_qualityShadows)
+ {
+ if (m_device->GetMaxTextureStageCount() < 6)
+ {
+ m_qualityShadows = false;
+ GetLogger()->Error("Cannot use quality shadow maps, not enough texture units\n");
+ GetLogger()->Error("Attempting to use lower quality shadow maps\n");
+ }
+ else
+ {
+ // Texture Unit 2
+ m_device->SetTextureEnabled(2, true);
+ m_device->SetTexture(2, m_shadowMap);
+ m_device->SetTransform(TRANSFORM_SHADOW, m_shadowTextureMat);
+
+ Math::Matrix identity;
+ identity.LoadIdentity();
+ m_device->SetTransform(TRANSFORM_WORLD, identity);
+
+ float shadowBias = 0.6f;
+ float shadowUnbias = 1.0f - shadowBias;
+
+ TextureStageParams params;
+ params.colorOperation = TEX_MIX_OPER_MODULATE;
+ params.colorArg1 = TEX_MIX_ARG_TEXTURE;
+ params.colorArg2 = TEX_MIX_ARG_FACTOR;
+ params.colorOperation = TEX_MIX_OPER_DEFAULT;
+ params.factor = Color(shadowBias, shadowBias, shadowBias, 1.0f);
+ params.wrapS = TEX_WRAP_CLAMP_TO_BORDER;
+ params.wrapT = TEX_WRAP_CLAMP_TO_BORDER;
+
+ m_device->SetTextureStageParams(2, params);
+
+ TextureGenerationParams genParams;
+
+ for (int i = 0; i < 4; i++)
+ {
+ genParams.coords[i].mode = TEX_GEN_EYE_LINEAR;
+
+ for (int j = 0; j < 4; j++)
+ {
+ genParams.coords[i].plane[j] = (i == j ? 1.0f : 0.0f);
+ }
+ }
+
+ m_device->SetTextureCoordGeneration(2, genParams);
+
+ // Texture Unit 3
+ m_device->SetTextureEnabled(3, true);
+ m_device->SetTexture(3, m_shadowMap);
+
+ params.LoadDefault();
+ params.colorOperation = TEX_MIX_OPER_ADD;
+ params.colorArg1 = TEX_MIX_ARG_COMPUTED_COLOR;
+ params.colorArg2 = TEX_MIX_ARG_FACTOR;
+ params.alphaOperation = TEX_MIX_OPER_DEFAULT;
+ params.factor = Color(shadowUnbias, shadowUnbias, shadowUnbias, 0.0f);
+ params.wrapS = TEX_WRAP_CLAMP_TO_BORDER;
+ params.wrapT = TEX_WRAP_CLAMP_TO_BORDER;
+
+ m_device->SetTextureStageParams(3, params);
+
+ // Texture Unit 4
+ m_device->SetTextureEnabled(4, true);
+ m_device->SetTexture(4, m_shadowMap);
+
+ params.LoadDefault();
+ params.colorOperation = TEX_MIX_OPER_MODULATE;
+ params.colorArg1 = TEX_MIX_ARG_COMPUTED_COLOR;
+ params.colorArg2 = TEX_MIX_ARG_SRC_COLOR;
+ params.alphaOperation = TEX_MIX_OPER_DEFAULT;
+ params.wrapS = TEX_WRAP_CLAMP_TO_BORDER;
+ params.wrapT = TEX_WRAP_CLAMP_TO_BORDER;
+
+ m_device->SetTextureStageParams(4, params);
+
+ // Texture Unit 5
+ m_device->SetTextureEnabled(5, true);
+ m_device->SetTexture(5, m_shadowMap);
+
+ params.LoadDefault();
+ params.colorOperation = TEX_MIX_OPER_MODULATE;
+ params.colorArg1 = TEX_MIX_ARG_COMPUTED_COLOR;
+ params.colorArg2 = TEX_MIX_ARG_TEXTURE_0;
+ params.alphaOperation = TEX_MIX_OPER_DEFAULT;
+ params.wrapS = TEX_WRAP_CLAMP_TO_BORDER;
+ params.wrapT = TEX_WRAP_CLAMP_TO_BORDER;
+
+ m_device->SetTextureStageParams(5, params);
+ }
+ }
+ else // Simpler shadows
+ {
+ // Texture Unit 2
+ m_device->SetTextureEnabled(2, true);
+ m_device->SetTexture(2, m_shadowMap);
+ m_device->SetTransform(TRANSFORM_SHADOW, m_shadowTextureMat);
+
+ Math::Matrix identity;
+ identity.LoadIdentity();
+ m_device->SetTransform(TRANSFORM_WORLD, identity);
+
+ TextureStageParams params;
+ params.colorOperation = TEX_MIX_OPER_MODULATE;
+ params.wrapS = TEX_WRAP_CLAMP_TO_BORDER;
+ params.wrapT = TEX_WRAP_CLAMP_TO_BORDER;
+ m_device->SetTextureStageParams(2, params);
+
+ TextureGenerationParams genParams;
+
+ for (int i = 0; i < 4; i++)
+ {
+ genParams.coords[i].mode = TEX_GEN_EYE_LINEAR;
+
+ for (int j = 0; j < 4; j++)
+ {
+ genParams.coords[i].plane[j] = (i == j ? 1.0f : 0.0f);
+ }
+ }
+
+ m_device->SetTextureCoordGeneration(2, genParams);
+ }
+ }
+ else // Disable shadow mapping
+ {
+ Math::Matrix identity;
+ identity.LoadIdentity();
+
+ m_device->SetTexture(2, 0);
+ m_device->SetTextureEnabled(2, false);
+ m_device->SetTransform(TRANSFORM_SHADOW, identity);
+
+ TextureGenerationParams params;
+
+ for (int i = 0; i < 4; i++)
+ params.coords[i].mode = TEX_GEN_NONE;
+
+ m_device->SetTextureCoordGeneration(2, params);
+
+ if (m_qualityShadows)
+ {
+ m_device->SetTexture(3, 0);
+ m_device->SetTextureEnabled(3, false);
+
+ m_device->SetTexture(4, 0);
+ m_device->SetTextureEnabled(4, false);
+
+ m_device->SetTexture(5, 0);
+ m_device->SetTextureEnabled(5, false);
+ }
+ }
+}
+
void CEngine::DrawObject(const EngineBaseObjDataTier& p4)
{
if (p4.staticBufferId != 0)
diff --git a/src/graphics/engine/engine.h b/src/graphics/engine/engine.h
index 05f4130..bbfa0c6 100644
--- a/src/graphics/engine/engine.h
+++ b/src/graphics/engine/engine.h
@@ -1235,6 +1235,8 @@ protected:
void Draw3DScene();
//! Renders shadow map
void RenderShadowMap();
+ //! Enables or disables shadow mapping
+ void UseShadowMapping(bool enable);
//! Draw 3D object
void DrawObject(const EngineBaseObjDataTier& p4);
//! Draws the user interface over the scene
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-games/colobot.git
More information about the Pkg-games-commits
mailing list