#include #include "FrameBufferObject.h" #include "glInterface.h" using namespace std; namespace CHCDemoEngine { GLenum color_attachment[] = {GL_COLOR_ATTACHMENT0_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_COLOR_ATTACHMENT2_EXT, GL_COLOR_ATTACHMENT3_EXT}; void PrintFBOStatus(GLenum status) { switch(status) { case GL_FRAMEBUFFER_COMPLETE_EXT: //cout << "frame buffer object complete" << endl; break; case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT: cerr << "incomplete attachment" << endl; break; case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT: cerr << "missing attachment" << endl; break; case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT: cerr << "incomplete dimensions" << endl; break; case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT: cerr << "incomplete formats" << endl; break; case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT: cerr << "incomplete draw buffer" << endl; break; case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT: cerr << "incomplete read buffer" << endl; break; case GL_FRAMEBUFFER_UNSUPPORTED_EXT: cerr << "framebuffer unsupported" << endl; break; default: cerr << "unknown status code " << status << endl; } } ColorBufferObject::ColorBufferObject(int w, int h, FORMAT format, WRAP_TYPE wrapType, FILTER_TYPE filterType, bool useMipMap, int attachment_idx) { GLuint glformat, internalFormat; switch (format) { case BUFFER_UBYTE: glformat = GL_UNSIGNED_BYTE; internalFormat = GL_RGBA8; break; case BUFFER_FLOAT_16: glformat = GL_FLOAT; internalFormat = GL_RGBA16F_ARB; break; case BUFFER_FLOAT_32: glformat = GL_FLOAT; internalFormat = GL_RGBA32F_ARB; break; default: glformat = GL_UNSIGNED_BYTE; internalFormat = GL_RGBA8; cerr << "should not come here" << endl; } glGenRenderbuffersEXT(1, &mId); glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, mId); glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, internalFormat, w, h); glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, color_attachment[attachment_idx], GL_RENDERBUFFER_EXT, mId); glGenTextures(1, &mTexId); glBindTexture(GL_TEXTURE_2D, mTexId); glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, w, h, 0, GL_RGBA, glformat, NULL); glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, color_attachment[attachment_idx], GL_TEXTURE_2D, mTexId, 0); GLuint minfilterParam; GLuint magfilterParam; switch (filterType) { case FILTER_NEAREST: minfilterParam = GL_NEAREST; magfilterParam = GL_NEAREST; break; case FILTER_LINEAR: minfilterParam = GL_LINEAR; magfilterParam = GL_LINEAR; break; case FILTER_MIPMAP_LINEAR: minfilterParam = GL_NEAREST_MIPMAP_NEAREST; magfilterParam = GL_NEAREST; //minfilterParam = GL_LINEAR_MIPMAP_NEAREST; //magfilterParam = GL_LINEAR; break; default: minfilterParam = GL_NEAREST; magfilterParam = GL_NEAREST; cerr << "should not come here" << endl; } GLuint wrapParam; switch (wrapType) { case WRAP_REPEAT: wrapParam = GL_REPEAT; break; case WRAP_CLAMP_TO_EDGE: wrapParam = GL_CLAMP_TO_EDGE; break; } glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, magfilterParam); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minfilterParam); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrapParam); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapParam); if (useMipMap) glGenerateMipmapEXT(GL_TEXTURE_2D); // print status PrintFBOStatus(glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT)); } ColorBufferObject::~ColorBufferObject() { glDeleteRenderbuffersEXT(1, &mId); glDeleteTextures(1, &mTexId); } FrameBufferObject::FrameBufferObject(int w, int h, DEPTH_FORMAT d, bool useDepthTex) : mWidth(w), mHeight(h), mDepthTexId(0) { glGenFramebuffersEXT(1, &mId); Bind(); /////////// //-- create depth buffer if (d != DEPTH_NONE) { glGenRenderbuffersEXT(1, &mDepthId); glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, mDepthId); GLuint depthFormat; switch (d) { case DEPTH_16: depthFormat = GL_DEPTH_COMPONENT16; break; case DEPTH_24: depthFormat = GL_DEPTH_COMPONENT24; break; case DEPTH_32: depthFormat = GL_DEPTH_COMPONENT32; break; default: cerr << "should not come here" << endl; } glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, depthFormat, w, h); glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, mDepthId); if (useDepthTex) { glGenTextures(1, &mDepthTexId); glBindTexture(GL_TEXTURE_2D, mDepthTexId); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); glTexImage2D(GL_TEXTURE_2D, 0, depthFormat, mWidth, mHeight, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL); glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, mDepthTexId, 0); } } Release(); } FrameBufferObject::~FrameBufferObject() { glDeleteFramebuffersEXT(1, &mId); glDeleteRenderbuffersEXT(1, &mDepthId); if (mDepthTexId) glDeleteTextures(1, &mDepthTexId); CLEAR_CONTAINER(mColorBuffers); } int FrameBufferObject::AddColorBuffer(ColorBufferObject::FORMAT col, ColorBufferObject::WRAP_TYPE wrapType, ColorBufferObject::FILTER_TYPE filterType, bool useMipMap) { Bind(); const int idx = (int)mColorBuffers.size(); ColorBufferObject *colorBuf = new ColorBufferObject(mWidth, mHeight, col, wrapType, filterType, useMipMap, idx); mColorBuffers.push_back(colorBuf); Release(); return idx; } void FrameBufferObject::Bind() const { glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mId); } void FrameBufferObject::Release() { glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); } } // namespace