mirror of
https://github.com/love2d/love.git
synced 2026-08-19 12:14:20 +02:00
Fix issue #294 (really this time).
Add stencil attachment to framebuffer creation. Needed to remove depth attachment to make it work, but that should not change anything, since depth test is not enabled anyway. May need testing nonetheless.
This commit is contained in:
@@ -14,39 +14,44 @@ namespace opengl
|
|||||||
// strategy for fbo creation, interchangable at runtime:
|
// strategy for fbo creation, interchangable at runtime:
|
||||||
// none, opengl >= 3.0, extensions
|
// none, opengl >= 3.0, extensions
|
||||||
struct FramebufferStrategy {
|
struct FramebufferStrategy {
|
||||||
/// create a new framebuffer, depthbuffer and texture
|
/// create a new framebuffer, stencilbuffer and texture
|
||||||
/**
|
/**
|
||||||
* @param[out] framebuffer Framebuffer name
|
* @param[out] framebuffer Framebuffer name
|
||||||
* @param[out] depthbuffer Depthbuffer name
|
* @param[out] stencilbuffer Stencilbuffer name
|
||||||
* @param[out] img Texture name
|
* @param[out] img Texture name
|
||||||
* @param[in] width Width of framebuffer
|
* @param[in] width Width of framebuffer
|
||||||
* @param[in] height Height of framebuffer
|
* @param[in] height Height of framebuffer
|
||||||
* @return Creation status
|
* @return Creation status
|
||||||
*/
|
*/
|
||||||
virtual GLenum createFBO(GLuint&, GLuint&, GLuint&, int, int)
|
virtual GLenum createFBO(GLuint&, GLuint&, GLuint&, int, int)
|
||||||
{ return GL_FRAMEBUFFER_UNSUPPORTED; }
|
{ return GL_FRAMEBUFFER_UNSUPPORTED; }
|
||||||
/// remove objects
|
/// remove objects
|
||||||
/**
|
/**
|
||||||
* @param[in] framebuffer Framebuffer name
|
* @param[in] framebuffer Framebuffer name
|
||||||
* @param[in] depthbuffer Depthbuffer name
|
* @param[in] stencilbuffer Stencilbuffer name
|
||||||
* @param[in] img Texture name
|
* @param[in] img Texture name
|
||||||
*/
|
*/
|
||||||
virtual void deleteFBO(GLuint, GLuint, GLuint) {}
|
virtual void deleteFBO(GLuint, GLuint, GLuint) {}
|
||||||
virtual void bindFBO(GLuint) {}
|
virtual void bindFBO(GLuint) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct FramebufferStrategyGL3 : public FramebufferStrategy {
|
struct FramebufferStrategyGL3 : public FramebufferStrategy {
|
||||||
virtual GLenum createFBO(GLuint& framebuffer, GLuint& depthbuffer, GLuint& img, int width, int height)
|
virtual GLenum createFBO(GLuint& framebuffer, GLuint& stencilbuffer, GLuint& img, int width, int height)
|
||||||
{
|
{
|
||||||
// get currently bound fbo to reset to it later
|
// get currently bound fbo to reset to it later
|
||||||
GLint current_fbo;
|
GLint current_fbo;
|
||||||
glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, ¤t_fbo);
|
glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, ¤t_fbo);
|
||||||
|
|
||||||
// generate depth buffer
|
// create framebuffer
|
||||||
glGenRenderbuffers(1, &depthbuffer);
|
glGenFramebuffers(1, &framebuffer);
|
||||||
glBindRenderbuffer(GL_RENDERBUFFER, depthbuffer);
|
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
|
||||||
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, width, height);
|
|
||||||
glBindRenderbuffer(GL_RENDERBUFFER, 0);
|
// create stencil buffer
|
||||||
|
glGenRenderbuffers(1, &stencilbuffer);
|
||||||
|
glBindRenderbuffer(GL_RENDERBUFFER, stencilbuffer);
|
||||||
|
glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX, width, height);
|
||||||
|
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
|
||||||
|
GL_RENDERBUFFER, stencilbuffer);
|
||||||
|
|
||||||
// generate texture save target
|
// generate texture save target
|
||||||
glGenTextures(1, &img);
|
glGenTextures(1, &img);
|
||||||
@@ -56,24 +61,21 @@ namespace opengl
|
|||||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height,
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height,
|
||||||
0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
||||||
glBindTexture(GL_TEXTURE_2D, 0);
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
|
|
||||||
// create framebuffer
|
|
||||||
glGenFramebuffers(1, &framebuffer);
|
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
|
|
||||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
|
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
|
||||||
GL_TEXTURE_2D, img, 0);
|
GL_TEXTURE_2D, img, 0);
|
||||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
|
|
||||||
GL_RENDERBUFFER, depthbuffer);
|
// check status
|
||||||
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
|
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
|
||||||
|
|
||||||
// unbind framebuffer
|
// unbind framebuffer
|
||||||
|
glBindRenderbuffer(GL_RENDERBUFFER, 0);
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, (GLuint)current_fbo);
|
glBindFramebuffer(GL_FRAMEBUFFER, (GLuint)current_fbo);
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
virtual void deleteFBO(GLuint framebuffer, GLuint depthbuffer, GLuint img)
|
virtual void deleteFBO(GLuint framebuffer, GLuint stencilbuffer, GLuint img)
|
||||||
{
|
{
|
||||||
glDeleteTextures(1, &img);
|
glDeleteTextures(1, &img);
|
||||||
glDeleteRenderbuffers(1, &depthbuffer);
|
glDeleteRenderbuffers(1, &stencilbuffer);
|
||||||
glDeleteFramebuffers(1, &framebuffer);
|
glDeleteFramebuffers(1, &framebuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -85,16 +87,21 @@ namespace opengl
|
|||||||
|
|
||||||
struct FramebufferStrategyEXT : public FramebufferStrategy {
|
struct FramebufferStrategyEXT : public FramebufferStrategy {
|
||||||
|
|
||||||
virtual GLenum createFBO(GLuint& framebuffer, GLuint& depthbuffer, GLuint& img, int width, int height)
|
virtual GLenum createFBO(GLuint& framebuffer, GLuint& stencilbuffer, GLuint& img, int width, int height)
|
||||||
{
|
{
|
||||||
GLint current_fbo;
|
GLint current_fbo;
|
||||||
glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING_EXT, ¤t_fbo);
|
glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING_EXT, ¤t_fbo);
|
||||||
|
|
||||||
// generate depth buffer
|
// create framebuffer
|
||||||
glGenRenderbuffersEXT(1, &depthbuffer);
|
glGenFramebuffersEXT(1, &framebuffer);
|
||||||
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, depthbuffer);
|
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, framebuffer);
|
||||||
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT16, width, height);
|
|
||||||
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
|
// create stencil buffer
|
||||||
|
glGenRenderbuffersEXT(1, &stencilbuffer);
|
||||||
|
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, stencilbuffer);
|
||||||
|
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_STENCIL_INDEX, width, height);
|
||||||
|
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT,
|
||||||
|
GL_RENDERBUFFER_EXT, stencilbuffer);
|
||||||
|
|
||||||
// generate texture save target
|
// generate texture save target
|
||||||
glGenTextures(1, &img);
|
glGenTextures(1, &img);
|
||||||
@@ -104,25 +111,22 @@ namespace opengl
|
|||||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height,
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height,
|
||||||
0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
||||||
glBindTexture(GL_TEXTURE_2D, 0);
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
|
|
||||||
// create framebuffer
|
|
||||||
glGenFramebuffersEXT(1, &framebuffer);
|
|
||||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, framebuffer);
|
|
||||||
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
|
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
|
||||||
GL_TEXTURE_2D, img, 0);
|
GL_TEXTURE_2D, img, 0);
|
||||||
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
|
|
||||||
GL_RENDERBUFFER_EXT, depthbuffer);
|
// check status
|
||||||
GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
|
GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
|
||||||
|
|
||||||
// unbind framebuffer
|
// unbind framebuffer
|
||||||
|
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
|
||||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, (GLuint)current_fbo);
|
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, (GLuint)current_fbo);
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void deleteFBO(GLuint framebuffer, GLuint depthbuffer, GLuint img)
|
virtual void deleteFBO(GLuint framebuffer, GLuint stencilbuffer, GLuint img)
|
||||||
{
|
{
|
||||||
glDeleteTextures(1, &img);
|
glDeleteTextures(1, &img);
|
||||||
glDeleteRenderbuffersEXT(1, &depthbuffer);
|
glDeleteRenderbuffersEXT(1, &stencilbuffer);
|
||||||
glDeleteFramebuffersEXT(1, &framebuffer);
|
glDeleteFramebuffersEXT(1, &framebuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -213,9 +217,8 @@ namespace opengl
|
|||||||
current->stopGrab();
|
current->stopGrab();
|
||||||
|
|
||||||
// bind buffer and clear screen
|
// bind buffer and clear screen
|
||||||
glPushAttrib(GL_VIEWPORT_BIT | GL_DEPTH_BUFFER_BIT | GL_TRANSFORM_BIT);
|
glPushAttrib(GL_VIEWPORT_BIT | GL_TRANSFORM_BIT);
|
||||||
strategy->bindFBO(fbo);
|
strategy->bindFBO(fbo);
|
||||||
glClear(GL_DEPTH_BUFFER_BIT);
|
|
||||||
glViewport(0, 0, width, height);
|
glViewport(0, 0, width, height);
|
||||||
|
|
||||||
// Reset the projection matrix
|
// Reset the projection matrix
|
||||||
@@ -366,7 +369,7 @@ namespace opengl
|
|||||||
|
|
||||||
bool Canvas::loadVolatile()
|
bool Canvas::loadVolatile()
|
||||||
{
|
{
|
||||||
status = strategy->createFBO(fbo, depthbuffer, img, width, height);
|
status = strategy->createFBO(fbo, stencilbuffer, img, width, height);
|
||||||
if (status != GL_FRAMEBUFFER_COMPLETE)
|
if (status != GL_FRAMEBUFFER_COMPLETE)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@@ -382,7 +385,7 @@ namespace opengl
|
|||||||
{
|
{
|
||||||
settings.filter = getFilter();
|
settings.filter = getFilter();
|
||||||
settings.wrap = getWrap();
|
settings.wrap = getWrap();
|
||||||
strategy->deleteFBO(fbo, depthbuffer, img);
|
strategy->deleteFBO(fbo, stencilbuffer, img);
|
||||||
}
|
}
|
||||||
|
|
||||||
int Canvas::getWidth()
|
int Canvas::getWidth()
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ namespace opengl
|
|||||||
GLsizei width;
|
GLsizei width;
|
||||||
GLsizei height;
|
GLsizei height;
|
||||||
GLuint fbo;
|
GLuint fbo;
|
||||||
GLuint depthbuffer;
|
GLuint stencilbuffer;
|
||||||
GLuint img;
|
GLuint img;
|
||||||
|
|
||||||
vertex vertices[4];
|
vertex vertices[4];
|
||||||
|
|||||||
@@ -169,9 +169,6 @@ namespace opengl
|
|||||||
|
|
||||||
static int setStencil(lua_State * L, bool invert)
|
static int setStencil(lua_State * L, bool invert)
|
||||||
{
|
{
|
||||||
// stencils require the default fb to work properly
|
|
||||||
Canvas::TemporaryUnbinder unbinder;
|
|
||||||
|
|
||||||
// no argument -> clear mask
|
// no argument -> clear mask
|
||||||
if (lua_isnoneornil(L, 1)) {
|
if (lua_isnoneornil(L, 1)) {
|
||||||
instance->discardStencil();
|
instance->discardStencil();
|
||||||
|
|||||||
Reference in New Issue
Block a user