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

odyx pushed a commit to branch upstream/latest
in repository colobot.

commit 2665847c413b289dfb230d3ba97accb749fc52f2
Author: Tomasz Kapuściński <tomaszka...@gmail.com>
Date:   Tue May 12 13:09:31 2015 +0200

    Added support for offscreen rendering and high resolution shadow maps
---
 src/graphics/core/device.h       |  6 ++-
 src/graphics/core/nulldevice.cpp |  4 ++
 src/graphics/core/nulldevice.h   |  2 +
 src/graphics/core/texture.h      |  8 ++++
 src/graphics/engine/engine.cpp   | 51 ++++++++++++++++-----
 src/graphics/engine/engine.h     |  4 +-
 src/graphics/opengl/gldevice.cpp | 96 ++++++++++++++++++++++++++++++++++++++++
 src/graphics/opengl/gldevice.h   | 15 +++++++
 8 files changed, 171 insertions(+), 15 deletions(-)

diff --git a/src/graphics/core/device.h b/src/graphics/core/device.h
index 16b32b3..ba8db6d 100644
--- a/src/graphics/core/device.h
+++ b/src/graphics/core/device.h
@@ -107,7 +107,8 @@ enum RenderState
     RENDER_STATE_DEPTH_WRITE,
     RENDER_STATE_ALPHA_TEST,
     RENDER_STATE_CULLING,
-    RENDER_STATE_DEPTH_BIAS
+    RENDER_STATE_DEPTH_BIAS,
+    RENDER_STATE_OFFSCREEN_RENDERING
 };
 
 /**
@@ -380,6 +381,9 @@ public:
     //! Sets the current fill mode
     virtual void SetFillMode(FillMode mode) = 0;
 
+    //! Initializes offscreen buffer
+    virtual void InitOffscreenBuffer(int width, int height) = 0;
+
     //! Copies content of framebuffer to texture
     virtual void CopyFramebufferToTexture(Texture& texture, int xOffset, int 
yOffset, int x, int y, int width, int height) = 0;
 
diff --git a/src/graphics/core/nulldevice.cpp b/src/graphics/core/nulldevice.cpp
index 869bb89..4ab69d1 100644
--- a/src/graphics/core/nulldevice.cpp
+++ b/src/graphics/core/nulldevice.cpp
@@ -355,6 +355,10 @@ FillMode CNullDevice::GetFillMode()
     return FILL_POINT;
 }
 
+void CNullDevice::InitOffscreenBuffer(int width, int height)
+{
+}
+
 void CNullDevice::CopyFramebufferToTexture(Texture& texture, int xOffset, int 
yOffset, int x, int y, int width, int height)
 {
 }
diff --git a/src/graphics/core/nulldevice.h b/src/graphics/core/nulldevice.h
index a80c5fa..9dea04a 100644
--- a/src/graphics/core/nulldevice.h
+++ b/src/graphics/core/nulldevice.h
@@ -139,6 +139,8 @@ public:
     virtual void SetFillMode(FillMode mode) ;
     virtual FillMode GetFillMode();
 
+    virtual void InitOffscreenBuffer(int width, int height);
+
     virtual void CopyFramebufferToTexture(Texture& texture, int xOffset, int 
yOffset, int x, int y, int width, int height);
     
     virtual void* GetFrameBufferPixels() const;
diff --git a/src/graphics/core/texture.h b/src/graphics/core/texture.h
index 70fc845..49d3610 100644
--- a/src/graphics/core/texture.h
+++ b/src/graphics/core/texture.h
@@ -128,6 +128,14 @@ enum TexMixArgument
 {
     //! Color from current texture
     TEX_MIX_ARG_TEXTURE,
+    //! Color from texture unit 0
+    TEX_MIX_ARG_TEXTURE_0,
+    //! Color from texture unit 1
+    TEX_MIX_ARG_TEXTURE_1,
+    //! Color from texture unit 2
+    TEX_MIX_ARG_TEXTURE_2,
+    //! Color from texture unit 3
+    TEX_MIX_ARG_TEXTURE_3,
     //! Color computed by previous texture unit (current in DirectX; previous 
in OpenGL)
     TEX_MIX_ARG_COMPUTED_COLOR,
     //! (Source) color of textured fragment (diffuse in DirectX; primary color 
in OpenGL)
diff --git a/src/graphics/engine/engine.cpp b/src/graphics/engine/engine.cpp
index 5009254..b0c8f6d 100644
--- a/src/graphics/engine/engine.cpp
+++ b/src/graphics/engine/engine.cpp
@@ -117,7 +117,7 @@ CEngine::CEngine(CApplication *app)
     m_textureMipmapLevel = 1;
     m_textureAnisotropy = 1;
     m_shadowMapping = false;
-    m_npotShadowMap = false;
+    m_offscreenShadowRendering = false;
     m_totoMode = true;
     m_lensMode = true;
     m_waterMode = true;
@@ -186,7 +186,7 @@ CEngine::CEngine(CApplication *app)
     if (CProfile::GetInstance().GetIntProperty("Setup", "ShadowMapping", 
value))
     {
         m_shadowMapping = (value > 0);
-        m_npotShadowMap = (value > 1);
+        m_offscreenShadowRendering = (value > 1);
     }
 
     m_defaultTexParams.format = TEX_IMG_AUTO;
@@ -3336,6 +3336,9 @@ void CEngine::Draw3DScene()
             params.coords[i].mode = TEX_GEN_NONE;
 
         m_device->SetTextureCoordGeneration(2, params);
+
+        m_device->SetTexture(3, 0);
+        m_device->SetTextureEnabled(3, false);
     }
 
         // Draws the shadows , if shadows enabled
@@ -3515,8 +3518,6 @@ void CEngine::RenderShadowMap()
 
     m_app->StartPerformanceCounter(PCNT_RENDER_SHADOW_MAP);
 
-    m_device->Clear();
-
     // If no shadow map texture exists, create it
     if (m_shadowMap.id == 0)
     {
@@ -3524,9 +3525,18 @@ void CEngine::RenderShadowMap()
 
         int depth = m_app->GetInstance().GetVideoConfig().depthSize;
 
-        if (m_npotShadowMap)
+        if (m_offscreenShadowRendering)
         {
-            width = height = Math::Min(m_size.x, m_size.y);
+            int size;
+
+            if (CProfile::GetInstance().GetIntProperty("Setup", 
"OffscreenBuffer", size))
+            {
+                width = height = size;
+            }
+            else
+            {
+                width = height = 2048;
+            }
         }
         else
         {
@@ -3542,12 +3552,23 @@ void CEngine::RenderShadowMap()
 
         m_shadowMap = m_device->CreateDepthTexture(width, height, depth);
 
+        if (m_offscreenShadowRendering)
+        {
+            m_device->InitOffscreenBuffer(width, height);
+        }
+
         GetLogger()->Info("Created shadow map texture: %dx%d, depth %d\n", 
width, height, depth);
     }
 
+    if (m_offscreenShadowRendering)
+    {
+        m_device->SetRenderState(RENDER_STATE_OFFSCREEN_RENDERING, true);
+    }
+
+    m_device->Clear();
+
     // change state to rendering shadow maps
     m_device->SetColorMask(false, false, false, false);
-    //m_device->SetDepthTestFunc(COMP_FUNC_LEQUAL);
     m_device->SetRenderState(RENDER_STATE_DEPTH_TEST, true);
     m_device->SetRenderState(RENDER_STATE_DEPTH_WRITE, true);
     m_device->SetRenderState(RENDER_STATE_BLENDING, false);
@@ -3561,16 +3582,18 @@ void CEngine::RenderShadowMap()
     // recompute matrices
     Math::Vector worldUp(1.0f, 0.0f, 0.0f);
     Math::Vector dir = m_lookatPt - m_eyePt;
-    float change = Math::Max(1.0f, dir.Length() / 25.0f);
+    float change = Math::Max(0.5f, (5.0f + dir.Length()) / 25.0f);
     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 = 75.0f; // *change;
+    float dist = 75.0f * change;
+
+    if (m_offscreenShadowRendering) dist = 400.0f * change;
 
-    Math::LoadOrthoProjectionMatrix(m_shadowProjMat, -dist, dist, -dist, dist, 
-50.0f, 50.0f);
+    Math::LoadOrthoProjectionMatrix(m_shadowProjMat, -dist, dist, -dist, dist, 
-200.0f, 200.0f);
     Math::LoadViewMatrix(m_shadowViewMat, lightPos, lookAt, worldUp);
 
     Math::Matrix temporary = Math::MultiplyMatrices(m_shadowProjMat, 
m_shadowViewMat);
@@ -3642,12 +3665,16 @@ void CEngine::RenderShadowMap()
         }
     }
 
-    m_device->SetCullMode(CULL_CCW);
-    m_device->SetRenderState(RENDER_STATE_DEPTH_BIAS, false);
+    //m_device->SetRenderState(RENDER_STATE_DEPTH_BIAS, 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)
+    {
+        m_device->SetRenderState(RENDER_STATE_OFFSCREEN_RENDERING, false);
+    }
+
     // restore default state
     m_device->SetViewport(0, 0, m_size.x, m_size.y);
 
diff --git a/src/graphics/engine/engine.h b/src/graphics/engine/engine.h
index 5a5533b..8e4e4f3 100644
--- a/src/graphics/engine/engine.h
+++ b/src/graphics/engine/engine.h
@@ -1457,8 +1457,8 @@ protected:
     int m_textureAnisotropy;
     //! true if shadow mapping enabled
     bool m_shadowMapping;
-    //! Override for NPOT shadow map texture
-    bool m_npotShadowMap;
+    //! true enables offscreen shadow rendering
+    bool m_offscreenShadowRendering;
 
     //! Map of loaded textures (by name)
     std::map<std::string, Texture> m_texNameMap;
diff --git a/src/graphics/opengl/gldevice.cpp b/src/graphics/opengl/gldevice.cpp
index 87ab61b..541bfd4 100644
--- a/src/graphics/opengl/gldevice.cpp
+++ b/src/graphics/opengl/gldevice.cpp
@@ -75,6 +75,10 @@ CGLDevice::CGLDevice(const GLDeviceConfig &config)
     m_glMajor = 1;
     m_glMinor = 1;
     m_shadowMappingSupport = SMS_NONE;
+
+    m_framebuffer = 0;
+    m_colorBuffer = 0;
+    m_depthBuffer = 0;
 }
 
 
@@ -217,6 +221,15 @@ bool CGLDevice::Create()
         if (!m_multitextureAvailable)
             GetLogger()->Warn("GLEW reports multitexturing not supported - 
graphics quality will be degraded!\n");
 
+        m_framebufferObject = glewIsSupported("GL_EXT_framebuffer_object");
+        if (m_framebufferObject)
+        {
+            glGetIntegerv(GL_MAX_RENDERBUFFER_SIZE_EXT, 
&m_maxRenderbufferSize);
+
+            GetLogger()->Info("Offscreen rendering available\n");
+            GetLogger()->Info("Maximum renderbuffer size: %d\n", 
m_maxRenderbufferSize);
+        }
+
         // Detect Shadow mapping support
         if (m_glMajor >= 2 || m_glMinor >= 4)     // Core depth 
texture+shadow, OpenGL 1.4+
         {
@@ -1054,6 +1067,14 @@ void CGLDevice::UpdateTextureParams(int index)
     // Color arg1
     if (params.colorArg1 == TEX_MIX_ARG_TEXTURE)
         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_TEXTURE);
+    else if (params.colorArg1 == TEX_MIX_ARG_TEXTURE_0)
+        glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_TEXTURE0);
+    else if (params.colorArg1 == TEX_MIX_ARG_TEXTURE_1)
+        glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_TEXTURE1);
+    else if (params.colorArg1 == TEX_MIX_ARG_TEXTURE_2)
+        glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_TEXTURE2);
+    else if (params.colorArg1 == TEX_MIX_ARG_TEXTURE_3)
+        glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_TEXTURE3);
     else if (params.colorArg1 == TEX_MIX_ARG_COMPUTED_COLOR)
         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_PREVIOUS);
     else if (params.colorArg1 == TEX_MIX_ARG_SRC_COLOR)
@@ -1065,6 +1086,14 @@ void CGLDevice::UpdateTextureParams(int index)
     // Color arg2
     if (params.colorArg2 == TEX_MIX_ARG_TEXTURE)
         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_TEXTURE);
+    else if (params.colorArg2 == TEX_MIX_ARG_TEXTURE_0)
+        glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_TEXTURE0);
+    else if (params.colorArg2 == TEX_MIX_ARG_TEXTURE_1)
+        glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_TEXTURE1);
+    else if (params.colorArg2 == TEX_MIX_ARG_TEXTURE_2)
+        glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_TEXTURE2);
+    else if (params.colorArg2 == TEX_MIX_ARG_TEXTURE_3)
+        glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_TEXTURE3);
     else if (params.colorArg2 == TEX_MIX_ARG_COMPUTED_COLOR)
         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_PREVIOUS);
     else if (params.colorArg2 == TEX_MIX_ARG_SRC_COLOR)
@@ -1097,6 +1126,14 @@ after_tex_color:
     // Alpha arg1
     if (params.alphaArg1 == TEX_MIX_ARG_TEXTURE)
         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_TEXTURE);
+    else if (params.alphaArg1 == TEX_MIX_ARG_TEXTURE_0)
+        glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_TEXTURE0);
+    else if (params.alphaArg1 == TEX_MIX_ARG_TEXTURE_1)
+        glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_TEXTURE1);
+    else if (params.alphaArg1 == TEX_MIX_ARG_TEXTURE_2)
+        glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_TEXTURE2);
+    else if (params.alphaArg1 == TEX_MIX_ARG_TEXTURE_3)
+        glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_TEXTURE3);
     else if (params.alphaArg1 == TEX_MIX_ARG_COMPUTED_COLOR)
         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_PREVIOUS);
     else if (params.alphaArg1 == TEX_MIX_ARG_SRC_COLOR)
@@ -1108,6 +1145,14 @@ after_tex_color:
     // Alpha arg2
     if (params.alphaArg2 == TEX_MIX_ARG_TEXTURE)
         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA, GL_TEXTURE);
+    else if (params.alphaArg2 == TEX_MIX_ARG_TEXTURE_0)
+        glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA, GL_TEXTURE0);
+    else if (params.alphaArg2 == TEX_MIX_ARG_TEXTURE_1)
+        glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA, GL_TEXTURE1);
+    else if (params.alphaArg2 == TEX_MIX_ARG_TEXTURE_2)
+        glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA, GL_TEXTURE2);
+    else if (params.alphaArg2 == TEX_MIX_ARG_TEXTURE_3)
+        glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA, GL_TEXTURE3);
     else if (params.alphaArg2 == TEX_MIX_ARG_COMPUTED_COLOR)
         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA, GL_PREVIOUS);
     else if (params.alphaArg2 == TEX_MIX_ARG_SRC_COLOR)
@@ -1728,6 +1773,21 @@ void CGLDevice::SetRenderState(RenderState state, bool 
enabled)
 
         return;
     }
+    else if (state == RENDER_STATE_OFFSCREEN_RENDERING)
+    {
+        if (!m_framebufferObject)
+        {
+            GetLogger()->Error("Cannot enable offscreen rendering without 
framebuffer object!\n");
+            return;
+        }
+
+        if (m_framebuffer == 0)
+            InitOffscreenBuffer(2048, 2048);
+
+        GLuint toBind = (enabled ? m_framebuffer : 0);
+
+        glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, toBind);
+    }
 
     GLenum flag = 0;
 
@@ -1895,6 +1955,42 @@ void CGLDevice::SetFillMode(FillMode mode)
     else assert(false);
 }
 
+void CGLDevice::InitOffscreenBuffer(int width, int height)
+{
+    if (!m_framebufferObject) return;
+
+    width = Math::Min(width, m_maxRenderbufferSize);
+    height = Math::Min(height, m_maxRenderbufferSize);
+
+    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
+
+    if (m_colorBuffer != 0)
+        glDeleteRenderbuffersEXT(1, &m_colorBuffer);
+
+    glGenRenderbuffersEXT(1, &m_colorBuffer);
+    glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_colorBuffer);
+    glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_RGBA8, width, height);
+    glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
+
+    if (m_depthBuffer != 0)
+        glDeleteRenderbuffersEXT(1, &m_depthBuffer);
+
+    glGenRenderbuffersEXT(1, &m_depthBuffer);
+    glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_depthBuffer);
+    glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT24, width, 
height);
+    glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
+
+    if (m_framebuffer == 0)
+        glGenFramebuffersEXT(1, &m_framebuffer);
+
+    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_framebuffer);
+    glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, 
GL_RENDERBUFFER_EXT, m_colorBuffer);
+    glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, 
GL_RENDERBUFFER_EXT, m_depthBuffer);
+    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
+
+    GetLogger()->Info("Initialized offscreen buffer %dx%d\n", width, height);
+}
+
 void CGLDevice::CopyFramebufferToTexture(Texture& texture, int xOffset, int 
yOffset, int x, int y, int width, int height)
 {
     if (texture.id == 0) return;
diff --git a/src/graphics/opengl/gldevice.h b/src/graphics/opengl/gldevice.h
index 4ba1410..61a7736 100644
--- a/src/graphics/opengl/gldevice.h
+++ b/src/graphics/opengl/gldevice.h
@@ -26,6 +26,7 @@
 
 
 #include "graphics/core/device.h"
+#include "GL/glew.h"
 
 #include <string>
 #include <vector>
@@ -197,6 +198,8 @@ public:
 
     virtual void SetFillMode(FillMode mode) OVERRIDE;
 
+    virtual void InitOffscreenBuffer(int width, int height) OVERRIDE;
+
     virtual void CopyFramebufferToTexture(Texture& texture, int xOffset, int 
yOffset, int x, int y, int width, int height) OVERRIDE;
 
     virtual void* GetFrameBufferPixels() const OVERRIDE;
@@ -272,12 +275,24 @@ private:
     bool m_anisotropyAvailable;
     //! Maximum anisotropy level
     int m_maxAnisotropy;
+    //! Whether offscreen rendering is available
+    bool m_framebufferObject;
     //! Which vertex buffer type to use
     VertexBufferType m_vertexBufferType;
     //! Map of saved VBO objects
     std::map<unsigned int, VboObjectInfo> m_vboObjects;
     //! Last ID of VBO object
     unsigned int m_lastVboId;
+
+    // Offscreen buffer
+    //! Framebuffer object
+    GLuint m_framebuffer;
+    //! Color renderbuffer
+    GLuint m_colorBuffer;
+    //! Depth renderbuffer
+    GLuint m_depthBuffer;
+    //! Maximum available renderbuffer size
+    int m_maxRenderbufferSize;
 };
 
 

-- 
Alioth's /usr/local/bin/git-commit-notice on 
/srv/git.debian.org/git/pkg-games/colobot.git

_______________________________________________
Pkg-games-commits mailing list
Pkg-games-commits@lists.alioth.debian.org
http://lists.alioth.debian.org/cgi-bin/mailman/listinfo/pkg-games-commits

Reply via email to