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 <[email protected]> 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 _______________________________________________ Pkg-games-commits mailing list [email protected] http://lists.alioth.debian.org/cgi-bin/mailman/listinfo/pkg-games-commits

