[colobot] 78/145: Added blur effect when the game is paused (issue #656)

Didier Raboud odyx at moszumanska.debian.org
Mon Jul 11 12:56:19 UTC 2016


This is an automated email from the git hooks/post-receive script.

odyx pushed a commit to branch debian/master
in repository colobot.

commit 213fd6b203c82156fef49e8d77e1a4c719e53a19
Author: Tomasz Kapuściński <tomaszkax86 at gmail.com>
Date:   Sat May 21 14:27:35 2016 +0200

    Added blur effect when the game is paused (issue #656)
    
    Might be unstable, needs more testing. To enable, add PauseBlur=1 to [Experimental] section in colobot.ini
---
 src/common/settings.cpp        |   4 +
 src/graphics/engine/engine.cpp | 175 ++++++++++++++++++++++++++++++++++++++++-
 src/graphics/engine/engine.h   |  17 ++++
 src/level/robotmain.cpp        |   4 +
 src/math/func.h                |   9 +++
 5 files changed, 206 insertions(+), 3 deletions(-)

diff --git a/src/common/settings.cpp b/src/common/settings.cpp
index 2b67ef1..1003984 100644
--- a/src/common/settings.cpp
+++ b/src/common/settings.cpp
@@ -112,6 +112,7 @@ void CSettings::SaveSettings()
 
     // Experimental settings
     GetConfigFile().SetBoolProperty("Experimental", "TerrainShadows", engine->GetTerrainShadows());
+    GetConfigFile().SetBoolProperty("Experimental", "PauseBlur", engine->GetPauseBlur());
 
     CInput::GetInstancePointer()->SaveKeyBindings();
 
@@ -270,6 +271,9 @@ void CSettings::LoadSettings()
     if (GetConfigFile().GetBoolProperty("Experimental", "TerrainShadows", bValue))
         engine->SetTerrainShadows(bValue);
 
+    if (GetConfigFile().GetBoolProperty("Experimental", "PauseBlur", bValue))
+        engine->SetPauseBlur(bValue);
+
     CInput::GetInstancePointer()->LoadKeyBindings();
 
 
diff --git a/src/graphics/engine/engine.cpp b/src/graphics/engine/engine.cpp
index aeb6dcb..b7d0e56 100644
--- a/src/graphics/engine/engine.cpp
+++ b/src/graphics/engine/engine.cpp
@@ -59,6 +59,7 @@
 #include "ui/controls/interface.h"
 
 #include <iomanip>
+#include <SDL_surface.h>
 #include <SDL_thread.h>
 
 template<> Gfx::CEngine* CSingleton<Gfx::CEngine>::m_instance = nullptr;
@@ -148,6 +149,7 @@ CEngine::CEngine(CApplication *app, CSystemUtils* systemUtils)
     m_editIndentMode = true;
     m_editIndentValue = 4;
     m_tracePrecision = 1.0f;
+    m_pauseBlur = false;
 
 
     m_updateGeometry = false;
@@ -3028,6 +3030,16 @@ EngineMouseType CEngine::GetMouseType()
     return m_mouseType;
 }
 
+void CEngine::SetPauseBlur(bool enable)
+{
+    m_pauseBlur = enable;
+}
+
+bool CEngine::GetPauseBlur()
+{
+    return m_pauseBlur;
+}
+
 const Math::Matrix& CEngine::GetMatView()
 {
     return m_matView;
@@ -3066,6 +3078,10 @@ void CEngine::UpdateMatProj()
 void CEngine::ApplyChange()
 {
     SetFocus(m_focus);
+
+    // recapture 3D scene
+    if (m_worldCaptured)
+        m_captureWorld = true;
 }
 
 void CEngine::ClearDisplayCrashSpheres()
@@ -3137,8 +3153,8 @@ void CEngine::Render()
 
     UseMSAA(true);
 
-    DrawBackground();                // draws the background
-
+    if (!m_worldCaptured)
+        DrawBackground();                // draws the background
 
     if (m_drawWorld)
         Draw3DScene();
@@ -3155,6 +3171,33 @@ void CEngine::Render()
 
 void CEngine::Draw3DScene()
 {
+    // use currently captured scene for world
+    if (m_worldCaptured)
+    {
+        Math::Matrix identity;
+
+        m_device->SetTransform(TRANSFORM_PROJECTION, identity);
+        m_device->SetTransform(TRANSFORM_VIEW, identity);
+        m_device->SetTransform(TRANSFORM_WORLD, identity);
+
+        Vertex vertices[4];
+
+        vertices[0] = Vertex(Math::Vector(-1.0f, -1.0f, 0.0f), Math::Vector(0.0f, 1.0f, 0.0f), Math::Point(0.0f, 0.0f));
+        vertices[1] = Vertex(Math::Vector( 1.0f, -1.0f, 0.0f), Math::Vector(0.0f, 1.0f, 0.0f), Math::Point(1.0f, 0.0f));
+        vertices[2] = Vertex(Math::Vector(-1.0f,  1.0f, 0.0f), Math::Vector(0.0f, 1.0f, 0.0f), Math::Point(0.0f, 1.0f));
+        vertices[3] = Vertex(Math::Vector( 1.0f,  1.0f, 0.0f), Math::Vector(0.0f, 1.0f, 0.0f), Math::Point(1.0f, 1.0f));
+
+        m_device->SetRenderState(RENDER_STATE_DEPTH_TEST, false);
+
+        m_device->SetTexture(TEXTURE_PRIMARY, m_capturedWorldTexture);
+        m_device->SetTextureEnabled(TEXTURE_PRIMARY, true);
+        m_device->SetTextureEnabled(TEXTURE_SECONDARY, false);
+
+        m_device->DrawPrimitive(PRIMITIVE_TRIANGLE_STRIP, vertices, 4);
+
+        return;
+    }
+
     m_device->SetRenderState(RENDER_STATE_DEPTH_TEST, false);
 
     UpdateGroundSpotTextures();
@@ -3237,7 +3280,6 @@ void CEngine::Draw3DScene()
     if (!m_shadowMapping)
         DrawShadowSpots();
 
-
     m_app->StopPerformanceCounter(PCNT_RENDER_TERRAIN);
 
     // Draw other objects
@@ -3407,6 +3449,117 @@ void CEngine::Draw3DScene()
     DrawForegroundImage();   // draws the foreground
 
     if (! m_overFront) DrawOverColor();      // draws the foreground color
+
+    // marked to capture currently rendered world
+    if (m_captureWorld)
+    {
+        // destroy existing texture
+        if (m_capturedWorldTexture.Valid())
+        {
+            m_device->DestroyTexture(m_capturedWorldTexture);
+            m_capturedWorldTexture = Texture();
+        }
+
+        // obtain pixels from screen
+        int width = m_size.x;
+        int height = m_size.y;
+
+        auto pixels = m_device->GetFrameBufferPixels();
+        unsigned char* data = reinterpret_cast<unsigned char*>(pixels->GetPixelsData());
+
+        // calculate 2nd mipmap
+        int newWidth = width / 4;
+        int newHeight = height / 4;
+        std::unique_ptr<unsigned char[]> mipmap(new unsigned char[4 * newWidth * newHeight]);
+
+        for (int x = 0; x < newWidth; x++)
+        {
+            for (int y = 0; y < newHeight; y++)
+            {
+                float color[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
+
+                for (int i = 0; i < 4; i++)
+                {
+                    for (int j = 0; j < 4; j++)
+                    {
+                        int index = 4 * ((4 * x + i) + width * (4 * y + j));
+
+                        for (int k = 0; k < 4; k++)
+                            color[k] += data[index + k];
+                    }
+                }
+
+                int index = 4 * (x + newWidth * y);
+
+                for (int k = 0; k < 4; k++)
+                {
+                    mipmap[index + k] = static_cast<unsigned char>(color[k] * (1.0f / 16.0f));
+                }
+            }
+        }
+
+        // calculate Gaussian blur
+        std::unique_ptr<unsigned char[]> blured(new unsigned char[4 * newWidth * newHeight]);
+
+        float matrix[7][7] =
+        {
+            { 0.00000067f, 0.00002292f, 0.00019117f, 0.00038771f, 0.00019117f, 0.00002292f, 0.00000067f },
+            { 0.00002292f, 0.00078634f, 0.00655965f, 0.01330373f, 0.00655965f, 0.00078633f, 0.00002292f },
+            { 0.00019117f, 0.00655965f, 0.05472157f, 0.11098164f, 0.05472157f, 0.00655965f, 0.00019117f },
+            { 0.00038771f, 0.01330373f, 0.11098164f, 0.22508352f, 0.11098164f, 0.01330373f, 0.00038771f },
+            { 0.00019117f, 0.00655965f, 0.05472157f, 0.11098164f, 0.05472157f, 0.00655965f, 0.00019117f },
+            { 0.00002292f, 0.00078633f, 0.00655965f, 0.01330373f, 0.00655965f, 0.00078633f, 0.00002292f },
+            { 0.00000067f, 0.00002292f, 0.00019117f, 0.00038771f, 0.00019117f, 0.00002292f, 0.00000067f }
+        };
+
+        for (int x = 0; x < newWidth; x++)
+        {
+            for (int y = 0; y < newHeight; y++)
+            {
+                float color[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
+
+                for (int i = -3; i <= 3; i++)
+                {
+                    for (int j = -3; j <= 3; j++)
+                    {
+                        int xp = Math::Clamp(x + i, 0, newWidth - 1);
+                        int yp = Math::Clamp(y + j, 0, newHeight - 1);
+
+                        float weight = matrix[i + 3][j + 3];
+
+                        int index = 4 * (newWidth * yp + xp);
+
+                        for (int k = 0; k < 4; k++)
+                            color[k] += weight * mipmap[index + k];
+                    }
+                }
+
+                int index = 4 * (newWidth * y + x);
+
+                for (int k = 0; k < 4; k++)
+                {
+                    float value = Math::Clamp(color[k], 0.0f, 255.0f);
+                    blured[index + k] = static_cast<unsigned char>(value);
+                }
+            }
+        }
+
+        // create SDL surface and final texture
+        ImageData image;
+        image.surface = SDL_CreateRGBSurfaceFrom(blured.get(), newWidth, newHeight, 32, 0, 0, 0, 0, 0xFF000000);
+
+        TextureCreateParams params;
+        params.filter = TEX_FILTER_BILINEAR;
+        params.format = TEX_IMG_RGBA;
+        params.mipmap = false;
+
+        m_capturedWorldTexture = m_device->CreateTexture(&image, params);
+
+        SDL_FreeSurface(image.surface);
+
+        m_captureWorld = false;
+        m_worldCaptured = true;
+    }
 }
 
 void CEngine::DrawCrashSpheres()
@@ -5190,6 +5343,22 @@ void CEngine::SetInterfaceCoordinates()
     m_device->SetTransform(TRANSFORM_WORLD,      m_matWorldInterface);
 }
 
+void CEngine::EnablePauseBlur()
+{
+    if (!m_pauseBlur) return;
+
+    m_captureWorld = true;
+    m_worldCaptured = false;
+}
+
+void CEngine::DisablePauseBlur()
+{
+    if (!m_pauseBlur) return;
+
+    m_captureWorld = false;
+    m_worldCaptured = false;
+}
+
 void CEngine::SetWindowCoordinates()
 {
     Math::Matrix matWorldWindow;
diff --git a/src/graphics/engine/engine.h b/src/graphics/engine/engine.h
index 1f5cfe8..8fb195a 100644
--- a/src/graphics/engine/engine.h
+++ b/src/graphics/engine/engine.h
@@ -1162,6 +1162,12 @@ public:
     EngineMouseType GetMouseType();
     //@}
 
+    //@{
+    //! Management of pause blur
+    void            SetPauseBlur(bool enable);
+    bool            GetPauseBlur();
+    //@}
+
     //! Returns the view matrix
     const Math::Matrix& GetMatView();
     //! Returns the camera center point
@@ -1199,6 +1205,9 @@ public:
     void            SetWindowCoordinates();
     void            SetInterfaceCoordinates();
 
+    void            EnablePauseBlur();
+    void            DisablePauseBlur();
+
 protected:
     //! Resets some states and flushes textures after device was changed (e.g. resoulution changed)
     /** Instead of calling this directly, send EVENT_RESOLUTION_CHANGED event **/
@@ -1408,6 +1417,7 @@ protected:
     float           m_terrainVision;
     bool            m_backForce;
     float           m_tracePrecision;
+    bool            m_pauseBlur;
 
     bool            m_dirty;
     bool            m_fog;
@@ -1502,6 +1512,13 @@ protected:
 
     //! Pause the animation updates
     bool            m_pause = false;
+
+    //! true means that current 3D scene was captured and is not to be rendered again
+    bool            m_worldCaptured = false;
+    //! true means that currently rendered world is to be captured
+    bool            m_captureWorld = false;
+    //! Texture with captured 3D world
+    Texture         m_capturedWorldTexture;
 };
 
 
diff --git a/src/level/robotmain.cpp b/src/level/robotmain.cpp
index e6caa12..e41a060 100644
--- a/src/level/robotmain.cpp
+++ b/src/level/robotmain.cpp
@@ -1601,6 +1601,8 @@ void CRobotMain::StartSuspend()
 
     m_suspendInitCamera = m_camera->GetType();
     m_camera->SetType(Gfx::CAM_TYPE_DIALOG);
+
+    m_engine->EnablePauseBlur();
 }
 
 //! End of dialogue during the game
@@ -1619,6 +1621,8 @@ void CRobotMain::StopSuspend()
     m_displayText->HideText(false);
 
     m_camera->SetType(m_suspendInitCamera);
+
+    m_engine->DisablePauseBlur();
 }
 
 
diff --git a/src/math/func.h b/src/math/func.h
index 66ee974..b206c89 100644
--- a/src/math/func.h
+++ b/src/math/func.h
@@ -93,6 +93,15 @@ inline float Max(float a, float b, float c, float d, float e)
     return Math::Max( Math::Max(a, b), Math::Max(c, d), e );
 }
 
+//! Clamps the value to a range specified by min and max
+template<typename T>
+inline T Clamp(T value, T min, T max)
+{
+    if (value < min) return min;
+    else if (value > max) return max;
+    else return value;
+}
+
 //! Returns the normalized value (0 .. 1)
 inline float Norm(float a)
 {

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