#include "TGLFBO.h"
#include <TMath.h>
#include <TString.h>
#include <GL/glew.h>
#include <stdexcept>
ClassImp(TGLFBO);
Bool_t TGLFBO::fgRescaleToPow2 = kTRUE;
TGLFBO::TGLFBO() :
fFrameBuffer (0),
fColorTexture (0),
fDepthBuffer (0),
fW (-1),
fH (-1),
fIsRescaled (kFALSE),
fWScale (1),
fHScale (1)
{
}
TGLFBO::~TGLFBO()
{
Release();
}
void TGLFBO::Init(int w, int h)
{
static const std::string eh("TGLFBO::Init ");
if (!GLEW_VERSION_1_5)
{
throw std::runtime_error(eh + "GL version 1.5 required for FBO.");
}
fIsRescaled = kFALSE;
if (fgRescaleToPow2)
{
Int_t nw = 1 << TMath::CeilNint(TMath::Log2(w));
Int_t nh = 1 << TMath::CeilNint(TMath::Log2(h));
if (nw != w || nh != h)
{
fWScale = ((Float_t)w) / nw;
fHScale = ((Float_t)h) / nh;
w = nw; h = nh;
fIsRescaled = kTRUE;
}
}
if (fFrameBuffer != 0)
{
if (fW == w || fH == h)
return;
Release();
}
Int_t maxSize;
glGetIntegerv(GL_MAX_RENDERBUFFER_SIZE_EXT, &maxSize);
if (w > maxSize || h > maxSize)
{
throw std::runtime_error(eh + Form("maximum size supported by GL implementation is %d.", maxSize));
}
fW = w; fH = h;
glGenFramebuffersEXT (1, &fFrameBuffer);
glGenTextures (1, &fColorTexture);
glGenRenderbuffersEXT(1, &fDepthBuffer);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fFrameBuffer);
glBindTexture(GL_TEXTURE_2D, fColorTexture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, fW, fH, 0, GL_RGB,
GL_UNSIGNED_BYTE, NULL);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
GL_TEXTURE_2D, fColorTexture, 0);
glBindRenderbufferEXT (GL_RENDERBUFFER_EXT, fDepthBuffer);
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT24, fW, fH);
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
GL_RENDERBUFFER_EXT, fDepthBuffer);
GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, 0);
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
glBindTexture (GL_TEXTURE_2D, 0);
switch (status)
{
case GL_FRAMEBUFFER_COMPLETE_EXT:
if (gDebug > 0)
printf("%sConstructed TGLFBO ... all fine.\n", eh.c_str());
break;
case GL_FRAMEBUFFER_UNSUPPORTED_EXT:
Release();
throw std::runtime_error(eh + "Constructed TGLFBO not supported, choose different formats.");
break;
default:
Release();
throw std::runtime_error(eh + "Constructed TGLFBO is crap, fix code in TGLFBO class.");
break;
}
}
void TGLFBO::Release()
{
glDeleteFramebuffersEXT (1, &fFrameBuffer);
glDeleteTextures (1, &fColorTexture);
glDeleteRenderbuffersEXT(1, &fDepthBuffer);
fColorTexture = fFrameBuffer = fDepthBuffer = 0;
fW = fH = -1;
}
void TGLFBO::Bind()
{
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fFrameBuffer);
}
void TGLFBO::Unbind()
{
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
}
void TGLFBO::BindTexture()
{
glPushAttrib(GL_TEXTURE_BIT);
glBindTexture(GL_TEXTURE_2D, fColorTexture);
glEnable(GL_TEXTURE_2D);
glMatrixMode(GL_TEXTURE);
glPushMatrix();
glScalef(fWScale, fHScale, 1);
glMatrixMode(GL_MODELVIEW);
}
void TGLFBO::UnbindTexture()
{
glMatrixMode(GL_TEXTURE);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
glPopAttrib();
}