#include "BsGLFrameBufferObject.h" #include "BsGLPixelFormat.h" #include "BsGLPixelBuffer.h" #include "BsGLRenderTexture.h" #include "BsRenderStats.h" namespace BansheeEngine { GLFrameBufferObject::GLFrameBufferObject() { glGenFramebuffersEXT(1, &mFB); for(UINT32 x = 0; x < BS_MAX_MULTIPLE_RENDER_TARGETS; ++x) mColor[x].buffer = nullptr; BS_INC_RENDER_STAT_CAT(ResCreated, RenderStatObject_FrameBufferObject); } GLFrameBufferObject::~GLFrameBufferObject() { glDeleteFramebuffersEXT(1, &mFB); BS_INC_RENDER_STAT_CAT(ResDestroyed, RenderStatObject_FrameBufferObject); } void GLFrameBufferObject::bindSurface(UINT32 attachment, const GLSurfaceDesc &target) { assert(attachment < BS_MAX_MULTIPLE_RENDER_TARGETS); mColor[attachment] = target; if(mColor[0].buffer) rebuild(); } void GLFrameBufferObject::unbindSurface(UINT32 attachment) { assert(attachment < BS_MAX_MULTIPLE_RENDER_TARGETS); mColor[attachment].buffer = nullptr; if(mColor[0].buffer) rebuild(); } void GLFrameBufferObject::bindDepthStencil(GLPixelBufferPtr depthStencilBuffer) { mDepthStencilBuffer = depthStencilBuffer; } void GLFrameBufferObject::unbindDepthStencil() { mDepthStencilBuffer = nullptr; } void GLFrameBufferObject::rebuild() { // First buffer must be bound if(!mColor[0].buffer) BS_EXCEPT(InvalidParametersException, "Attachment 0 must have surface attached"); // Store basic stats UINT32 width = mColor[0].buffer->getWidth(); UINT32 height = mColor[0].buffer->getHeight(); GLuint glformat = mColor[0].buffer->getGLFormat(); PixelFormat format = mColor[0].buffer->getFormat(); UINT16 maxSupportedMRTs = BansheeEngine::RenderSystem::instancePtr()->getCapabilities()->getNumMultiRenderTargets(); // Bind simple buffer to add color attachments glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mFB); // Bind all attachment points to frame buffer for(UINT16 x = 0; x < maxSupportedMRTs; ++x) { if(mColor[x].buffer) { if(mColor[x].buffer->getWidth() != width || mColor[x].buffer->getHeight() != height) { StringStream ss; ss << "Attachment " << x << " has incompatible size "; ss << mColor[x].buffer->getWidth() << "x" << mColor[x].buffer->getHeight(); ss << ". It must be of the same as the size of surface 0, "; ss << width << "x" << height; ss << "."; BS_EXCEPT(InvalidParametersException, ss.str()); } if(mColor[x].buffer->getGLFormat() != glformat) { StringStream ss; ss << "Attachment " << x << " has incompatible format."; BS_EXCEPT(InvalidParametersException, ss.str()); } mColor[x].buffer->bindToFramebuffer(GL_COLOR_ATTACHMENT0_EXT + x, mColor[x].zoffset); } else { // Detach glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT + x, GL_RENDERBUFFER_EXT, 0); } } if(mDepthStencilBuffer != nullptr) mDepthStencilBuffer->bindToFramebuffer(GL_DEPTH_STENCIL_ATTACHMENT, 0); // Do glDrawBuffer calls GLenum bufs[BS_MAX_MULTIPLE_RENDER_TARGETS]; GLsizei n=0; for(UINT32 x=0; x