Added support for creation of a stencil attachment and multisampling to sf::RenderTexture.

This commit is contained in:
binary1248 2017-09-17 17:08:49 +02:00 committed by Lukas Dürrenberger
parent b0f3611ab9
commit 421e8bb812
11 changed files with 414 additions and 63 deletions

View File

@ -31,6 +31,7 @@
#include <SFML/Graphics/Export.hpp>
#include <SFML/Graphics/Texture.hpp>
#include <SFML/Graphics/RenderTarget.hpp>
#include <SFML/Window/ContextSettings.hpp>
namespace sf
@ -82,8 +83,38 @@ public:
///
/// \return True if creation has been successful
///
/// \deprecated Use create(unsigned int, unsigned int, const ContextSettings&) instead.
///
////////////////////////////////////////////////////////////
bool create(unsigned int width, unsigned int height, bool depthBuffer = false);
SFML_DEPRECATED bool create(unsigned int width, unsigned int height, bool depthBuffer);
////////////////////////////////////////////////////////////
/// \brief Create the render-texture
///
/// Before calling this function, the render-texture is in
/// an invalid state, thus it is mandatory to call it before
/// doing anything with the render-texture.
/// The last parameter, \a settings, is useful if you want to enable
/// multi-sampling or use the render-texture for OpenGL rendering that
/// requires a depth or stencil buffer. Otherwise it is unnecessary, and
/// you should leave this parameter at its default value.
///
/// \param width Width of the render-texture
/// \param height Height of the render-texture
/// \param settings Additional settings for the underlying OpenGL texture and context
///
/// \return True if creation has been successful
///
////////////////////////////////////////////////////////////
bool create(unsigned int width, unsigned int height, const ContextSettings& settings = ContextSettings());
////////////////////////////////////////////////////////////
/// \brief Get the maximum anti-aliasing level supported by the system
///
/// \return The maximum anti-aliasing level supported by the system
///
////////////////////////////////////////////////////////////
static unsigned int getMaximumAntialiasingLevel();
////////////////////////////////////////////////////////////
/// \brief Enable or disable texture smoothing

View File

@ -124,9 +124,15 @@
#define GLEXT_GL_FRAMEBUFFER_BINDING GL_FRAMEBUFFER_BINDING_OES
#define GLEXT_GL_INVALID_FRAMEBUFFER_OPERATION GL_INVALID_FRAMEBUFFER_OPERATION_OES
// Core since 3.0
#define GLEXT_packed_depth_stencil false
// Core since 3.0
#define GLEXT_framebuffer_blit false
// Core since 3.0
#define GLEXT_framebuffer_multisample false
// Core since 3.0 - NV_copy_buffer
#define GLEXT_copy_buffer false
@ -277,6 +283,11 @@
#define GLEXT_GL_FRAMEBUFFER_COMPLETE GL_FRAMEBUFFER_COMPLETE_EXT
#define GLEXT_GL_FRAMEBUFFER_BINDING GL_FRAMEBUFFER_BINDING_EXT
#define GLEXT_GL_INVALID_FRAMEBUFFER_OPERATION GL_INVALID_FRAMEBUFFER_OPERATION_EXT
#define GLEXT_GL_STENCIL_ATTACHMENT GL_STENCIL_ATTACHMENT_EXT
// Core since 3.0 - EXT_packed_depth_stencil
#define GLEXT_packed_depth_stencil sfogl_ext_EXT_packed_depth_stencil
#define GLEXT_GL_DEPTH24_STENCIL8 GL_DEPTH24_STENCIL8_EXT
// Core since 3.0 - EXT_framebuffer_blit
#define GLEXT_framebuffer_blit sfogl_ext_EXT_framebuffer_blit
@ -286,6 +297,11 @@
#define GLEXT_GL_DRAW_FRAMEBUFFER_BINDING GL_DRAW_FRAMEBUFFER_BINDING_EXT
#define GLEXT_GL_READ_FRAMEBUFFER_BINDING GL_READ_FRAMEBUFFER_BINDING_EXT
// Core since 3.0 - EXT_framebuffer_multisample
#define GLEXT_framebuffer_multisample sfogl_ext_EXT_framebuffer_multisample
#define GLEXT_glRenderbufferStorageMultisample glRenderbufferStorageMultisampleEXT
#define GLEXT_GL_MAX_SAMPLES GL_MAX_SAMPLES_EXT
// Core since 3.1 - ARB_copy_buffer
#define GLEXT_copy_buffer sfogl_ext_ARB_copy_buffer
#define GLEXT_GL_COPY_READ_BUFFER GL_COPY_READ_BUFFER

View File

@ -16,6 +16,8 @@ ARB_texture_non_power_of_two
EXT_blend_equation_separate
EXT_texture_sRGB
EXT_framebuffer_object
EXT_packed_depth_stencil
EXT_framebuffer_blit
EXT_framebuffer_multisample
ARB_copy_buffer
ARB_geometry_shader4

View File

@ -48,7 +48,9 @@ int sfogl_ext_ARB_texture_non_power_of_two = sfogl_LOAD_FAILED;
int sfogl_ext_EXT_blend_equation_separate = sfogl_LOAD_FAILED;
int sfogl_ext_EXT_texture_sRGB = sfogl_LOAD_FAILED;
int sfogl_ext_EXT_framebuffer_object = sfogl_LOAD_FAILED;
int sfogl_ext_EXT_packed_depth_stencil = sfogl_LOAD_FAILED;
int sfogl_ext_EXT_framebuffer_blit = sfogl_LOAD_FAILED;
int sfogl_ext_EXT_framebuffer_multisample = sfogl_LOAD_FAILED;
int sfogl_ext_ARB_copy_buffer = sfogl_LOAD_FAILED;
int sfogl_ext_ARB_geometry_shader4 = sfogl_LOAD_FAILED;
@ -879,6 +881,19 @@ static int Load_EXT_framebuffer_blit()
return numFailed;
}
void (GL_FUNCPTR *sf_ptrc_glRenderbufferStorageMultisampleEXT)(GLenum, GLsizei, GLenum, GLsizei, GLsizei) = NULL;
static int Load_EXT_framebuffer_multisample()
{
int numFailed = 0;
sf_ptrc_glRenderbufferStorageMultisampleEXT = reinterpret_cast<void (GL_FUNCPTR *)(GLenum, GLsizei, GLenum, GLsizei, GLsizei)>(glLoaderGetProcAddress("glRenderbufferStorageMultisampleEXT"));
if (!sf_ptrc_glRenderbufferStorageMultisampleEXT)
numFailed++;
return numFailed;
}
void (GL_FUNCPTR *sf_ptrc_glCopyBufferSubData)(GLenum, GLenum, GLintptr, GLintptr, GLsizeiptr) = NULL;
static int Load_ARB_copy_buffer()
@ -928,7 +943,7 @@ typedef struct sfogl_StrToExtMap_s
PFN_LOADFUNCPOINTERS LoadExtension;
} sfogl_StrToExtMap;
static sfogl_StrToExtMap ExtensionMap[18] = {
static sfogl_StrToExtMap ExtensionMap[20] = {
{"GL_SGIS_texture_edge_clamp", &sfogl_ext_SGIS_texture_edge_clamp, NULL},
{"GL_EXT_texture_edge_clamp", &sfogl_ext_EXT_texture_edge_clamp, NULL},
{"GL_EXT_blend_minmax", &sfogl_ext_EXT_blend_minmax, Load_EXT_blend_minmax},
@ -944,12 +959,14 @@ static sfogl_StrToExtMap ExtensionMap[18] = {
{"GL_EXT_blend_equation_separate", &sfogl_ext_EXT_blend_equation_separate, Load_EXT_blend_equation_separate},
{"GL_EXT_texture_sRGB", &sfogl_ext_EXT_texture_sRGB, NULL},
{"GL_EXT_framebuffer_object", &sfogl_ext_EXT_framebuffer_object, Load_EXT_framebuffer_object},
{"GL_EXT_packed_depth_stencil", &sfogl_ext_EXT_packed_depth_stencil, NULL},
{"GL_EXT_framebuffer_blit", &sfogl_ext_EXT_framebuffer_blit, Load_EXT_framebuffer_blit},
{"GL_EXT_framebuffer_multisample", &sfogl_ext_EXT_framebuffer_multisample, Load_EXT_framebuffer_multisample},
{"GL_ARB_copy_buffer", &sfogl_ext_ARB_copy_buffer, Load_ARB_copy_buffer},
{"GL_ARB_geometry_shader4", &sfogl_ext_ARB_geometry_shader4, Load_ARB_geometry_shader4}
};
static int g_extensionMapSize = 18;
static int g_extensionMapSize = 20;
static void ClearExtensionVars()
@ -969,7 +986,9 @@ static void ClearExtensionVars()
sfogl_ext_EXT_blend_equation_separate = sfogl_LOAD_FAILED;
sfogl_ext_EXT_texture_sRGB = sfogl_LOAD_FAILED;
sfogl_ext_EXT_framebuffer_object = sfogl_LOAD_FAILED;
sfogl_ext_EXT_packed_depth_stencil = sfogl_LOAD_FAILED;
sfogl_ext_EXT_framebuffer_blit = sfogl_LOAD_FAILED;
sfogl_ext_EXT_framebuffer_multisample = sfogl_LOAD_FAILED;
sfogl_ext_ARB_copy_buffer = sfogl_LOAD_FAILED;
sfogl_ext_ARB_geometry_shader4 = sfogl_LOAD_FAILED;
}

View File

@ -185,7 +185,9 @@ extern int sfogl_ext_ARB_texture_non_power_of_two;
extern int sfogl_ext_EXT_blend_equation_separate;
extern int sfogl_ext_EXT_texture_sRGB;
extern int sfogl_ext_EXT_framebuffer_object;
extern int sfogl_ext_EXT_packed_depth_stencil;
extern int sfogl_ext_EXT_framebuffer_blit;
extern int sfogl_ext_EXT_framebuffer_multisample;
extern int sfogl_ext_ARB_copy_buffer;
extern int sfogl_ext_ARB_geometry_shader4;
@ -414,11 +416,20 @@ extern int sfogl_ext_ARB_geometry_shader4;
#define GL_STENCIL_INDEX4_EXT 0x8D47
#define GL_STENCIL_INDEX8_EXT 0x8D48
#define GL_DEPTH24_STENCIL8_EXT 0x88F0
#define GL_DEPTH_STENCIL_EXT 0x84F9
#define GL_TEXTURE_STENCIL_SIZE_EXT 0x88F1
#define GL_UNSIGNED_INT_24_8_EXT 0x84FA
#define GL_DRAW_FRAMEBUFFER_BINDING_EXT 0x8CA6
#define GL_DRAW_FRAMEBUFFER_EXT 0x8CA9
#define GL_READ_FRAMEBUFFER_BINDING_EXT 0x8CAA
#define GL_READ_FRAMEBUFFER_EXT 0x8CA8
#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT 0x8D56
#define GL_MAX_SAMPLES_EXT 0x8D57
#define GL_RENDERBUFFER_SAMPLES_EXT 0x8CAB
#define GL_COPY_READ_BUFFER 0x8F36
#define GL_COPY_WRITE_BUFFER 0x8F37
@ -1311,12 +1322,19 @@ extern void (GL_FUNCPTR *sf_ptrc_glRenderbufferStorageEXT)(GLenum, GLenum, GLsiz
#define glRenderbufferStorageEXT sf_ptrc_glRenderbufferStorageEXT
#endif // GL_EXT_framebuffer_object
#ifndef GL_EXT_framebuffer_blit
#define GL_EXT_framebuffer_blit 1
extern void (GL_FUNCPTR *sf_ptrc_glBlitFramebufferEXT)(GLint, GLint, GLint, GLint, GLint, GLint, GLint, GLint, GLbitfield, GLenum);
#define glBlitFramebufferEXT sf_ptrc_glBlitFramebufferEXT
#endif // GL_EXT_framebuffer_blit
#ifndef GL_EXT_framebuffer_multisample
#define GL_EXT_framebuffer_multisample 1
extern void (GL_FUNCPTR *sf_ptrc_glRenderbufferStorageMultisampleEXT)(GLenum, GLsizei, GLenum, GLsizei, GLsizei);
#define glRenderbufferStorageMultisampleEXT sf_ptrc_glRenderbufferStorageMultisampleEXT
#endif // GL_EXT_framebuffer_multisample
#ifndef GL_ARB_copy_buffer
#define GL_ARB_copy_buffer 1
extern void (GL_FUNCPTR *sf_ptrc_glCopyBufferSubData)(GLenum, GLenum, GLintptr, GLintptr, GLsizeiptr);

View File

@ -50,6 +50,13 @@ RenderTexture::~RenderTexture()
////////////////////////////////////////////////////////////
bool RenderTexture::create(unsigned int width, unsigned int height, bool depthBuffer)
{
return create(width, height, ContextSettings(depthBuffer ? 32 : 0));
}
////////////////////////////////////////////////////////////
bool RenderTexture::create(unsigned int width, unsigned int height, const ContextSettings& settings)
{
// Create the texture
if (!m_texture.create(width, height))
@ -78,7 +85,7 @@ bool RenderTexture::create(unsigned int width, unsigned int height, bool depthBu
}
// Initialize the render texture
if (!m_impl->create(width, height, m_texture.m_texture, depthBuffer))
if (!m_impl->create(width, height, m_texture.m_texture, settings))
return false;
// We can now initialize the render target part
@ -88,6 +95,20 @@ bool RenderTexture::create(unsigned int width, unsigned int height, bool depthBu
}
////////////////////////////////////////////////////////////
unsigned int RenderTexture::getMaximumAntialiasingLevel()
{
if (priv::RenderTextureImplFBO::isAvailable())
{
return priv::RenderTextureImplFBO::getMaximumAntialiasingLevel();
}
else
{
return priv::RenderTextureImplDefault::getMaximumAntialiasingLevel();
}
}
////////////////////////////////////////////////////////////
void RenderTexture::setSmooth(bool smooth)
{

View File

@ -33,6 +33,9 @@
namespace sf
{
struct ContextSettings;
namespace priv
{
////////////////////////////////////////////////////////////
@ -52,15 +55,15 @@ public:
////////////////////////////////////////////////////////////
/// \brief Create the render texture implementation
///
/// \param width Width of the texture to render to
/// \param height Height of the texture to render to
/// \param textureId OpenGL identifier of the target texture
/// \param depthBuffer Is a depth buffer requested?
/// \param width Width of the texture to render to
/// \param height Height of the texture to render to
/// \param textureId OpenGL identifier of the target texture
/// \param settings Context settings to create render-texture with
///
/// \return True if creation has been successful
///
////////////////////////////////////////////////////////////
virtual bool create(unsigned int width, unsigned int height, unsigned int textureId, bool depthBuffer) = 0;
virtual bool create(unsigned int width, unsigned int height, unsigned int textureId, const ContextSettings& settings) = 0;
////////////////////////////////////////////////////////////
/// \brief Activate or deactivate the render texture for rendering

View File

@ -55,14 +55,24 @@ RenderTextureImplDefault::~RenderTextureImplDefault()
////////////////////////////////////////////////////////////
bool RenderTextureImplDefault::create(unsigned int width, unsigned int height, unsigned int, bool depthBuffer)
unsigned int RenderTextureImplDefault::getMaximumAntialiasingLevel()
{
// If the system is so old that it doesn't support FBOs, chances are it is
// also using either a software renderer or some CPU emulated support for AA
// In order to not cripple performance in this rare case, we just return 0 here
return 0;
}
////////////////////////////////////////////////////////////
bool RenderTextureImplDefault::create(unsigned int width, unsigned int height, unsigned int, const ContextSettings& settings)
{
// Store the dimensions
m_width = width;
m_height = height;
// Create the in-memory OpenGL context
m_context = new Context(ContextSettings(depthBuffer ? 32 : 0), width, height);
m_context = new Context(settings, width, height);
return true;
}

View File

@ -58,20 +58,28 @@ public:
////////////////////////////////////////////////////////////
~RenderTextureImplDefault();
////////////////////////////////////////////////////////////
/// \brief Get the maximum anti-aliasing level supported by the system
///
/// \return The maximum anti-aliasing level supported by the system
///
////////////////////////////////////////////////////////////
static unsigned int getMaximumAntialiasingLevel();
private:
////////////////////////////////////////////////////////////
/// \brief Create the render texture implementation
///
/// \param width Width of the texture to render to
/// \param height Height of the texture to render to
/// \param textureId OpenGL identifier of the target texture
/// \param depthBuffer Is a depth buffer requested?
/// \param width Width of the texture to render to
/// \param height Height of the texture to render to
/// \param textureId OpenGL identifier of the target texture
/// \param settings Context settings to create render-texture with
///
/// \return True if creation has been successful
///
////////////////////////////////////////////////////////////
virtual bool create(unsigned int width, unsigned int height, unsigned int textureId, bool depthBuffer);
virtual bool create(unsigned int width, unsigned int height, unsigned int textureId, const ContextSettings& settings);
////////////////////////////////////////////////////////////
/// \brief Activate or deactivate the render texture for rendering

View File

@ -37,9 +37,13 @@ namespace priv
{
////////////////////////////////////////////////////////////
RenderTextureImplFBO::RenderTextureImplFBO() :
m_context (NULL),
m_frameBuffer(0),
m_depthBuffer(0)
m_context (NULL),
m_frameBuffer (0),
m_multisampleFrameBuffer(0),
m_depthStencilBuffer (0),
m_colorBuffer (0),
m_width (0),
m_height (0)
{
}
@ -50,11 +54,25 @@ RenderTextureImplFBO::~RenderTextureImplFBO()
{
m_context->setActive(true);
// Destroy the depth buffer
if (m_depthBuffer)
// Destroy the color buffer
if (m_colorBuffer)
{
GLuint depthBuffer = static_cast<GLuint>(m_depthBuffer);
glCheck(GLEXT_glDeleteRenderbuffers(1, &depthBuffer));
GLuint colorBuffer = static_cast<GLuint>(m_colorBuffer);
glCheck(GLEXT_glDeleteRenderbuffers(1, &colorBuffer));
}
// Destroy the depth/stencil buffer
if (m_depthStencilBuffer)
{
GLuint depthStencilBuffer = static_cast<GLuint>(m_depthStencilBuffer);
glCheck(GLEXT_glDeleteRenderbuffers(1, &depthStencilBuffer));
}
// Destroy the multisample frame buffer
if (m_multisampleFrameBuffer)
{
GLuint multisampleFrameBuffer = static_cast<GLuint>(m_multisampleFrameBuffer);
glCheck(GLEXT_glDeleteFramebuffers(1, &multisampleFrameBuffer));
}
// Destroy the frame buffer
@ -82,52 +100,233 @@ bool RenderTextureImplFBO::isAvailable()
////////////////////////////////////////////////////////////
bool RenderTextureImplFBO::create(unsigned int width, unsigned int height, unsigned int textureId, bool depthBuffer)
unsigned int RenderTextureImplFBO::getMaximumAntialiasingLevel()
{
GLint samples = 0;
#ifndef SFML_OPENGL_ES
glCheck(glGetIntegerv(GLEXT_GL_MAX_SAMPLES, &samples));
#endif
return static_cast<unsigned int>(samples);
}
////////////////////////////////////////////////////////////
bool RenderTextureImplFBO::create(unsigned int width, unsigned int height, unsigned int textureId, const ContextSettings& settings)
{
// Store the dimensions
m_width = width;
m_height = height;
// Disable creation of depth/stencil surfaces in the context
ContextSettings contextSettings(settings);
contextSettings.depthBits = 0;
contextSettings.stencilBits = 0;
contextSettings.antialiasingLevel = 0;
contextSettings.sRgbCapable = false;
// Create the context
m_context = new Context;
m_context = new Context(contextSettings, 1, 1);
// Create the framebuffer object
GLuint frameBuffer = 0;
glCheck(GLEXT_glGenFramebuffers(1, &frameBuffer));
m_frameBuffer = static_cast<unsigned int>(frameBuffer);
if (!m_frameBuffer)
{
err() << "Impossible to create render texture (failed to create the frame buffer object)" << std::endl;
if (settings.antialiasingLevel && !(GLEXT_framebuffer_multisample && GLEXT_framebuffer_blit))
return false;
}
glCheck(GLEXT_glBindFramebuffer(GLEXT_GL_FRAMEBUFFER, m_frameBuffer));
// Create the depth buffer if requested
if (depthBuffer)
if (settings.stencilBits && !GLEXT_packed_depth_stencil)
return false;
#ifndef SFML_OPENGL_ES
// Check if the requested anti-aliasing level is supported
if (settings.antialiasingLevel)
{
GLuint depth = 0;
glCheck(GLEXT_glGenRenderbuffers(1, &depth));
m_depthBuffer = static_cast<unsigned int>(depth);
if (!m_depthBuffer)
GLint samples = 0;
glCheck(glGetIntegerv(GLEXT_GL_MAX_SAMPLES, &samples));
if (settings.antialiasingLevel > static_cast<unsigned int>(samples))
{
err() << "Impossible to create render texture (failed to create the attached depth buffer)" << std::endl;
err() << "Impossible to create render texture (unsupported anti-aliasing level)";
err() << " Requested: " << settings.antialiasingLevel << " Maximum supported: " << samples << std::endl;
return false;
}
glCheck(GLEXT_glBindRenderbuffer(GLEXT_GL_RENDERBUFFER, m_depthBuffer));
glCheck(GLEXT_glRenderbufferStorage(GLEXT_GL_RENDERBUFFER, GLEXT_GL_DEPTH_COMPONENT, width, height));
glCheck(GLEXT_glFramebufferRenderbuffer(GLEXT_GL_FRAMEBUFFER, GLEXT_GL_DEPTH_ATTACHMENT, GLEXT_GL_RENDERBUFFER, m_depthBuffer));
}
// Link the texture to the frame buffer
glCheck(GLEXT_glFramebufferTexture2D(GLEXT_GL_FRAMEBUFFER, GLEXT_GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureId, 0));
#endif
// A final check, just to be sure...
GLenum status;
glCheck(status = GLEXT_glCheckFramebufferStatus(GLEXT_GL_FRAMEBUFFER));
if (status != GLEXT_GL_FRAMEBUFFER_COMPLETE)
if (!settings.antialiasingLevel)
{
glCheck(GLEXT_glBindFramebuffer(GLEXT_GL_FRAMEBUFFER, 0));
err() << "Impossible to create render texture (failed to link the target texture to the frame buffer)" << std::endl;
return false;
}
// Create the framebuffer object
GLuint frameBuffer = 0;
glCheck(GLEXT_glGenFramebuffers(1, &frameBuffer));
m_frameBuffer = static_cast<unsigned int>(frameBuffer);
if (!m_frameBuffer)
{
err() << "Impossible to create render texture (failed to create the frame buffer object)" << std::endl;
return false;
}
glCheck(GLEXT_glBindFramebuffer(GLEXT_GL_FRAMEBUFFER, m_frameBuffer));
return true;
// Create the depth/stencil buffer if requested
if (settings.stencilBits)
{
#ifndef SFML_OPENGL_ES
GLuint depthStencil = 0;
glCheck(GLEXT_glGenRenderbuffers(1, &depthStencil));
m_depthStencilBuffer = static_cast<unsigned int>(depthStencil);
if (!m_depthStencilBuffer)
{
err() << "Impossible to create render texture (failed to create the attached depth/stencil buffer)" << std::endl;
return false;
}
glCheck(GLEXT_glBindRenderbuffer(GLEXT_GL_RENDERBUFFER, m_depthStencilBuffer));
glCheck(GLEXT_glRenderbufferStorage(GLEXT_GL_RENDERBUFFER, GLEXT_GL_DEPTH24_STENCIL8, width, height));
glCheck(GLEXT_glFramebufferRenderbuffer(GLEXT_GL_FRAMEBUFFER, GLEXT_GL_DEPTH_ATTACHMENT, GLEXT_GL_RENDERBUFFER, m_depthStencilBuffer));
glCheck(GLEXT_glFramebufferRenderbuffer(GLEXT_GL_FRAMEBUFFER, GLEXT_GL_STENCIL_ATTACHMENT, GLEXT_GL_RENDERBUFFER, m_depthStencilBuffer));
#else
err() << "Impossible to create render texture (failed to create the attached depth/stencil buffer)" << std::endl;
return false;
#endif // SFML_OPENGL_ES
}
else if (settings.depthBits)
{
GLuint depthStencil = 0;
glCheck(GLEXT_glGenRenderbuffers(1, &depthStencil));
m_depthStencilBuffer = static_cast<unsigned int>(depthStencil);
if (!m_depthStencilBuffer)
{
err() << "Impossible to create render texture (failed to create the attached depth buffer)" << std::endl;
return false;
}
glCheck(GLEXT_glBindRenderbuffer(GLEXT_GL_RENDERBUFFER, m_depthStencilBuffer));
glCheck(GLEXT_glRenderbufferStorage(GLEXT_GL_RENDERBUFFER, GLEXT_GL_DEPTH_COMPONENT, width, height));
glCheck(GLEXT_glFramebufferRenderbuffer(GLEXT_GL_FRAMEBUFFER, GLEXT_GL_DEPTH_ATTACHMENT, GLEXT_GL_RENDERBUFFER, m_depthStencilBuffer));
}
// Link the texture to the frame buffer
glCheck(GLEXT_glFramebufferTexture2D(GLEXT_GL_FRAMEBUFFER, GLEXT_GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureId, 0));
// A final check, just to be sure...
GLenum status;
glCheck(status = GLEXT_glCheckFramebufferStatus(GLEXT_GL_FRAMEBUFFER));
if (status != GLEXT_GL_FRAMEBUFFER_COMPLETE)
{
glCheck(GLEXT_glBindFramebuffer(GLEXT_GL_FRAMEBUFFER, 0));
err() << "Impossible to create render texture (frame buffer incomplete)" << std::endl;
return false;
}
return true;
}
else
{
#ifndef SFML_OPENGL_ES
// Create the framebuffer object
GLuint frameBuffer = 0;
glCheck(GLEXT_glGenFramebuffers(1, &frameBuffer));
m_frameBuffer = static_cast<unsigned int>(frameBuffer);
if (!m_frameBuffer)
{
err() << "Impossible to create render texture (failed to create the frame buffer object)" << std::endl;
return false;
}
glCheck(GLEXT_glBindFramebuffer(GLEXT_GL_FRAMEBUFFER, m_frameBuffer));
// Link the texture to the frame buffer
glCheck(GLEXT_glFramebufferTexture2D(GLEXT_GL_FRAMEBUFFER, GLEXT_GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureId, 0));
// A final check, just to be sure...
GLenum status;
glCheck(status = GLEXT_glCheckFramebufferStatus(GLEXT_GL_FRAMEBUFFER));
if (status != GLEXT_GL_FRAMEBUFFER_COMPLETE)
{
glCheck(GLEXT_glBindFramebuffer(GLEXT_GL_FRAMEBUFFER, 0));
err() << "Impossible to create render texture (frame buffer incomplete)" << std::endl;
return false;
}
// Create the multisample framebuffer object
frameBuffer = 0;
glCheck(GLEXT_glGenFramebuffers(1, &frameBuffer));
m_multisampleFrameBuffer = static_cast<unsigned int>(frameBuffer);
if (!m_multisampleFrameBuffer)
{
err() << "Impossible to create render texture (failed to create the multisample frame buffer object)" << std::endl;
return false;
}
glCheck(GLEXT_glBindFramebuffer(GLEXT_GL_FRAMEBUFFER, m_multisampleFrameBuffer));
// Create the multisample color buffer
GLuint color = 0;
glCheck(GLEXT_glGenRenderbuffers(1, &color));
m_colorBuffer = static_cast<unsigned int>(color);
if (!m_colorBuffer)
{
err() << "Impossible to create render texture (failed to create the attached multisample color buffer)" << std::endl;
return false;
}
glCheck(GLEXT_glBindRenderbuffer(GLEXT_GL_RENDERBUFFER, m_colorBuffer));
glCheck(GLEXT_glRenderbufferStorageMultisample(GLEXT_GL_RENDERBUFFER, settings.antialiasingLevel, GL_RGBA, width, height));
glCheck(GLEXT_glFramebufferRenderbuffer(GLEXT_GL_FRAMEBUFFER, GLEXT_GL_COLOR_ATTACHMENT0, GLEXT_GL_RENDERBUFFER, m_colorBuffer));
// Create the multisample depth/stencil buffer if requested
if (settings.stencilBits)
{
GLuint depthStencil = 0;
glCheck(GLEXT_glGenRenderbuffers(1, &depthStencil));
m_depthStencilBuffer = static_cast<unsigned int>(depthStencil);
if (!m_depthStencilBuffer)
{
err() << "Impossible to create render texture (failed to create the attached multisample depth/stencil buffer)" << std::endl;
return false;
}
glCheck(GLEXT_glBindRenderbuffer(GLEXT_GL_RENDERBUFFER, m_depthStencilBuffer));
glCheck(GLEXT_glRenderbufferStorageMultisample(GLEXT_GL_RENDERBUFFER, settings.antialiasingLevel, GLEXT_GL_DEPTH24_STENCIL8, width, height));
glCheck(GLEXT_glFramebufferRenderbuffer(GLEXT_GL_FRAMEBUFFER, GLEXT_GL_DEPTH_ATTACHMENT, GLEXT_GL_RENDERBUFFER, m_depthStencilBuffer));
glCheck(GLEXT_glFramebufferRenderbuffer(GLEXT_GL_FRAMEBUFFER, GLEXT_GL_STENCIL_ATTACHMENT, GLEXT_GL_RENDERBUFFER, m_depthStencilBuffer));
}
else if (settings.depthBits)
{
GLuint depthStencil = 0;
glCheck(GLEXT_glGenRenderbuffers(1, &depthStencil));
m_depthStencilBuffer = static_cast<unsigned int>(depthStencil);
if (!m_depthStencilBuffer)
{
err() << "Impossible to create render texture (failed to create the attached multisample depth buffer)" << std::endl;
return false;
}
glCheck(GLEXT_glBindRenderbuffer(GLEXT_GL_RENDERBUFFER, m_depthStencilBuffer));
glCheck(GLEXT_glRenderbufferStorageMultisample(GLEXT_GL_RENDERBUFFER, settings.antialiasingLevel, GLEXT_GL_DEPTH_COMPONENT, width, height));
glCheck(GLEXT_glFramebufferRenderbuffer(GLEXT_GL_FRAMEBUFFER, GLEXT_GL_DEPTH_ATTACHMENT, GLEXT_GL_RENDERBUFFER, m_depthStencilBuffer));
}
// A final check, just to be sure...
glCheck(status = GLEXT_glCheckFramebufferStatus(GLEXT_GL_FRAMEBUFFER));
if (status != GLEXT_GL_FRAMEBUFFER_COMPLETE)
{
glCheck(GLEXT_glBindFramebuffer(GLEXT_GL_FRAMEBUFFER, 0));
err() << "Impossible to create render texture (multisample frame buffer incomplete)" << std::endl;
return false;
}
return true;
#else
err() << "Impossible to create render texture (failed to create the multisample frame buffer object)" << std::endl;
return false;
#endif // SFML_OPENGL_ES
}
}
@ -141,6 +340,18 @@ bool RenderTextureImplFBO::activate(bool active)
////////////////////////////////////////////////////////////
void RenderTextureImplFBO::updateTexture(unsigned int)
{
#ifndef SFML_OPENGL_ES
if (m_multisampleFrameBuffer)
{
glCheck(GLEXT_glBindFramebuffer(GLEXT_GL_DRAW_FRAMEBUFFER, m_frameBuffer));
glCheck(GLEXT_glBlitFramebuffer(0, 0, m_width, m_height, 0, 0, m_width, m_height, GL_COLOR_BUFFER_BIT, GL_NEAREST));
glCheck(GLEXT_glBindFramebuffer(GLEXT_GL_DRAW_FRAMEBUFFER, m_multisampleFrameBuffer));
}
#endif // SFML_OPENGL_ES
glCheck(glFlush());
}

View File

@ -66,20 +66,28 @@ public:
////////////////////////////////////////////////////////////
static bool isAvailable();
////////////////////////////////////////////////////////////
/// \brief Get the maximum anti-aliasing level supported by the system
///
/// \return The maximum anti-aliasing level supported by the system
///
////////////////////////////////////////////////////////////
static unsigned int getMaximumAntialiasingLevel();
private:
////////////////////////////////////////////////////////////
/// \brief Create the render texture implementation
///
/// \param width Width of the texture to render to
/// \param height Height of the texture to render to
/// \param textureId OpenGL identifier of the target texture
/// \param depthBuffer Is a depth buffer requested?
/// \param width Width of the texture to render to
/// \param height Height of the texture to render to
/// \param textureId OpenGL identifier of the target texture
/// \param settings Context settings to create render-texture with
///
/// \return True if creation has been successful
///
////////////////////////////////////////////////////////////
virtual bool create(unsigned int width, unsigned int height, unsigned int textureId, bool depthBuffer);
virtual bool create(unsigned int width, unsigned int height, unsigned int textureId, const ContextSettings& settings);
////////////////////////////////////////////////////////////
/// \brief Activate or deactivate the render texture for rendering
@ -102,9 +110,13 @@ private:
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
Context* m_context; ///< Needs a separate OpenGL context for not messing up the other ones
unsigned int m_frameBuffer; ///< OpenGL frame buffer object
unsigned int m_depthBuffer; ///< Optional depth buffer attached to the frame buffer
Context* m_context; ///< Needs a separate OpenGL context for not messing up the other ones
unsigned int m_frameBuffer; ///< OpenGL frame buffer object
unsigned int m_multisampleFrameBuffer; ///< Optional OpenGL frame buffer object with multisample attachments
unsigned int m_depthStencilBuffer; ///< Optional depth/stencil buffer attached to the frame buffer
unsigned int m_colorBuffer; ///< Optional multisample color buffer attached to the frame buffer
unsigned int m_width; ///< Width of the attachments
unsigned int m_height; ///< Height of the attachments
};
} // namespace priv