Refactored framebuffer implementations
parent
94851c2694
commit
7d57ec634e
|
@ -98,6 +98,7 @@ set(BASE_SOURCES
|
||||||
common/resources/sndfile.cpp
|
common/resources/sndfile.cpp
|
||||||
graphics/core/color.cpp
|
graphics/core/color.cpp
|
||||||
graphics/core/nulldevice.cpp
|
graphics/core/nulldevice.cpp
|
||||||
|
graphics/core/framebuffer.cpp
|
||||||
graphics/engine/camera.cpp
|
graphics/engine/camera.cpp
|
||||||
graphics/engine/cloud.cpp
|
graphics/engine/cloud.cpp
|
||||||
graphics/engine/engine.cpp
|
graphics/engine/engine.cpp
|
||||||
|
@ -115,6 +116,7 @@ set(BASE_SOURCES
|
||||||
graphics/opengl/gl21device.cpp
|
graphics/opengl/gl21device.cpp
|
||||||
graphics/opengl/gl33device.cpp
|
graphics/opengl/gl33device.cpp
|
||||||
graphics/opengl/glutil.cpp
|
graphics/opengl/glutil.cpp
|
||||||
|
graphics/opengl/glframebuffer.cpp
|
||||||
object/auto/auto.cpp
|
object/auto/auto.cpp
|
||||||
object/auto/autobase.cpp
|
object/auto/autobase.cpp
|
||||||
object/auto/autoconvert.cpp
|
object/auto/autoconvert.cpp
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
#include "graphics/core/material.h"
|
#include "graphics/core/material.h"
|
||||||
#include "graphics/core/texture.h"
|
#include "graphics/core/texture.h"
|
||||||
#include "graphics/core/vertex.h"
|
#include "graphics/core/vertex.h"
|
||||||
|
#include "graphics/core/framebuffer.h"
|
||||||
|
|
||||||
#include "math/intpoint.h"
|
#include "math/intpoint.h"
|
||||||
#include "math/matrix.h"
|
#include "math/matrix.h"
|
||||||
|
@ -75,6 +76,8 @@ struct DeviceConfig
|
||||||
int alphaSize;
|
int alphaSize;
|
||||||
//! Color depth in bits
|
//! Color depth in bits
|
||||||
int depthSize;
|
int depthSize;
|
||||||
|
//! Stencil depth in bits
|
||||||
|
int stencilSize;
|
||||||
|
|
||||||
//! Force hardware acceleration (video mode set will fail on lack of hw accel)
|
//! Force hardware acceleration (video mode set will fail on lack of hw accel)
|
||||||
bool hardwareAccel;
|
bool hardwareAccel;
|
||||||
|
@ -99,6 +102,7 @@ struct DeviceConfig
|
||||||
greenSize = 8;
|
greenSize = 8;
|
||||||
alphaSize = 8;
|
alphaSize = 8;
|
||||||
depthSize = 24;
|
depthSize = 24;
|
||||||
|
stencilSize = 8;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -131,7 +135,6 @@ enum RenderState
|
||||||
RENDER_STATE_ALPHA_TEST,
|
RENDER_STATE_ALPHA_TEST,
|
||||||
RENDER_STATE_CULLING,
|
RENDER_STATE_CULLING,
|
||||||
RENDER_STATE_DEPTH_BIAS,
|
RENDER_STATE_DEPTH_BIAS,
|
||||||
RENDER_STATE_OFFSCREEN_RENDERING
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -418,17 +421,20 @@ public:
|
||||||
//! Sets the current fill mode
|
//! Sets the current fill mode
|
||||||
virtual void SetFillMode(FillMode mode) = 0;
|
virtual void SetFillMode(FillMode mode) = 0;
|
||||||
|
|
||||||
//! Initializes offscreen buffer
|
|
||||||
virtual void InitOffscreenBuffer(int width, int height) = 0;
|
|
||||||
|
|
||||||
//! Sets render target to texture
|
|
||||||
virtual void SetRenderTexture(RenderTarget target, int texture) = 0;
|
|
||||||
|
|
||||||
//! Copies content of framebuffer to texture
|
//! Copies content of framebuffer to texture
|
||||||
virtual void CopyFramebufferToTexture(Texture& texture, int xOffset, int yOffset, int x, int y, int width, int height) = 0;
|
virtual void CopyFramebufferToTexture(Texture& texture, int xOffset, int yOffset, int x, int y, int width, int height) = 0;
|
||||||
|
|
||||||
//! Returns the pixels of the entire screen
|
//! Returns the pixels of the entire screen
|
||||||
virtual void* GetFrameBufferPixels() const = 0;
|
virtual void* GetFrameBufferPixels() const = 0;
|
||||||
|
|
||||||
|
//! Returns framebuffer with given name or nullptr if it doesn't exist
|
||||||
|
virtual CFramebuffer* GetFramebuffer(std::string name) = 0;
|
||||||
|
|
||||||
|
//! Creates new framebuffer with given name or nullptr if it's not possible
|
||||||
|
virtual CFramebuffer* CreateFramebuffer(std::string name, const FramebufferParams& params) = 0;
|
||||||
|
|
||||||
|
//! Deletes framebuffer
|
||||||
|
virtual void DeleteFramebuffer(std::string name) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,100 @@
|
||||||
|
/*
|
||||||
|
* This file is part of the Colobot: Gold Edition source code
|
||||||
|
* Copyright (C) 2001-2014, Daniel Roux, EPSITEC SA & TerranovaTeam
|
||||||
|
* http://epsite?.ch; http://colobot.info; http://github.com/colobot
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
* See the GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see http://gnu.org/licenses
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \file graphics/core/framebuffer.h
|
||||||
|
* \brief Abstract representation of framebuffer and offscreen buffers
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "graphics/core/framebuffer.h"
|
||||||
|
|
||||||
|
namespace Gfx {
|
||||||
|
|
||||||
|
CDefaultFramebuffer::CDefaultFramebuffer(const FramebufferParams& params)
|
||||||
|
: m_width(params.width), m_height(params.height), m_depth(params.depth)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void CDefaultFramebuffer::Create()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void CDefaultFramebuffer::Destroy()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CDefaultFramebuffer::IsDefault()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Returns width of buffers in this framebuffer
|
||||||
|
int CDefaultFramebuffer::GetWidth()
|
||||||
|
{
|
||||||
|
return m_width;
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Returns height of buffers in this framebuffer
|
||||||
|
int CDefaultFramebuffer::GetHeight()
|
||||||
|
{
|
||||||
|
return m_height;
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Returns depth size in bits
|
||||||
|
int CDefaultFramebuffer::GetDepth()
|
||||||
|
{
|
||||||
|
return m_depth;
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Returns number of samples or 1 if multisampling is not supported
|
||||||
|
int CDefaultFramebuffer::GetSamples()
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Returns texture that contains color buffer or 0 if not available
|
||||||
|
int CDefaultFramebuffer::GetColorTexture()
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Returns texture that contains depth buffer or 0 if not available
|
||||||
|
int CDefaultFramebuffer::GetDepthTexture()
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Binds this framebuffer to context
|
||||||
|
void CDefaultFramebuffer::Bind()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Unbinds this framebuffer from context
|
||||||
|
void CDefaultFramebuffer::Unbind()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
} // end of Gfx
|
|
@ -0,0 +1,164 @@
|
||||||
|
/*
|
||||||
|
* This file is part of the Colobot: Gold Edition source code
|
||||||
|
* Copyright (C) 2001-2014, Daniel Roux, EPSITEC SA & TerranovaTeam
|
||||||
|
* http://epsite?.ch; http://colobot.info; http://github.com/colobot
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
* See the GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see http://gnu.org/licenses
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \file graphics/core/framebuffer.h
|
||||||
|
* \brief Abstract representation of framebuffer and offscreen buffers
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace Gfx {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \struct FramebufferParams
|
||||||
|
* \brief Contains parameters for new framebuffer
|
||||||
|
*/
|
||||||
|
struct FramebufferParams
|
||||||
|
{
|
||||||
|
//! Requested width of buffers
|
||||||
|
int width;
|
||||||
|
//! Requested height of buffers
|
||||||
|
int height;
|
||||||
|
//! Requested depth buffer
|
||||||
|
int depth;
|
||||||
|
//! Requested number of samples for multisampling
|
||||||
|
int samples;
|
||||||
|
//! true requests color texture
|
||||||
|
bool colorTexture;
|
||||||
|
//! true requests depth texture
|
||||||
|
bool depthTexture;
|
||||||
|
|
||||||
|
|
||||||
|
//! Initializes
|
||||||
|
FramebufferParams()
|
||||||
|
{
|
||||||
|
LoadDefault();
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Loads default values
|
||||||
|
void LoadDefault()
|
||||||
|
{
|
||||||
|
width = 1024;
|
||||||
|
height = 1024;
|
||||||
|
depth = 16;
|
||||||
|
samples = 1;
|
||||||
|
colorTexture = false;
|
||||||
|
depthTexture = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \class CFramebuffer
|
||||||
|
* \brief Abstract interface of default framebuffer and offscreen framebuffers
|
||||||
|
*
|
||||||
|
* This code encapsulates basics of default framebuffer and offscreen buffers
|
||||||
|
* and allows offscreen rendering in generic way. CDevice may or may not implement
|
||||||
|
* offscreen buffers depending on available hardware but is required to provide
|
||||||
|
* default framebuffer implementation. Because of some hardware restrictions
|
||||||
|
* and in order to simplify interface, you can't bind/unbind textures from
|
||||||
|
* offscreen buffers and you can't change it's parameters.
|
||||||
|
*/
|
||||||
|
class CFramebuffer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
//! Creates this framebuffer
|
||||||
|
virtual void Create() = 0;
|
||||||
|
|
||||||
|
//! Destroys this framebuffer
|
||||||
|
virtual void Destroy() = 0;
|
||||||
|
|
||||||
|
//! Returns true if this is default framebuffer
|
||||||
|
virtual bool IsDefault() = 0;
|
||||||
|
|
||||||
|
//! Returns width of buffers in this framebuffer
|
||||||
|
virtual int GetWidth() = 0;
|
||||||
|
|
||||||
|
//! Returns height of buffers in this framebuffer
|
||||||
|
virtual int GetHeight() = 0;
|
||||||
|
|
||||||
|
//! Returns depth size in bits
|
||||||
|
virtual int GetDepth() = 0;
|
||||||
|
|
||||||
|
//! Returns number of samples or 1 if multisampling is not supported
|
||||||
|
virtual int GetSamples() = 0;
|
||||||
|
|
||||||
|
//! Returns texture that contains color buffer or 0 if not available
|
||||||
|
virtual int GetColorTexture() = 0;
|
||||||
|
|
||||||
|
//! Returns texture that contains depth buffer or 0 if not available
|
||||||
|
virtual int GetDepthTexture() = 0;
|
||||||
|
|
||||||
|
//! Binds this framebuffer to context
|
||||||
|
virtual void Bind() = 0;
|
||||||
|
|
||||||
|
//! Unbinds this framebuffer from context
|
||||||
|
virtual void Unbind() = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \class CDefaultFramebuffer
|
||||||
|
* \brief Concrete implementation of default framebuffer.
|
||||||
|
*
|
||||||
|
* This class represents default framebuffer implementation.
|
||||||
|
*/
|
||||||
|
class CDefaultFramebuffer : public CFramebuffer
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
int m_width, m_height, m_depth;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit CDefaultFramebuffer(const FramebufferParams ¶ms);
|
||||||
|
|
||||||
|
//! Creates default framebuffer
|
||||||
|
virtual void Create() OVERRIDE;
|
||||||
|
|
||||||
|
//! Destroys default framebuffer
|
||||||
|
virtual void Destroy() OVERRIDE;
|
||||||
|
|
||||||
|
//! Returns true
|
||||||
|
virtual bool IsDefault() OVERRIDE;
|
||||||
|
|
||||||
|
//! Returns width of buffers in this framebuffer
|
||||||
|
virtual int GetWidth() OVERRIDE;
|
||||||
|
|
||||||
|
//! Returns height of buffers in this framebuffer
|
||||||
|
virtual int GetHeight() OVERRIDE;
|
||||||
|
|
||||||
|
//! Returns depth size in bits
|
||||||
|
virtual int GetDepth() OVERRIDE;
|
||||||
|
|
||||||
|
//! Returns number of samples or 1 if multisampling is not supported
|
||||||
|
virtual int GetSamples() OVERRIDE;
|
||||||
|
|
||||||
|
//! Returns texture that contains color buffer or 0 if not available
|
||||||
|
virtual int GetColorTexture() OVERRIDE;
|
||||||
|
|
||||||
|
//! Returns texture that contains depth buffer or 0 if not available
|
||||||
|
virtual int GetDepthTexture() OVERRIDE;
|
||||||
|
|
||||||
|
//! Binds this framebuffer to context
|
||||||
|
virtual void Bind() OVERRIDE;
|
||||||
|
|
||||||
|
//! Unbinds this framebuffer from context
|
||||||
|
virtual void Unbind() OVERRIDE;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // end of Gfx
|
|
@ -359,14 +359,6 @@ FillMode CNullDevice::GetFillMode()
|
||||||
return FILL_POINT;
|
return FILL_POINT;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CNullDevice::InitOffscreenBuffer(int width, int height)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void CNullDevice::SetRenderTexture(RenderTarget target, int texture)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void CNullDevice::CopyFramebufferToTexture(Texture& texture, int xOffset, int yOffset, int x, int y, int width, int height)
|
void CNullDevice::CopyFramebufferToTexture(Texture& texture, int xOffset, int yOffset, int x, int y, int width, int height)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -376,6 +368,19 @@ void* CNullDevice::GetFrameBufferPixels() const
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CFramebuffer* CNullDevice::GetFramebuffer(std::string name)
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
CFramebuffer* CNullDevice::CreateFramebuffer(std::string name, const FramebufferParams& params)
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CNullDevice::DeleteFramebuffer(std::string name)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Gfx
|
} // namespace Gfx
|
||||||
|
|
||||||
|
|
|
@ -142,13 +142,15 @@ public:
|
||||||
virtual void SetFillMode(FillMode mode) ;
|
virtual void SetFillMode(FillMode mode) ;
|
||||||
virtual FillMode GetFillMode();
|
virtual FillMode GetFillMode();
|
||||||
|
|
||||||
virtual void InitOffscreenBuffer(int width, int height);
|
|
||||||
|
|
||||||
virtual void SetRenderTexture(RenderTarget target, int texture);
|
|
||||||
|
|
||||||
virtual void CopyFramebufferToTexture(Texture& texture, int xOffset, int yOffset, int x, int y, 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;
|
virtual void* GetFrameBufferPixels() const;
|
||||||
|
|
||||||
|
virtual CFramebuffer* GetFramebuffer(std::string name);
|
||||||
|
|
||||||
|
virtual CFramebuffer* CreateFramebuffer(std::string name, const FramebufferParams& params);
|
||||||
|
|
||||||
|
virtual void DeleteFramebuffer(std::string name);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Math::Matrix m_matrix;
|
Math::Matrix m_matrix;
|
||||||
|
|
|
@ -3527,6 +3527,24 @@ void CEngine::RenderShadowMap()
|
||||||
{
|
{
|
||||||
width = height = 1024;
|
width = height = 1024;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FramebufferParams params;
|
||||||
|
params.width = params.height = width;
|
||||||
|
params.depth = depth;
|
||||||
|
params.depthTexture = true;
|
||||||
|
|
||||||
|
CFramebuffer *framebuffer = m_device->CreateFramebuffer("shadow", params);
|
||||||
|
if (framebuffer == nullptr)
|
||||||
|
{
|
||||||
|
GetLogger()->Error("Could not create framebuffer, disabling shadows\n");
|
||||||
|
m_shadowMapping = false;
|
||||||
|
m_offscreenShadowRendering = false;
|
||||||
|
m_qualityShadows = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_shadowMap.id = framebuffer->GetDepthTexture();
|
||||||
|
m_shadowMap.size = Math::IntPoint(width, height);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -3538,13 +3556,8 @@ void CEngine::RenderShadowMap()
|
||||||
|
|
||||||
width = height = 1 << i;
|
width = height = 1 << i;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
m_shadowMap = m_device->CreateDepthTexture(width, height, depth);
|
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);
|
GetLogger()->Info("Created shadow map texture: %dx%d, depth %d\n", width, height, depth);
|
||||||
|
@ -3552,8 +3565,7 @@ void CEngine::RenderShadowMap()
|
||||||
|
|
||||||
if (m_offscreenShadowRendering)
|
if (m_offscreenShadowRendering)
|
||||||
{
|
{
|
||||||
m_device->SetRenderState(RENDER_STATE_OFFSCREEN_RENDERING, true);
|
m_device->GetFramebuffer("shadow")->Bind();
|
||||||
m_device->SetRenderTexture(RENDER_TARGET_DEPTH, m_shadowMap.id);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
m_device->Clear();
|
m_device->Clear();
|
||||||
|
@ -3666,8 +3678,7 @@ void CEngine::RenderShadowMap()
|
||||||
|
|
||||||
if (m_offscreenShadowRendering) // shadow map texture already have depth information, just unbind it
|
if (m_offscreenShadowRendering) // shadow map texture already have depth information, just unbind it
|
||||||
{
|
{
|
||||||
m_device->SetRenderTexture(RENDER_TARGET_DEPTH, 0);
|
m_device->GetFramebuffer("shadow")->Unbind();
|
||||||
m_device->SetRenderState(RENDER_STATE_OFFSCREEN_RENDERING, false);
|
|
||||||
}
|
}
|
||||||
else // copy depth buffer to shadow map
|
else // copy depth buffer to shadow map
|
||||||
{
|
{
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
|
|
||||||
|
|
||||||
#include "graphics/opengl/gl21device.h"
|
#include "graphics/opengl/gl21device.h"
|
||||||
|
#include "graphics/opengl/glframebuffer.h"
|
||||||
#include "graphics/engine/engine.h"
|
#include "graphics/engine/engine.h"
|
||||||
|
|
||||||
#include "common/config.h"
|
#include "common/config.h"
|
||||||
|
@ -48,11 +49,6 @@ CGL21Device::CGL21Device(const DeviceConfig &config)
|
||||||
m_glMajor = 1;
|
m_glMajor = 1;
|
||||||
m_glMinor = 1;
|
m_glMinor = 1;
|
||||||
|
|
||||||
m_framebuffer = 0;
|
|
||||||
m_colorBuffer = 0;
|
|
||||||
m_depthBuffer = 0;
|
|
||||||
m_offscreenRenderingEnabled = false;
|
|
||||||
|
|
||||||
m_perPixelLighting = false;
|
m_perPixelLighting = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -199,15 +195,6 @@ bool CGL21Device::Create()
|
||||||
|
|
||||||
GetLogger()->Info("OpenGL %d.%d\n", m_glMajor, m_glMinor);
|
GetLogger()->Info("OpenGL %d.%d\n", m_glMajor, m_glMinor);
|
||||||
|
|
||||||
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 support of anisotropic filtering
|
// Detect support of anisotropic filtering
|
||||||
m_anisotropyAvailable = glewIsSupported("GL_EXT_texture_filter_anisotropic");
|
m_anisotropyAvailable = glewIsSupported("GL_EXT_texture_filter_anisotropic");
|
||||||
if(m_anisotropyAvailable)
|
if(m_anisotropyAvailable)
|
||||||
|
@ -356,6 +343,19 @@ bool CGL21Device::Create()
|
||||||
for (int i = 0; i < 8; i++)
|
for (int i = 0; i < 8; i++)
|
||||||
glUniform1i(uni_LightEnabled[i], 0);
|
glUniform1i(uni_LightEnabled[i], 0);
|
||||||
|
|
||||||
|
// create default framebuffer object
|
||||||
|
FramebufferParams framebufferParams;
|
||||||
|
|
||||||
|
framebufferParams.width = m_config.size.x;
|
||||||
|
framebufferParams.height = m_config.size.y;
|
||||||
|
framebufferParams.depth = m_config.depthSize;
|
||||||
|
|
||||||
|
m_framebuffers["default"] = new CDefaultFramebuffer(framebufferParams);
|
||||||
|
|
||||||
|
m_framebufferSupport = DetectFramebufferSupport();
|
||||||
|
if (m_framebufferSupport != FBS_NONE)
|
||||||
|
GetLogger()->Debug("Framebuffer supported\n");
|
||||||
|
|
||||||
GetLogger()->Info("CDevice created successfully\n");
|
GetLogger()->Info("CDevice created successfully\n");
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -368,6 +368,15 @@ void CGL21Device::Destroy()
|
||||||
glUseProgram(0);
|
glUseProgram(0);
|
||||||
glDeleteProgram(m_program);
|
glDeleteProgram(m_program);
|
||||||
|
|
||||||
|
// delete framebuffers
|
||||||
|
for (std::map<std::string, CFramebuffer*>::iterator i = m_framebuffers.begin(); i != m_framebuffers.end(); i++)
|
||||||
|
{
|
||||||
|
i->second->Destroy();
|
||||||
|
delete i->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_framebuffers.clear();
|
||||||
|
|
||||||
DestroyAllTextures();
|
DestroyAllTextures();
|
||||||
|
|
||||||
m_lights.clear();
|
m_lights.clear();
|
||||||
|
@ -1561,25 +1570,6 @@ void CGL21Device::SetRenderState(RenderState state, bool enabled)
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (state == RENDER_STATE_OFFSCREEN_RENDERING)
|
|
||||||
{
|
|
||||||
if (!m_framebufferObject)
|
|
||||||
{
|
|
||||||
GetLogger()->Error("Cannot enable offscreen rendering without framebuffer object!\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_offscreenRenderingEnabled = enabled;
|
|
||||||
|
|
||||||
if (m_framebuffer == 0)
|
|
||||||
InitOffscreenBuffer(2048, 2048);
|
|
||||||
|
|
||||||
GLuint toBind = (enabled ? m_framebuffer : 0);
|
|
||||||
|
|
||||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, toBind);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else if (state == RENDER_STATE_ALPHA_TEST)
|
else if (state == RENDER_STATE_ALPHA_TEST)
|
||||||
{
|
{
|
||||||
glUniform1i(uni_AlphaTestEnabled, enabled ? 1 : 0);
|
glUniform1i(uni_AlphaTestEnabled, enabled ? 1 : 0);
|
||||||
|
@ -1693,79 +1683,6 @@ void CGL21Device::SetFillMode(FillMode mode)
|
||||||
else assert(false);
|
else assert(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CGL21Device::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 CGL21Device::SetRenderTexture(RenderTarget target, int texture)
|
|
||||||
{
|
|
||||||
if (!m_framebufferObject) return;
|
|
||||||
if (!m_offscreenRenderingEnabled) return;
|
|
||||||
|
|
||||||
GLenum attachment;
|
|
||||||
GLuint defaultBuffer;
|
|
||||||
|
|
||||||
switch (target)
|
|
||||||
{
|
|
||||||
case RENDER_TARGET_COLOR:
|
|
||||||
attachment = GL_COLOR_ATTACHMENT0_EXT;
|
|
||||||
defaultBuffer = m_colorBuffer;
|
|
||||||
break;
|
|
||||||
case RENDER_TARGET_DEPTH:
|
|
||||||
attachment = GL_DEPTH_ATTACHMENT_EXT;
|
|
||||||
defaultBuffer = m_depthBuffer;
|
|
||||||
break;
|
|
||||||
case RENDER_TARGET_STENCIL:
|
|
||||||
attachment = GL_STENCIL_ATTACHMENT_EXT;
|
|
||||||
defaultBuffer = 0;
|
|
||||||
break;
|
|
||||||
default: assert(false); break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (texture == 0) // unbind texture and bind default buffer
|
|
||||||
{
|
|
||||||
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, attachment, GL_TEXTURE_2D, 0, 0);
|
|
||||||
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, attachment, GL_RENDERBUFFER_EXT, defaultBuffer);
|
|
||||||
}
|
|
||||||
else // unbind default buffer and bind texture
|
|
||||||
{
|
|
||||||
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, attachment, GL_RENDERBUFFER_EXT, 0);
|
|
||||||
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, attachment, GL_TEXTURE_2D, texture, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CGL21Device::CopyFramebufferToTexture(Texture& texture, int xOffset, int yOffset, int x, int y, int width, int height)
|
void CGL21Device::CopyFramebufferToTexture(Texture& texture, int xOffset, int yOffset, int x, int y, int width, int height)
|
||||||
{
|
{
|
||||||
if (texture.id == 0) return;
|
if (texture.id == 0) return;
|
||||||
|
@ -1794,4 +1711,53 @@ void* CGL21Device::GetFrameBufferPixels()const{
|
||||||
return static_cast<void*>(p);
|
return static_cast<void*>(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CFramebuffer* CGL21Device::GetFramebuffer(std::string name)
|
||||||
|
{
|
||||||
|
if (m_framebuffers.find(name) != m_framebuffers.end())
|
||||||
|
return m_framebuffers[name];
|
||||||
|
else
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
CFramebuffer* CGL21Device::CreateFramebuffer(std::string name, const FramebufferParams& params)
|
||||||
|
{
|
||||||
|
// existing framebuffer was found
|
||||||
|
if (m_framebuffers.find(name) != m_framebuffers.end())
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CFramebuffer *framebuffer;
|
||||||
|
|
||||||
|
if (m_framebufferSupport == FBS_ARB)
|
||||||
|
framebuffer = new CGLFramebuffer(params);
|
||||||
|
else if (m_framebufferSupport == FBS_EXT)
|
||||||
|
framebuffer = new CGLFramebufferEXT(params);
|
||||||
|
else
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
framebuffer->Create();
|
||||||
|
|
||||||
|
m_framebuffers[name] = framebuffer;
|
||||||
|
return framebuffer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CGL21Device::DeleteFramebuffer(std::string name)
|
||||||
|
{
|
||||||
|
// can't delete default framebuffer
|
||||||
|
if (name == "default") return;
|
||||||
|
|
||||||
|
auto position = m_framebuffers.find(name);
|
||||||
|
|
||||||
|
if (position != m_framebuffers.end())
|
||||||
|
{
|
||||||
|
position->second->Destroy();
|
||||||
|
delete position->second;
|
||||||
|
|
||||||
|
m_framebuffers.erase(position);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Gfx
|
} // namespace Gfx
|
||||||
|
|
|
@ -137,14 +137,16 @@ public:
|
||||||
|
|
||||||
virtual void SetFillMode(FillMode mode) OVERRIDE;
|
virtual void SetFillMode(FillMode mode) OVERRIDE;
|
||||||
|
|
||||||
virtual void InitOffscreenBuffer(int width, int height) OVERRIDE;
|
|
||||||
|
|
||||||
virtual void SetRenderTexture(RenderTarget target, int texture) OVERRIDE;
|
|
||||||
|
|
||||||
virtual void CopyFramebufferToTexture(Texture& texture, int xOffset, int yOffset, int x, int y, 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;
|
virtual void* GetFrameBufferPixels() const OVERRIDE;
|
||||||
|
|
||||||
|
virtual CFramebuffer* GetFramebuffer(std::string name) OVERRIDE;
|
||||||
|
|
||||||
|
virtual CFramebuffer* CreateFramebuffer(std::string name, const FramebufferParams& params) OVERRIDE;
|
||||||
|
|
||||||
|
virtual void DeleteFramebuffer(std::string name) OVERRIDE;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
//! Updates position for given light based on transformation matrices
|
//! Updates position for given light based on transformation matrices
|
||||||
void UpdateLightPosition(int index);
|
void UpdateLightPosition(int index);
|
||||||
|
@ -188,6 +190,9 @@ private:
|
||||||
//! Set of all created textures
|
//! Set of all created textures
|
||||||
std::set<Texture> m_allTextures;
|
std::set<Texture> m_allTextures;
|
||||||
|
|
||||||
|
//! Map of framebuffers
|
||||||
|
std::map<std::string, CFramebuffer*> m_framebuffers;
|
||||||
|
|
||||||
//! Type of vertex structure
|
//! Type of vertex structure
|
||||||
enum VertexType
|
enum VertexType
|
||||||
{
|
{
|
||||||
|
@ -215,6 +220,8 @@ private:
|
||||||
int m_maxAnisotropy;
|
int m_maxAnisotropy;
|
||||||
//! Whether offscreen rendering is available
|
//! Whether offscreen rendering is available
|
||||||
bool m_framebufferObject;
|
bool m_framebufferObject;
|
||||||
|
//! Framebuffer support
|
||||||
|
FramebufferSupport m_framebufferSupport;
|
||||||
//! Map of saved VBO objects
|
//! Map of saved VBO objects
|
||||||
std::map<unsigned int, VboObjectInfo> m_vboObjects;
|
std::map<unsigned int, VboObjectInfo> m_vboObjects;
|
||||||
//! Last ID of VBO object
|
//! Last ID of VBO object
|
||||||
|
@ -222,18 +229,6 @@ private:
|
||||||
//! Currently bound VBO
|
//! Currently bound VBO
|
||||||
GLuint m_currentVBO;
|
GLuint m_currentVBO;
|
||||||
|
|
||||||
// Offscreen buffer
|
|
||||||
//! Framebuffer object
|
|
||||||
GLuint m_framebuffer;
|
|
||||||
//! Color renderbuffer
|
|
||||||
GLuint m_colorBuffer;
|
|
||||||
//! Depth renderbuffer
|
|
||||||
GLuint m_depthBuffer;
|
|
||||||
//! Maximum available renderbuffer size
|
|
||||||
int m_maxRenderbufferSize;
|
|
||||||
//! true if offscreen rendering enabled
|
|
||||||
bool m_offscreenRenderingEnabled;
|
|
||||||
|
|
||||||
//! true enables per-pixel lighting
|
//! true enables per-pixel lighting
|
||||||
bool m_perPixelLighting;
|
bool m_perPixelLighting;
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "graphics/opengl/gl33device.h"
|
#include "graphics/opengl/gl33device.h"
|
||||||
|
#include "graphics/opengl/glframebuffer.h"
|
||||||
#include "graphics/engine/engine.h"
|
#include "graphics/engine/engine.h"
|
||||||
|
|
||||||
#include "common/config.h"
|
#include "common/config.h"
|
||||||
|
@ -47,11 +48,6 @@ CGL33Device::CGL33Device(const DeviceConfig &config)
|
||||||
m_glMajor = 1;
|
m_glMajor = 1;
|
||||||
m_glMinor = 1;
|
m_glMinor = 1;
|
||||||
|
|
||||||
m_framebuffer = 0;
|
|
||||||
m_colorBuffer = 0;
|
|
||||||
m_depthBuffer = 0;
|
|
||||||
m_offscreenRenderingEnabled = false;
|
|
||||||
|
|
||||||
m_perPixelLighting = false;
|
m_perPixelLighting = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -205,9 +201,6 @@ bool CGL33Device::Create()
|
||||||
GetLogger()->Info("OpenGL %d.%d\n", m_glMajor, m_glMinor);
|
GetLogger()->Info("OpenGL %d.%d\n", m_glMajor, m_glMinor);
|
||||||
}
|
}
|
||||||
|
|
||||||
glGetIntegerv(GL_MAX_RENDERBUFFER_SIZE, &m_maxRenderbufferSize);
|
|
||||||
GetLogger()->Info("Maximum renderbuffer size: %d\n", m_maxRenderbufferSize);
|
|
||||||
|
|
||||||
// Detect support of anisotropic filtering
|
// Detect support of anisotropic filtering
|
||||||
m_anisotropyAvailable = glewIsSupported("GL_EXT_texture_filter_anisotropic");
|
m_anisotropyAvailable = glewIsSupported("GL_EXT_texture_filter_anisotropic");
|
||||||
if(m_anisotropyAvailable)
|
if(m_anisotropyAvailable)
|
||||||
|
@ -249,8 +242,6 @@ bool CGL33Device::Create()
|
||||||
m_vertexTex2 = CreateStaticBuffer(PRIMITIVE_POINTS, static_cast<VertexTex2*>(nullptr), 1);
|
m_vertexTex2 = CreateStaticBuffer(PRIMITIVE_POINTS, static_cast<VertexTex2*>(nullptr), 1);
|
||||||
m_vertexCol = CreateStaticBuffer(PRIMITIVE_POINTS, static_cast<VertexCol*>(nullptr), 1);
|
m_vertexCol = CreateStaticBuffer(PRIMITIVE_POINTS, static_cast<VertexCol*>(nullptr), 1);
|
||||||
|
|
||||||
GetLogger()->Info("CDevice created successfully\n");
|
|
||||||
|
|
||||||
int value;
|
int value;
|
||||||
if (CProfile::GetInstance().GetIntProperty("Setup", "PerPixelLighting", value))
|
if (CProfile::GetInstance().GetIntProperty("Setup", "PerPixelLighting", value))
|
||||||
{
|
{
|
||||||
|
@ -379,23 +370,35 @@ bool CGL33Device::Create()
|
||||||
for (int i = 0; i < 8; i++)
|
for (int i = 0; i < 8; i++)
|
||||||
glUniform1i(uni_Light[i].Enabled, 0);
|
glUniform1i(uni_Light[i].Enabled, 0);
|
||||||
|
|
||||||
|
// create default framebuffer object
|
||||||
|
FramebufferParams framebufferParams;
|
||||||
|
|
||||||
|
framebufferParams.width = m_config.size.x;
|
||||||
|
framebufferParams.height = m_config.size.y;
|
||||||
|
framebufferParams.depth = m_config.depthSize;
|
||||||
|
|
||||||
|
m_framebuffers["default"] = new CDefaultFramebuffer(framebufferParams);
|
||||||
|
|
||||||
|
GetLogger()->Info("CDevice created successfully\n");
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CGL33Device::Destroy()
|
void CGL33Device::Destroy()
|
||||||
{
|
{
|
||||||
|
// delete shader program
|
||||||
glUseProgram(0);
|
glUseProgram(0);
|
||||||
glDeleteProgram(m_shaderProgram);
|
glDeleteProgram(m_shaderProgram);
|
||||||
|
|
||||||
if (m_framebuffer != 0)
|
// delete framebuffers
|
||||||
|
for (std::map<std::string, CFramebuffer*>::iterator i = m_framebuffers.begin(); i != m_framebuffers.end(); i++)
|
||||||
{
|
{
|
||||||
glDeleteFramebuffers(1, &m_framebuffer);
|
i->second->Destroy();
|
||||||
glDeleteRenderbuffers(1, &m_colorBuffer);
|
delete i->second;
|
||||||
glDeleteRenderbuffers(1, &m_depthBuffer);
|
|
||||||
|
|
||||||
m_framebuffer = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_framebuffers.clear();
|
||||||
|
|
||||||
// Delete the remaining textures
|
// Delete the remaining textures
|
||||||
// Should not be strictly necessary, but just in case
|
// Should not be strictly necessary, but just in case
|
||||||
DestroyAllTextures();
|
DestroyAllTextures();
|
||||||
|
@ -1443,6 +1446,8 @@ void CGL33Device::UpdateStaticBuffer(unsigned int bufferId, PrimitiveType primit
|
||||||
|
|
||||||
bool changed = (info.vertexType != VERTEX_TYPE_NORMAL) || (size > info.size);
|
bool changed = (info.vertexType != VERTEX_TYPE_NORMAL) || (size > info.size);
|
||||||
|
|
||||||
|
if (info.vertexType != VERTEX_TYPE_NORMAL) CLogger::GetInstance().Debug("Changing static buffer type\n");
|
||||||
|
|
||||||
info.primitiveType = primitiveType;
|
info.primitiveType = primitiveType;
|
||||||
info.vertexType = VERTEX_TYPE_NORMAL;
|
info.vertexType = VERTEX_TYPE_NORMAL;
|
||||||
info.vertexCount = vertexCount;
|
info.vertexCount = vertexCount;
|
||||||
|
@ -1498,6 +1503,8 @@ void CGL33Device::UpdateStaticBuffer(unsigned int bufferId, PrimitiveType primit
|
||||||
|
|
||||||
bool changed = (info.vertexType != VERTEX_TYPE_TEX2) || (size > info.size);
|
bool changed = (info.vertexType != VERTEX_TYPE_TEX2) || (size > info.size);
|
||||||
|
|
||||||
|
if (info.vertexType != VERTEX_TYPE_TEX2) CLogger::GetInstance().Debug("Changing static buffer type\n");
|
||||||
|
|
||||||
info.primitiveType = primitiveType;
|
info.primitiveType = primitiveType;
|
||||||
info.vertexType = VERTEX_TYPE_TEX2;
|
info.vertexType = VERTEX_TYPE_TEX2;
|
||||||
info.vertexCount = vertexCount;
|
info.vertexCount = vertexCount;
|
||||||
|
@ -1551,7 +1558,9 @@ void CGL33Device::UpdateStaticBuffer(unsigned int bufferId, PrimitiveType primit
|
||||||
|
|
||||||
unsigned int size = vertexCount * sizeof(VertexCol);
|
unsigned int size = vertexCount * sizeof(VertexCol);
|
||||||
|
|
||||||
bool changed = (info.vertexType != VERTEX_TYPE_TEX2) || (size > info.size);
|
bool changed = (info.vertexType != VERTEX_TYPE_COL) || (size > info.size);
|
||||||
|
|
||||||
|
if (info.vertexType != VERTEX_TYPE_NORMAL) CLogger::GetInstance().Debug("Changing static buffer type\n");
|
||||||
|
|
||||||
info.primitiveType = primitiveType;
|
info.primitiveType = primitiveType;
|
||||||
info.vertexType = VERTEX_TYPE_COL;
|
info.vertexType = VERTEX_TYPE_COL;
|
||||||
|
@ -1735,19 +1744,6 @@ void CGL33Device::SetRenderState(RenderState state, bool enabled)
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (state == RENDER_STATE_OFFSCREEN_RENDERING)
|
|
||||||
{
|
|
||||||
if (m_framebuffer == 0)
|
|
||||||
InitOffscreenBuffer(1024, 1024);
|
|
||||||
|
|
||||||
m_offscreenRenderingEnabled = enabled;
|
|
||||||
|
|
||||||
GLuint toBind = (enabled ? m_framebuffer : 0);
|
|
||||||
|
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, toBind);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else if (state == RENDER_STATE_FOG)
|
else if (state == RENDER_STATE_FOG)
|
||||||
{
|
{
|
||||||
glUniform1i(uni_FogEnabled, enabled ? 1 : 0);
|
glUniform1i(uni_FogEnabled, enabled ? 1 : 0);
|
||||||
|
@ -1860,76 +1856,6 @@ void CGL33Device::SetFillMode(FillMode mode)
|
||||||
else assert(false);
|
else assert(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CGL33Device::InitOffscreenBuffer(int width, int height)
|
|
||||||
{
|
|
||||||
width = Math::Min(width, m_maxRenderbufferSize);
|
|
||||||
height = Math::Min(height, m_maxRenderbufferSize);
|
|
||||||
|
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
|
||||||
|
|
||||||
if (m_colorBuffer != 0)
|
|
||||||
glDeleteRenderbuffers(1, &m_colorBuffer);
|
|
||||||
|
|
||||||
glGenRenderbuffers(1, &m_colorBuffer);
|
|
||||||
glBindRenderbuffer(GL_RENDERBUFFER, m_colorBuffer);
|
|
||||||
glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, width, height);
|
|
||||||
glBindRenderbuffer(GL_RENDERBUFFER, 0);
|
|
||||||
|
|
||||||
if (m_depthBuffer != 0)
|
|
||||||
glDeleteRenderbuffers(1, &m_depthBuffer);
|
|
||||||
|
|
||||||
glGenRenderbuffers(1, &m_depthBuffer);
|
|
||||||
glBindRenderbuffer(GL_RENDERBUFFER, m_depthBuffer);
|
|
||||||
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, width, height);
|
|
||||||
glBindRenderbuffer(GL_RENDERBUFFER, 0);
|
|
||||||
|
|
||||||
if (m_framebuffer == 0)
|
|
||||||
glGenFramebuffers(1, &m_framebuffer);
|
|
||||||
|
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, m_framebuffer);
|
|
||||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_colorBuffer);
|
|
||||||
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_depthBuffer);
|
|
||||||
glBindFramebufferEXT(GL_FRAMEBUFFER, 0);
|
|
||||||
|
|
||||||
GetLogger()->Info("Initialized offscreen buffer %dx%d\n", width, height);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CGL33Device::SetRenderTexture(RenderTarget target, int texture)
|
|
||||||
{
|
|
||||||
if (!m_offscreenRenderingEnabled) return;
|
|
||||||
|
|
||||||
GLenum attachment;
|
|
||||||
GLuint defaultBuffer;
|
|
||||||
|
|
||||||
switch (target)
|
|
||||||
{
|
|
||||||
case RENDER_TARGET_COLOR:
|
|
||||||
attachment = GL_COLOR_ATTACHMENT0;
|
|
||||||
defaultBuffer = m_colorBuffer;
|
|
||||||
break;
|
|
||||||
case RENDER_TARGET_DEPTH:
|
|
||||||
attachment = GL_DEPTH_ATTACHMENT;
|
|
||||||
defaultBuffer = m_depthBuffer;
|
|
||||||
break;
|
|
||||||
case RENDER_TARGET_STENCIL:
|
|
||||||
attachment = GL_STENCIL_ATTACHMENT;
|
|
||||||
defaultBuffer = 0;
|
|
||||||
break;
|
|
||||||
default: assert(false); break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (texture == 0) // unbind texture and bind default buffer
|
|
||||||
{
|
|
||||||
glFramebufferTexture2DEXT(GL_FRAMEBUFFER, attachment, GL_TEXTURE_2D, 0, 0);
|
|
||||||
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER, attachment, GL_RENDERBUFFER, defaultBuffer);
|
|
||||||
}
|
|
||||||
else // unbind default buffer and bind texture
|
|
||||||
{
|
|
||||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, attachment, GL_RENDERBUFFER, 0);
|
|
||||||
glFramebufferTexture2D(GL_FRAMEBUFFER, attachment, GL_TEXTURE_2D, texture, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CGL33Device::CopyFramebufferToTexture(Texture& texture, int xOffset, int yOffset, int x, int y, int width, int height)
|
void CGL33Device::CopyFramebufferToTexture(Texture& texture, int xOffset, int yOffset, int x, int y, int width, int height)
|
||||||
{
|
{
|
||||||
if (texture.id == 0) return;
|
if (texture.id == 0) return;
|
||||||
|
@ -1957,6 +1883,47 @@ void* CGL33Device::GetFrameBufferPixels() const
|
||||||
return static_cast<void*>(p);
|
return static_cast<void*>(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CFramebuffer* CGL33Device::GetFramebuffer(std::string name)
|
||||||
|
{
|
||||||
|
if (m_framebuffers.find(name) != m_framebuffers.end())
|
||||||
|
return m_framebuffers[name];
|
||||||
|
else
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
CFramebuffer* CGL33Device::CreateFramebuffer(std::string name, const FramebufferParams& params)
|
||||||
|
{
|
||||||
|
// existing framebuffer was found
|
||||||
|
if (m_framebuffers.find(name) != m_framebuffers.end())
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CGLFramebuffer* framebuffer = new CGLFramebuffer(params);
|
||||||
|
framebuffer->Create();
|
||||||
|
|
||||||
|
m_framebuffers[name] = framebuffer;
|
||||||
|
return framebuffer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CGL33Device::DeleteFramebuffer(std::string name)
|
||||||
|
{
|
||||||
|
// can't delete default framebuffer
|
||||||
|
if (name == "default") return;
|
||||||
|
|
||||||
|
auto position = m_framebuffers.find(name);
|
||||||
|
|
||||||
|
if (position != m_framebuffers.end())
|
||||||
|
{
|
||||||
|
position->second->Destroy();
|
||||||
|
delete position->second;
|
||||||
|
|
||||||
|
m_framebuffers.erase(position);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void CGL33Device::UpdateRenderingMode()
|
void CGL33Device::UpdateRenderingMode()
|
||||||
{
|
{
|
||||||
bool enabled = m_texturesEnabled[0] && m_currentTextures[0].id != 0;
|
bool enabled = m_texturesEnabled[0] && m_currentTextures[0].id != 0;
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
|
|
||||||
#include "graphics/core/device.h"
|
#include "graphics/core/device.h"
|
||||||
#include "graphics/opengl/glutil.h"
|
#include "graphics/opengl/glutil.h"
|
||||||
|
#include "graphics/opengl/glframebuffer.h"
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
@ -135,14 +136,16 @@ public:
|
||||||
|
|
||||||
virtual void SetFillMode(FillMode mode) OVERRIDE;
|
virtual void SetFillMode(FillMode mode) OVERRIDE;
|
||||||
|
|
||||||
virtual void InitOffscreenBuffer(int width, int height) OVERRIDE;
|
|
||||||
|
|
||||||
virtual void SetRenderTexture(RenderTarget target, int texture) OVERRIDE;
|
|
||||||
|
|
||||||
virtual void CopyFramebufferToTexture(Texture& texture, int xOffset, int yOffset, int x, int y, 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;
|
virtual void* GetFrameBufferPixels() const OVERRIDE;
|
||||||
|
|
||||||
|
virtual CFramebuffer* GetFramebuffer(std::string name) OVERRIDE;
|
||||||
|
|
||||||
|
virtual CFramebuffer* CreateFramebuffer(std::string name, const FramebufferParams& params) OVERRIDE;
|
||||||
|
|
||||||
|
virtual void DeleteFramebuffer(std::string name) OVERRIDE;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
//! Updates position for given light based on transformation matrices
|
//! Updates position for given light based on transformation matrices
|
||||||
void UpdateLightPosition(int index);
|
void UpdateLightPosition(int index);
|
||||||
|
@ -224,17 +227,8 @@ private:
|
||||||
//! Currently bound VAO
|
//! Currently bound VAO
|
||||||
GLuint m_currentVAO;
|
GLuint m_currentVAO;
|
||||||
|
|
||||||
// Offscreen buffer
|
//! Map of framebuffers
|
||||||
//! Framebuffer object
|
std::map<std::string, CFramebuffer*> m_framebuffers;
|
||||||
GLuint m_framebuffer;
|
|
||||||
//! Color renderbuffer
|
|
||||||
GLuint m_colorBuffer;
|
|
||||||
//! Depth renderbuffer
|
|
||||||
GLuint m_depthBuffer;
|
|
||||||
//! Maximum available renderbuffer size
|
|
||||||
int m_maxRenderbufferSize;
|
|
||||||
//! true if offscreen rendering is enabled
|
|
||||||
bool m_offscreenRenderingEnabled;
|
|
||||||
|
|
||||||
//! Shader program
|
//! Shader program
|
||||||
GLuint m_shaderProgram;
|
GLuint m_shaderProgram;
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
|
|
||||||
|
|
||||||
#include "graphics/opengl/gldevice.h"
|
#include "graphics/opengl/gldevice.h"
|
||||||
|
#include "graphics/opengl/glframebuffer.h"
|
||||||
#include "graphics/engine/engine.h"
|
#include "graphics/engine/engine.h"
|
||||||
|
|
||||||
#include "common/config.h"
|
#include "common/config.h"
|
||||||
|
@ -50,11 +51,6 @@ CGLDevice::CGLDevice(const DeviceConfig &config)
|
||||||
m_glMinor = 1;
|
m_glMinor = 1;
|
||||||
m_shadowMappingSupport = SMS_NONE;
|
m_shadowMappingSupport = SMS_NONE;
|
||||||
m_shadowAmbientSupported = false;
|
m_shadowAmbientSupported = false;
|
||||||
|
|
||||||
m_framebuffer = 0;
|
|
||||||
m_colorBuffer = 0;
|
|
||||||
m_depthBuffer = 0;
|
|
||||||
m_offscreenRenderingEnabled = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -197,15 +193,6 @@ bool CGLDevice::Create()
|
||||||
if (!m_multitextureAvailable)
|
if (!m_multitextureAvailable)
|
||||||
GetLogger()->Warn("GLEW reports multitexturing not supported - graphics quality will be degraded!\n");
|
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
|
// Detect Shadow mapping support
|
||||||
if (m_glMajor >= 2 || m_glMinor >= 4) // Core depth texture+shadow, OpenGL 1.4+
|
if (m_glMajor >= 2 || m_glMinor >= 4) // Core depth texture+shadow, OpenGL 1.4+
|
||||||
{
|
{
|
||||||
|
@ -304,6 +291,19 @@ bool CGLDevice::Create()
|
||||||
m_texturesEnabled = std::vector<bool> (maxTextures, false);
|
m_texturesEnabled = std::vector<bool> (maxTextures, false);
|
||||||
m_textureStageParams = std::vector<TextureStageParams>(maxTextures, TextureStageParams());
|
m_textureStageParams = std::vector<TextureStageParams>(maxTextures, TextureStageParams());
|
||||||
|
|
||||||
|
// create default framebuffer object
|
||||||
|
FramebufferParams framebufferParams;
|
||||||
|
|
||||||
|
framebufferParams.width = m_config.size.x;
|
||||||
|
framebufferParams.height = m_config.size.y;
|
||||||
|
framebufferParams.depth = m_config.depthSize;
|
||||||
|
|
||||||
|
m_framebuffers["default"] = new CDefaultFramebuffer(framebufferParams);
|
||||||
|
|
||||||
|
m_framebufferSupport = DetectFramebufferSupport();
|
||||||
|
if (m_framebufferSupport != FBS_NONE)
|
||||||
|
GetLogger()->Debug("Framebuffer supported\n");
|
||||||
|
|
||||||
GetLogger()->Info("CDevice created successfully\n");
|
GetLogger()->Info("CDevice created successfully\n");
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -311,6 +311,15 @@ bool CGLDevice::Create()
|
||||||
|
|
||||||
void CGLDevice::Destroy()
|
void CGLDevice::Destroy()
|
||||||
{
|
{
|
||||||
|
// delete framebuffers
|
||||||
|
for (std::map<std::string, CFramebuffer*>::iterator i = m_framebuffers.begin(); i != m_framebuffers.end(); i++)
|
||||||
|
{
|
||||||
|
i->second->Destroy();
|
||||||
|
delete i->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_framebuffers.clear();
|
||||||
|
|
||||||
// Delete the remaining textures
|
// Delete the remaining textures
|
||||||
// Should not be strictly necessary, but just in case
|
// Should not be strictly necessary, but just in case
|
||||||
DestroyAllTextures();
|
DestroyAllTextures();
|
||||||
|
@ -774,7 +783,7 @@ Texture CGLDevice::CreateDepthTexture(int width, int height, int depth)
|
||||||
|
|
||||||
if (m_shadowAmbientSupported)
|
if (m_shadowAmbientSupported)
|
||||||
{
|
{
|
||||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FAIL_VALUE_ARB, 0.35f);
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FAIL_VALUE_ARB, 0.5f);
|
||||||
}
|
}
|
||||||
|
|
||||||
float color[] = { 1.0f, 1.0f, 1.0f, 1.0f };
|
float color[] = { 1.0f, 1.0f, 1.0f, 1.0f };
|
||||||
|
@ -1709,25 +1718,6 @@ void CGLDevice::SetRenderState(RenderState state, bool enabled)
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (state == RENDER_STATE_OFFSCREEN_RENDERING)
|
|
||||||
{
|
|
||||||
if (!m_framebufferObject)
|
|
||||||
{
|
|
||||||
GetLogger()->Error("Cannot enable offscreen rendering without framebuffer object!\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_offscreenRenderingEnabled = enabled;
|
|
||||||
|
|
||||||
if (m_framebuffer == 0)
|
|
||||||
InitOffscreenBuffer(2048, 2048);
|
|
||||||
|
|
||||||
GLuint toBind = (enabled ? m_framebuffer : 0);
|
|
||||||
|
|
||||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, toBind);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
GLenum flag = 0;
|
GLenum flag = 0;
|
||||||
|
|
||||||
|
@ -1825,79 +1815,6 @@ void CGLDevice::SetFillMode(FillMode mode)
|
||||||
else assert(false);
|
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::SetRenderTexture(RenderTarget target, int texture)
|
|
||||||
{
|
|
||||||
if (!m_framebufferObject) return;
|
|
||||||
if (!m_offscreenRenderingEnabled) return;
|
|
||||||
|
|
||||||
GLenum attachment;
|
|
||||||
GLuint defaultBuffer;
|
|
||||||
|
|
||||||
switch (target)
|
|
||||||
{
|
|
||||||
case RENDER_TARGET_COLOR:
|
|
||||||
attachment = GL_COLOR_ATTACHMENT0_EXT;
|
|
||||||
defaultBuffer = m_colorBuffer;
|
|
||||||
break;
|
|
||||||
case RENDER_TARGET_DEPTH:
|
|
||||||
attachment = GL_DEPTH_ATTACHMENT_EXT;
|
|
||||||
defaultBuffer = m_depthBuffer;
|
|
||||||
break;
|
|
||||||
case RENDER_TARGET_STENCIL:
|
|
||||||
attachment = GL_STENCIL_ATTACHMENT_EXT;
|
|
||||||
defaultBuffer = 0;
|
|
||||||
break;
|
|
||||||
default: assert(false); break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (texture == 0) // unbind texture and bind default buffer
|
|
||||||
{
|
|
||||||
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, attachment, GL_TEXTURE_2D, 0, 0);
|
|
||||||
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, attachment, GL_RENDERBUFFER_EXT, defaultBuffer);
|
|
||||||
}
|
|
||||||
else // unbind default buffer and bind texture
|
|
||||||
{
|
|
||||||
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, attachment, GL_RENDERBUFFER_EXT, 0);
|
|
||||||
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, attachment, GL_TEXTURE_2D, texture, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CGLDevice::CopyFramebufferToTexture(Texture& texture, int xOffset, int yOffset, int x, int y, int width, int height)
|
void CGLDevice::CopyFramebufferToTexture(Texture& texture, int xOffset, int yOffset, int x, int y, int width, int height)
|
||||||
{
|
{
|
||||||
if (texture.id == 0) return;
|
if (texture.id == 0) return;
|
||||||
|
@ -1927,5 +1844,54 @@ void* CGLDevice::GetFrameBufferPixels()const{
|
||||||
return static_cast<void*>(p);
|
return static_cast<void*>(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CFramebuffer* CGLDevice::GetFramebuffer(std::string name)
|
||||||
|
{
|
||||||
|
if (m_framebuffers.find(name) != m_framebuffers.end())
|
||||||
|
return m_framebuffers[name];
|
||||||
|
else
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
CFramebuffer* CGLDevice::CreateFramebuffer(std::string name, const FramebufferParams& params)
|
||||||
|
{
|
||||||
|
// existing framebuffer was found
|
||||||
|
if (m_framebuffers.find(name) != m_framebuffers.end())
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CFramebuffer *framebuffer;
|
||||||
|
|
||||||
|
if (m_framebufferSupport == FBS_ARB)
|
||||||
|
framebuffer = new CGLFramebuffer(params);
|
||||||
|
else if (m_framebufferSupport == FBS_EXT)
|
||||||
|
framebuffer = new CGLFramebufferEXT(params);
|
||||||
|
else
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
framebuffer->Create();
|
||||||
|
|
||||||
|
m_framebuffers[name] = framebuffer;
|
||||||
|
return framebuffer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CGLDevice::DeleteFramebuffer(std::string name)
|
||||||
|
{
|
||||||
|
// can't delete default framebuffer
|
||||||
|
if (name == "default") return;
|
||||||
|
|
||||||
|
auto position = m_framebuffers.find(name);
|
||||||
|
|
||||||
|
if (position != m_framebuffers.end())
|
||||||
|
{
|
||||||
|
position->second->Destroy();
|
||||||
|
delete position->second;
|
||||||
|
|
||||||
|
m_framebuffers.erase(position);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Gfx
|
} // namespace Gfx
|
||||||
|
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
|
|
||||||
#include "graphics/core/device.h"
|
#include "graphics/core/device.h"
|
||||||
#include "graphics/opengl/glutil.h"
|
#include "graphics/opengl/glutil.h"
|
||||||
|
#include "graphics/opengl/glframebuffer.h"
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
@ -155,14 +156,16 @@ public:
|
||||||
|
|
||||||
virtual void SetFillMode(FillMode mode) OVERRIDE;
|
virtual void SetFillMode(FillMode mode) OVERRIDE;
|
||||||
|
|
||||||
virtual void InitOffscreenBuffer(int width, int height) OVERRIDE;
|
|
||||||
|
|
||||||
virtual void SetRenderTexture(RenderTarget target, int texture) OVERRIDE;
|
|
||||||
|
|
||||||
virtual void CopyFramebufferToTexture(Texture& texture, int xOffset, int yOffset, int x, int y, 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;
|
virtual void* GetFrameBufferPixels() const OVERRIDE;
|
||||||
|
|
||||||
|
virtual CFramebuffer* GetFramebuffer(std::string name) OVERRIDE;
|
||||||
|
|
||||||
|
virtual CFramebuffer* CreateFramebuffer(std::string name, const FramebufferParams& params) OVERRIDE;
|
||||||
|
|
||||||
|
virtual void DeleteFramebuffer(std::string name) OVERRIDE;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
//! Updates internal modelview matrix
|
//! Updates internal modelview matrix
|
||||||
void UpdateModelviewMatrix();
|
void UpdateModelviewMatrix();
|
||||||
|
@ -204,6 +207,9 @@ private:
|
||||||
//! Set of all created textures
|
//! Set of all created textures
|
||||||
std::set<Texture> m_allTextures;
|
std::set<Texture> m_allTextures;
|
||||||
|
|
||||||
|
//! Map of framebuffers
|
||||||
|
std::map<std::string, CFramebuffer*> m_framebuffers;
|
||||||
|
|
||||||
//! Type of vertex structure
|
//! Type of vertex structure
|
||||||
enum VertexType
|
enum VertexType
|
||||||
{
|
{
|
||||||
|
@ -238,24 +244,14 @@ private:
|
||||||
int m_maxAnisotropy;
|
int m_maxAnisotropy;
|
||||||
//! Whether offscreen rendering is available
|
//! Whether offscreen rendering is available
|
||||||
bool m_framebufferObject;
|
bool m_framebufferObject;
|
||||||
|
//! Framebuffer support
|
||||||
|
FramebufferSupport m_framebufferSupport;
|
||||||
//! Which vertex buffer type to use
|
//! Which vertex buffer type to use
|
||||||
VertexBufferType m_vertexBufferType;
|
VertexBufferType m_vertexBufferType;
|
||||||
//! Map of saved VBO objects
|
//! Map of saved VBO objects
|
||||||
std::map<unsigned int, VboObjectInfo> m_vboObjects;
|
std::map<unsigned int, VboObjectInfo> m_vboObjects;
|
||||||
//! Last ID of VBO object
|
//! Last ID of VBO object
|
||||||
unsigned int m_lastVboId;
|
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;
|
|
||||||
//! true if offscreen rendering enabled
|
|
||||||
bool m_offscreenRenderingEnabled;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,471 @@
|
||||||
|
/*
|
||||||
|
* This file is part of the Colobot: Gold Edition source code
|
||||||
|
* Copyright (C) 2001-2014, Daniel Roux, EPSITEC SA & TerranovaTeam
|
||||||
|
* http://epsiteс.ch; http://colobot.info; http://github.com/colobot
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
* See the GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see http://gnu.org/licenses
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "graphics/opengl/glframebuffer.h"
|
||||||
|
|
||||||
|
#include "common/logger.h"
|
||||||
|
|
||||||
|
namespace Gfx {
|
||||||
|
|
||||||
|
// CGLFramebuffer
|
||||||
|
|
||||||
|
GLuint CGLFramebuffer::m_currentFBO = 0;
|
||||||
|
|
||||||
|
CGLFramebuffer::CGLFramebuffer(const FramebufferParams& params)
|
||||||
|
: m_params(params)
|
||||||
|
{
|
||||||
|
m_fbo = 0;
|
||||||
|
m_colorRenderbuffer = 0;
|
||||||
|
m_colorTexture = 0;
|
||||||
|
m_depthRenderbuffer = 0;
|
||||||
|
m_depthTexture = 0;
|
||||||
|
m_width = 0;
|
||||||
|
m_height = 0;
|
||||||
|
m_depth = 0;
|
||||||
|
m_samples = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CGLFramebuffer::Create()
|
||||||
|
{
|
||||||
|
if (m_fbo != 0) return;
|
||||||
|
|
||||||
|
m_width = m_params.width;
|
||||||
|
m_height = m_params.height;
|
||||||
|
m_depth = m_params.depth;
|
||||||
|
m_samples = m_params.samples;
|
||||||
|
|
||||||
|
glGenFramebuffers(1, &m_fbo);
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER, m_fbo);
|
||||||
|
|
||||||
|
// create color texture
|
||||||
|
if (m_params.colorTexture)
|
||||||
|
{
|
||||||
|
GLint previous;
|
||||||
|
glGetIntegerv(GL_TEXTURE_BINDING_2D, &previous);
|
||||||
|
|
||||||
|
glGenTextures(1, &m_colorTexture);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, m_colorTexture);
|
||||||
|
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, m_params.width, m_params.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
|
||||||
|
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||||
|
|
||||||
|
glBindTexture(GL_TEXTURE_2D, previous);
|
||||||
|
|
||||||
|
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_colorTexture, 0);
|
||||||
|
}
|
||||||
|
// create color renderbuffer
|
||||||
|
else
|
||||||
|
{
|
||||||
|
glGenRenderbuffers(1, &m_colorRenderbuffer);
|
||||||
|
glBindRenderbuffer(GL_RENDERBUFFER, m_colorRenderbuffer);
|
||||||
|
|
||||||
|
if (m_params.samples > 1)
|
||||||
|
glRenderbufferStorageMultisample(GL_RENDERBUFFER, m_params.samples, GL_RGBA8, m_params.width, m_params.height);
|
||||||
|
else
|
||||||
|
glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, m_params.width, m_params.height);
|
||||||
|
|
||||||
|
glBindRenderbuffer(GL_RENDERBUFFER, 0);
|
||||||
|
|
||||||
|
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_colorRenderbuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLuint depthFormat = 0;
|
||||||
|
|
||||||
|
switch (m_params.depth)
|
||||||
|
{
|
||||||
|
case 16: depthFormat = GL_DEPTH_COMPONENT16; break;
|
||||||
|
case 24: depthFormat = GL_DEPTH_COMPONENT24; break;
|
||||||
|
case 32: depthFormat = GL_DEPTH_COMPONENT32; break;
|
||||||
|
default: depthFormat = GL_DEPTH_COMPONENT16; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// create depth texture
|
||||||
|
if (m_params.depthTexture)
|
||||||
|
{
|
||||||
|
GLint previous;
|
||||||
|
glGetIntegerv(GL_TEXTURE_BINDING_2D, &previous);
|
||||||
|
|
||||||
|
glGenTextures(1, &m_depthTexture);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, m_depthTexture);
|
||||||
|
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 0, depthFormat, m_params.width, m_params.height, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, nullptr);
|
||||||
|
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
|
||||||
|
|
||||||
|
float color[] = { 1.0f, 1.0f, 1.0f, 1.0f };
|
||||||
|
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
|
||||||
|
glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, color);
|
||||||
|
|
||||||
|
glBindTexture(GL_TEXTURE_2D, previous);
|
||||||
|
|
||||||
|
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, m_depthTexture, 0);
|
||||||
|
}
|
||||||
|
// create depth renderbuffer
|
||||||
|
else
|
||||||
|
{
|
||||||
|
glGenRenderbuffers(1, &m_depthRenderbuffer);
|
||||||
|
glBindRenderbuffer(GL_RENDERBUFFER, m_depthRenderbuffer);
|
||||||
|
|
||||||
|
if (m_params.samples > 1)
|
||||||
|
glRenderbufferStorageMultisample(GL_RENDERBUFFER, m_params.samples, depthFormat, m_params.width, m_params.height);
|
||||||
|
else
|
||||||
|
glRenderbufferStorage(GL_RENDERBUFFER, depthFormat, m_params.width, m_params.height);
|
||||||
|
|
||||||
|
glBindRenderbuffer(GL_RENDERBUFFER, 0);
|
||||||
|
|
||||||
|
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_depthRenderbuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLuint result = glCheckFramebufferStatus(GL_FRAMEBUFFER);
|
||||||
|
if (result != GL_FRAMEBUFFER_COMPLETE)
|
||||||
|
{
|
||||||
|
GetLogger()->Error("Framebuffer incomplete\n");
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER, m_currentFBO);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CGLFramebuffer::Destroy()
|
||||||
|
{
|
||||||
|
if (m_fbo == 0) return;
|
||||||
|
|
||||||
|
if (m_currentFBO == m_fbo)
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||||
|
|
||||||
|
glDeleteFramebuffers(1, &m_fbo);
|
||||||
|
m_fbo = 0;
|
||||||
|
|
||||||
|
if (m_colorRenderbuffer != 0)
|
||||||
|
{
|
||||||
|
glDeleteRenderbuffers(1, &m_colorRenderbuffer);
|
||||||
|
m_colorRenderbuffer = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_colorTexture != 0)
|
||||||
|
{
|
||||||
|
glDeleteTextures(1, &m_colorTexture);
|
||||||
|
m_colorTexture = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_depthRenderbuffer != 0)
|
||||||
|
{
|
||||||
|
glDeleteRenderbuffers(1, &m_depthRenderbuffer);
|
||||||
|
m_depthRenderbuffer = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_depthTexture != 0)
|
||||||
|
{
|
||||||
|
glDeleteTextures(1, &m_depthTexture);
|
||||||
|
m_depthTexture = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_width = 0;
|
||||||
|
m_height = 0;
|
||||||
|
m_depth = 0;
|
||||||
|
m_samples = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CGLFramebuffer::IsDefault()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Returns width of buffers in this framebuffer
|
||||||
|
int CGLFramebuffer::GetWidth()
|
||||||
|
{
|
||||||
|
return m_width;
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Returns height of buffers in this framebuffer
|
||||||
|
int CGLFramebuffer::GetHeight()
|
||||||
|
{
|
||||||
|
return m_height;
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Returns depth size in bits
|
||||||
|
int CGLFramebuffer::GetDepth()
|
||||||
|
{
|
||||||
|
return m_depth;
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Returns number of samples or 1 if multisampling is not supported
|
||||||
|
int CGLFramebuffer::GetSamples()
|
||||||
|
{
|
||||||
|
return m_samples;
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Returns texture that contains color buffer or 0 if not available
|
||||||
|
int CGLFramebuffer::GetColorTexture()
|
||||||
|
{
|
||||||
|
return m_colorTexture;
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Returns texture that contains depth buffer or 0 if not available
|
||||||
|
int CGLFramebuffer::GetDepthTexture()
|
||||||
|
{
|
||||||
|
return m_depthTexture;
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Binds this framebuffer to context
|
||||||
|
void CGLFramebuffer::Bind()
|
||||||
|
{
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER, m_fbo);
|
||||||
|
m_currentFBO = m_fbo;
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Unbinds this framebuffer from context
|
||||||
|
void CGLFramebuffer::Unbind()
|
||||||
|
{
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||||
|
m_currentFBO = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// CGLFramebufferEXT
|
||||||
|
GLuint CGLFramebufferEXT::m_currentFBO = 0;
|
||||||
|
|
||||||
|
CGLFramebufferEXT::CGLFramebufferEXT(const FramebufferParams& params)
|
||||||
|
: m_params(params)
|
||||||
|
{
|
||||||
|
m_fbo = 0;
|
||||||
|
m_colorRenderbuffer = 0;
|
||||||
|
m_colorTexture = 0;
|
||||||
|
m_depthRenderbuffer = 0;
|
||||||
|
m_depthTexture = 0;
|
||||||
|
m_width = 0;
|
||||||
|
m_height = 0;
|
||||||
|
m_depth = 0;
|
||||||
|
m_samples = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CGLFramebufferEXT::Create()
|
||||||
|
{
|
||||||
|
if (m_fbo != 0) return;
|
||||||
|
|
||||||
|
m_width = m_params.width;
|
||||||
|
m_height = m_params.height;
|
||||||
|
m_depth = m_params.depth;
|
||||||
|
m_samples = m_params.samples;
|
||||||
|
|
||||||
|
glGenFramebuffersEXT(1, &m_fbo);
|
||||||
|
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fbo);
|
||||||
|
|
||||||
|
// create color texture
|
||||||
|
if (m_params.colorTexture)
|
||||||
|
{
|
||||||
|
GLint previous;
|
||||||
|
glGetIntegerv(GL_TEXTURE_BINDING_2D, &previous);
|
||||||
|
|
||||||
|
glGenTextures(1, &m_colorTexture);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, m_colorTexture);
|
||||||
|
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, m_params.width, m_params.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
|
||||||
|
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||||
|
|
||||||
|
glBindTexture(GL_TEXTURE_2D, previous);
|
||||||
|
|
||||||
|
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, m_colorTexture, 0);
|
||||||
|
}
|
||||||
|
// create color renderbuffer
|
||||||
|
else
|
||||||
|
{
|
||||||
|
glGenRenderbuffersEXT(1, &m_colorRenderbuffer);
|
||||||
|
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_colorRenderbuffer);
|
||||||
|
|
||||||
|
if (m_params.samples > 1)
|
||||||
|
glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, m_params.samples, GL_RGBA8, m_params.width, m_params.height);
|
||||||
|
else
|
||||||
|
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_RGBA8, m_params.width, m_params.height);
|
||||||
|
|
||||||
|
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
|
||||||
|
|
||||||
|
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, m_colorRenderbuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLuint depthFormat = 0;
|
||||||
|
|
||||||
|
switch (m_params.depth)
|
||||||
|
{
|
||||||
|
case 16: depthFormat = GL_DEPTH_COMPONENT16; break;
|
||||||
|
case 24: depthFormat = GL_DEPTH_COMPONENT24; break;
|
||||||
|
case 32: depthFormat = GL_DEPTH_COMPONENT32; break;
|
||||||
|
default: depthFormat = GL_DEPTH_COMPONENT16; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// create depth texture
|
||||||
|
if (m_params.depthTexture)
|
||||||
|
{
|
||||||
|
GLint previous;
|
||||||
|
glGetIntegerv(GL_TEXTURE_BINDING_2D, &previous);
|
||||||
|
|
||||||
|
glGenTextures(1, &m_depthTexture);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, m_depthTexture);
|
||||||
|
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 0, depthFormat, m_params.width, m_params.height, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, nullptr);
|
||||||
|
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
|
||||||
|
|
||||||
|
float color[] = { 1.0f, 1.0f, 1.0f, 1.0f };
|
||||||
|
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
|
||||||
|
glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, color);
|
||||||
|
|
||||||
|
glBindTexture(GL_TEXTURE_2D, previous);
|
||||||
|
|
||||||
|
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, m_depthTexture, 0);
|
||||||
|
}
|
||||||
|
// create depth renderbuffer
|
||||||
|
else
|
||||||
|
{
|
||||||
|
glGenRenderbuffersEXT(1, &m_depthRenderbuffer);
|
||||||
|
glBindRenderbufferEXT(GL_RENDERBUFFER, m_depthRenderbuffer);
|
||||||
|
|
||||||
|
if (m_params.samples > 1)
|
||||||
|
glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, m_params.samples, depthFormat, m_params.width, m_params.height);
|
||||||
|
else
|
||||||
|
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, depthFormat, m_params.width, m_params.height);
|
||||||
|
|
||||||
|
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
|
||||||
|
|
||||||
|
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, m_depthRenderbuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLuint result = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
|
||||||
|
if (result != GL_FRAMEBUFFER_COMPLETE_EXT)
|
||||||
|
{
|
||||||
|
GetLogger()->Error("Framebuffer incomplete: %d\n", result);
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_currentFBO);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CGLFramebufferEXT::Destroy()
|
||||||
|
{
|
||||||
|
if (m_fbo == 0) return;
|
||||||
|
|
||||||
|
if (m_currentFBO == m_fbo)
|
||||||
|
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
|
||||||
|
|
||||||
|
glDeleteFramebuffersEXT(1, &m_fbo);
|
||||||
|
m_fbo = 0;
|
||||||
|
|
||||||
|
if (m_colorRenderbuffer != 0)
|
||||||
|
{
|
||||||
|
glDeleteRenderbuffersEXT(1, &m_colorRenderbuffer);
|
||||||
|
m_colorRenderbuffer = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_colorTexture != 0)
|
||||||
|
{
|
||||||
|
glDeleteTextures(1, &m_colorTexture);
|
||||||
|
m_colorTexture = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_depthRenderbuffer != 0)
|
||||||
|
{
|
||||||
|
glDeleteRenderbuffersEXT(1, &m_depthRenderbuffer);
|
||||||
|
m_depthRenderbuffer = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_depthTexture != 0)
|
||||||
|
{
|
||||||
|
glDeleteTextures(1, &m_depthTexture);
|
||||||
|
m_depthTexture = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_width = 0;
|
||||||
|
m_height = 0;
|
||||||
|
m_depth = 0;
|
||||||
|
m_samples = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CGLFramebufferEXT::IsDefault()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Returns width of buffers in this framebuffer
|
||||||
|
int CGLFramebufferEXT::GetWidth()
|
||||||
|
{
|
||||||
|
return m_width;
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Returns height of buffers in this framebuffer
|
||||||
|
int CGLFramebufferEXT::GetHeight()
|
||||||
|
{
|
||||||
|
return m_height;
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Returns depth size in bits
|
||||||
|
int CGLFramebufferEXT::GetDepth()
|
||||||
|
{
|
||||||
|
return m_depth;
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Returns number of samples or 1 if multisampling is not supported
|
||||||
|
int CGLFramebufferEXT::GetSamples()
|
||||||
|
{
|
||||||
|
return m_samples;
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Returns texture that contains color buffer or 0 if not available
|
||||||
|
int CGLFramebufferEXT::GetColorTexture()
|
||||||
|
{
|
||||||
|
return m_colorTexture;
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Returns texture that contains depth buffer or 0 if not available
|
||||||
|
int CGLFramebufferEXT::GetDepthTexture()
|
||||||
|
{
|
||||||
|
return m_depthTexture;
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Binds this framebuffer to context
|
||||||
|
void CGLFramebufferEXT::Bind()
|
||||||
|
{
|
||||||
|
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fbo);
|
||||||
|
m_currentFBO = m_fbo;
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Unbinds this framebuffer from context
|
||||||
|
void CGLFramebufferEXT::Unbind()
|
||||||
|
{
|
||||||
|
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
|
||||||
|
m_currentFBO = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // end of Gfx
|
|
@ -0,0 +1,123 @@
|
||||||
|
/*
|
||||||
|
* This file is part of the Colobot: Gold Edition source code
|
||||||
|
* Copyright (C) 2001-2014, Daniel Roux, EPSITEC SA & TerranovaTeam
|
||||||
|
* http://epsiteс.ch; http://colobot.info; http://github.com/colobot
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
* See the GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see http://gnu.org/licenses
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "graphics/core/framebuffer.h"
|
||||||
|
#include "graphics/opengl/glutil.h"
|
||||||
|
|
||||||
|
namespace Gfx {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \class CGLFramebuffer
|
||||||
|
* \brief Implementation of CFramebuffer interface in OpenGL 3.0+
|
||||||
|
*
|
||||||
|
* Provides the concrete implementation of core framebuffers.
|
||||||
|
* Can be used in OpenGL 3.0+ and with ARB_framebuffer_object supported.
|
||||||
|
*/
|
||||||
|
class CGLFramebuffer : public CFramebuffer
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
FramebufferParams m_params;
|
||||||
|
|
||||||
|
int m_width, m_height, m_depth, m_samples;
|
||||||
|
|
||||||
|
GLuint m_fbo;
|
||||||
|
GLuint m_colorRenderbuffer;
|
||||||
|
GLuint m_colorTexture;
|
||||||
|
GLuint m_depthRenderbuffer;
|
||||||
|
GLuint m_depthTexture;
|
||||||
|
|
||||||
|
static GLuint m_currentFBO;
|
||||||
|
|
||||||
|
public:
|
||||||
|
CGLFramebuffer(const FramebufferParams& params);
|
||||||
|
|
||||||
|
virtual void Create() OVERRIDE;
|
||||||
|
|
||||||
|
virtual void Destroy() OVERRIDE;
|
||||||
|
|
||||||
|
virtual bool IsDefault() OVERRIDE;
|
||||||
|
|
||||||
|
virtual int GetWidth() OVERRIDE;
|
||||||
|
|
||||||
|
virtual int GetHeight() OVERRIDE;
|
||||||
|
|
||||||
|
virtual int GetDepth() OVERRIDE;
|
||||||
|
|
||||||
|
virtual int GetSamples() OVERRIDE;
|
||||||
|
|
||||||
|
virtual int GetColorTexture() OVERRIDE;
|
||||||
|
|
||||||
|
virtual int GetDepthTexture() OVERRIDE;
|
||||||
|
|
||||||
|
virtual void Bind() OVERRIDE;
|
||||||
|
|
||||||
|
virtual void Unbind() OVERRIDE;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \class CGLFramebuffer
|
||||||
|
* \brief Implementation of CFramebuffer interface in legacy OpenGL
|
||||||
|
*
|
||||||
|
* Provides the concrete implementation of extension framebuffers.
|
||||||
|
* Can be used with EXT_framebuffer_object supported.
|
||||||
|
*/
|
||||||
|
class CGLFramebufferEXT : public CFramebuffer
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
FramebufferParams m_params;
|
||||||
|
|
||||||
|
int m_width, m_height, m_depth, m_samples;
|
||||||
|
|
||||||
|
GLuint m_fbo;
|
||||||
|
GLuint m_colorRenderbuffer;
|
||||||
|
GLuint m_colorTexture;
|
||||||
|
GLuint m_depthRenderbuffer;
|
||||||
|
GLuint m_depthTexture;
|
||||||
|
|
||||||
|
static GLuint m_currentFBO;
|
||||||
|
|
||||||
|
public:
|
||||||
|
CGLFramebufferEXT(const FramebufferParams& params);
|
||||||
|
|
||||||
|
virtual void Create() OVERRIDE;
|
||||||
|
|
||||||
|
virtual void Destroy() OVERRIDE;
|
||||||
|
|
||||||
|
virtual bool IsDefault() OVERRIDE;
|
||||||
|
|
||||||
|
virtual int GetWidth() OVERRIDE;
|
||||||
|
|
||||||
|
virtual int GetHeight() OVERRIDE;
|
||||||
|
|
||||||
|
virtual int GetDepth() OVERRIDE;
|
||||||
|
|
||||||
|
virtual int GetSamples() OVERRIDE;
|
||||||
|
|
||||||
|
virtual int GetColorTexture() OVERRIDE;
|
||||||
|
|
||||||
|
virtual int GetDepthTexture() OVERRIDE;
|
||||||
|
|
||||||
|
virtual void Bind() OVERRIDE;
|
||||||
|
|
||||||
|
virtual void Unbind() OVERRIDE;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // end of Gfx
|
|
@ -31,6 +31,14 @@ namespace Gfx {
|
||||||
GLuint textureCoordinates[] = { GL_S, GL_T, GL_R, GL_Q };
|
GLuint textureCoordinates[] = { GL_S, GL_T, GL_R, GL_Q };
|
||||||
GLuint textureCoordGen[] = { GL_TEXTURE_GEN_S, GL_TEXTURE_GEN_T, GL_TEXTURE_GEN_R, GL_TEXTURE_GEN_Q };
|
GLuint textureCoordGen[] = { GL_TEXTURE_GEN_S, GL_TEXTURE_GEN_T, GL_TEXTURE_GEN_R, GL_TEXTURE_GEN_Q };
|
||||||
|
|
||||||
|
FramebufferSupport DetectFramebufferSupport()
|
||||||
|
{
|
||||||
|
if (GetOpenGLVersion() >= 30) return FBS_ARB;
|
||||||
|
if (glewIsSupported("GL_ARB_framebuffer_object")) return FBS_ARB;
|
||||||
|
if (glewIsSupported("GL_EXT_framebuffer_object")) return FBS_EXT;
|
||||||
|
return FBS_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
CDevice* CreateDevice(const DeviceConfig &config, const char *name)
|
CDevice* CreateDevice(const DeviceConfig &config, const char *name)
|
||||||
{
|
{
|
||||||
if (name == nullptr) return nullptr;
|
if (name == nullptr) return nullptr;
|
||||||
|
|
|
@ -31,6 +31,15 @@
|
||||||
namespace Gfx
|
namespace Gfx
|
||||||
{
|
{
|
||||||
|
|
||||||
|
enum FramebufferSupport
|
||||||
|
{
|
||||||
|
FBS_NONE,
|
||||||
|
FBS_EXT,
|
||||||
|
FBS_ARB,
|
||||||
|
};
|
||||||
|
|
||||||
|
FramebufferSupport DetectFramebufferSupport();
|
||||||
|
|
||||||
//! Creates OpenGL device
|
//! Creates OpenGL device
|
||||||
CDevice* CreateDevice(const DeviceConfig &config, const char *name);
|
CDevice* CreateDevice(const DeviceConfig &config, const char *name);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue