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