Created
December 8, 2015 21:48
-
-
Save eigenbom/fcfa329b5073d85aa63c to your computer and use it in GitHub Desktop.
A single-context Framebuffer render target for SFML
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// NB: Requires some changes to the SFML headers to make some parts public | |
////////////// HEADER | |
// A single-context Framebuffer render target | |
// A lighter version of sf::RenderTexture | |
// NB: MUST call SetContextOwner before create() | |
class FBOTargetImpl : public sf::RenderTarget { | |
public: | |
FBOTargetImpl(); | |
virtual ~FBOTargetImpl(); | |
// Set the context for FBOs to be created on | |
// Must call this before any create(...) calls will work | |
static void SetContextOwner(sf::RenderWindow* window); | |
// Create the FBOTarget | |
bool create(unsigned int w, unsigned int h); | |
bool setActive(bool active = true); | |
void display(); | |
virtual sf::Vector2u getSize() const; | |
const sf::Texture& getTexture() const; | |
void setSmooth(bool smooth); | |
private: | |
virtual bool activate(bool active); | |
// Shared context | |
static sf::RenderWindow* sContextOwner; | |
// Internals | |
unsigned int mFbo; // FBO id | |
sf::Texture mTexture; // Target texture to draw on | |
unsigned int mTex; | |
}; | |
///////////////////// SOURCE | |
sf::RenderWindow* FBOTargetImpl::sContextOwner = nullptr; | |
FBOTargetImpl::FBOTargetImpl() :mFbo(0), mTex(0){ | |
} | |
FBOTargetImpl::~FBOTargetImpl(){ | |
// cleanup (will auto kill the texture, but need to delete the fbo) | |
if (mFbo != 0){ | |
glDeleteFramebuffers(1, &mFbo); | |
} | |
} | |
// Set the context for FBOs to be created on | |
// Must call this before any create(...) calls will work | |
void FBOTargetImpl::SetContextOwner(sf::RenderWindow* window){ | |
sContextOwner = window; | |
} | |
// Create the FBOTarget | |
bool FBOTargetImpl::create(unsigned int w, unsigned int h){ | |
if (sContextOwner == nullptr) return false; | |
// TODO: Fallback to sf::RenderTexture if we can't make FBOs | |
// Create the objects using the shared context | |
sContextOwner->setActive(true); | |
if (!mTexture.create(w, h)){ | |
LOG_WARN() << "Couldn't create texture"; | |
return false; | |
} | |
mTexture.setSmooth(false); | |
mTexture.m_fboAttachment = true; | |
// get texture id | |
mTex = mTexture.getNativeHandle(); | |
/*GLint tex; | |
sf::Texture::bind(&mTexture); | |
glGetIntegerv(GL_TEXTURE_BINDING_2D, &tex); | |
if (tex >= 0) mTex = tex; | |
*/ | |
// make fbo | |
glGenFramebuffers(1, &mFbo); | |
glBindFramebuffer(GL_FRAMEBUFFER, mFbo); | |
//Attach 2D texture to this FBO | |
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTex, 0); | |
//Does the GPU support current FBO configuration? | |
GLenum status; | |
status = glCheckFramebufferStatus(GL_FRAMEBUFFER); | |
if (status != GL_FRAMEBUFFER_COMPLETE){ | |
// Badness | |
LOG_WARN() << "Couldn't create fbo"; | |
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); | |
glBindFramebuffer(GL_FRAMEBUFFER, 0); | |
return false; | |
} | |
// Finally, intialize the parent | |
RenderTarget::initialize(); | |
return true; | |
} | |
bool FBOTargetImpl::setActive(bool active){ | |
bool res = sContextOwner->setActive(true); | |
if (active){ | |
GLint currentFbo; | |
glGetIntegerv(GL_FRAMEBUFFER_BINDING, ¤tFbo); | |
if (currentFbo != mFbo){ | |
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mFbo); | |
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTex, 0); | |
} | |
} | |
else { | |
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); | |
} | |
return true; | |
} | |
void FBOTargetImpl::display(){ | |
if (setActive(true)){ | |
glFlush(); | |
mTexture.m_pixelsFlipped = true; | |
} | |
} | |
sf::Vector2u FBOTargetImpl::getSize() const { | |
// NB: getSize() is called in initialise to setup the default viewport | |
return mTexture.getSize(); | |
}; | |
const sf::Texture& FBOTargetImpl::getTexture() const { | |
return mTexture; | |
} | |
bool FBOTargetImpl::activate(bool active){ | |
return setActive(active); | |
} | |
void FBOTargetImpl::setSmooth(bool smooth){ | |
mTexture.setSmooth(smooth); | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment