[colobot] 352/390: Added support for offscreen rendering and high resolution shadow maps
Didier Raboud
odyx at moszumanska.debian.org
Fri Jun 12 14:22:03 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 2665847c413b289dfb230d3ba97accb749fc52f2
Author: Tomasz Kapuściński <tomaszkax86 at 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
More information about the Pkg-games-commits
mailing list