1
0
Fork 0
mirror of https://github.com/AquariaOSE/Aquaria.git synced 2024-11-25 17:53:47 +00:00
Aquaria/BBGE/FrameBuffer.cpp

219 lines
5.4 KiB
C++

/*
Copyright (C) 2007, 2010 - Bit-Blot
This file is part of Aquaria.
Aquaria 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 2
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, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "FrameBuffer.h"
#include "Core.h"
#include "RenderBase.h"
//WARNING: FrameBuffer objects have to have reloadDevice/unloadDevice called manually!
FrameBuffer::FrameBuffer()
{
inited = false;
texw = 0;
texh = 0;
g_frameBuffer = 0;
g_depthRenderBuffer = 0;
g_dynamicTextureID = 0;
_w = _h = 0;
}
FrameBuffer::~FrameBuffer()
{
unloadDevice();
}
float FrameBuffer::getWidthP() const
{
return (float)core->getWindowWidth()/(float)texw;
}
float FrameBuffer::getHeightP() const
{
return (float)core->getWindowHeight()/(float)texh;
}
bool FrameBuffer::init(int width, int height, bool fitToScreen)
{
_w = width;
_h = height;
if (width == -1)
width = core->width;
if (height == -1)
height = core->height;
if (fitToScreen)
{
sizePowerOf2Texture(width);
sizePowerOf2Texture(height);
}
_fitToScreen = fitToScreen;
if (width == 0 || height == 0)
return false;
texw = width;
texh = height;
std::ostringstream os;
os << "Loading EXT_framebuffer_object (" << texw << ", " << texh << ")";
debugLog(os.str());
if( !glIsRenderbufferEXT || !glBindRenderbufferEXT || !glDeleteRenderbuffersEXT ||
!glGenRenderbuffersEXT || !glRenderbufferStorageEXT || !glGetRenderbufferParameterivEXT ||
!glIsFramebufferEXT || !glBindFramebufferEXT || !glDeleteFramebuffersEXT ||
!glGenFramebuffersEXT || !glCheckFramebufferStatusEXT || !glFramebufferTexture1DEXT ||
!glFramebufferTexture2DEXT || !glFramebufferTexture3DEXT || !glFramebufferRenderbufferEXT||
!glGetFramebufferAttachmentParameterivEXT)
{
debugLog("One or more EXT_framebuffer_object functions were not found");
return false;
}
unloadDevice();
//
// Create a frame-buffer object and a render-buffer object...
//
glGenFramebuffersEXT( 1, &g_frameBuffer );
glGenRenderbuffersEXT( 1, &g_depthRenderBuffer );
// Initialize the render-buffer for usage as a depth buffer.
// We don't really need this to render things into the frame-buffer object,
// but without it the geometry will not be sorted properly.
glBindRenderbufferEXT( GL_RENDERBUFFER_EXT, g_depthRenderBuffer );
glRenderbufferStorageEXT( GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT24, width, height );
glGenTextures( 1, &g_dynamicTextureID );
glBindTexture( GL_TEXTURE_2D, g_dynamicTextureID );
// GL_LINEAR
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
// FIXME: check for GL_ARB_texture_float; otherwise stick with old format
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA16F_ARB,
width, height,
0, GL_RGBA, GL_FLOAT, 0 );
// Put together
glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, g_frameBuffer );
glFramebufferTexture2DEXT( GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, g_dynamicTextureID, 0 );
glFramebufferRenderbufferEXT( GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, g_depthRenderBuffer );
//
// Check for errors...
//
GLenum status = glCheckFramebufferStatusEXT( GL_FRAMEBUFFER_EXT );
glBindTexture(GL_TEXTURE_2D, 0);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
switch( status )
{
case GL_FRAMEBUFFER_COMPLETE_EXT:
break;
case GL_FRAMEBUFFER_UNSUPPORTED_EXT:
debugLog("GL_FRAMEBUFFER_UNSUPPORTED_EXT!");
default:
unloadDevice();
return false;
}
debugLog("Done");
inited = true;
return true;
}
void FrameBuffer::unloadDevice()
{
debugLog("frameBuffer::unloadDevice");
inited = false;
if (glDeleteFramebuffersEXT == NULL)
{
debugLog("Already shut down the GL, don't delete framebuffers");
return;
}
if (g_frameBuffer)
{
glBindRenderbufferEXT( GL_RENDERBUFFER_EXT, 0 );
debugLog("frameBuffer handle present, deleting");
glDeleteFramebuffersEXT(1, &g_frameBuffer);
g_frameBuffer = 0;
}
if (g_dynamicTextureID)
{
glBindRenderbufferEXT( GL_RENDERBUFFER_EXT, 0 );
debugLog("dynamic texture ID handle present, deleting");
glDeleteTextures(1, &g_dynamicTextureID);
g_dynamicTextureID = 0;
}
if (g_depthRenderBuffer)
{
glBindRenderbufferEXT( GL_RENDERBUFFER_EXT, 0 );
debugLog("depth render buffer handle present, deleting");
glDeleteRenderbuffersEXT(1, &g_depthRenderBuffer);
g_depthRenderBuffer = 0;
}
debugLog("done");
}
void FrameBuffer::reloadDevice()
{
debugLog("frameBuffer::reloadDevice");
init(_w, _h, _fitToScreen);
}
void FrameBuffer::startCapture() const
{
assert(inited);
glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, g_frameBuffer );
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
}
void FrameBuffer::endCapture() const
{
assert(inited);
glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, 0 );
}
void FrameBuffer::bindTexture() const
{
assert(inited);
glBindTexture( GL_TEXTURE_2D, g_dynamicTextureID );
}