[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