#include "BsGLRenderTexture.h" #include "BsGLPixelFormat.h" #include "BsGLPixelBuffer.h" #include "BsTextureView.h" namespace BansheeEngine { #define PROBE_SIZE 16 static const GLenum depthFormats[] = { GL_NONE, GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT32, GL_DEPTH24_STENCIL8, GL_DEPTH32F_STENCIL8 }; static const UINT32 depthBits[] = { 0, 16, 32, 24, 32 }; #define DEPTHFORMAT_COUNT (sizeof(depthFormats)/sizeof(GLenum)) GLRenderTexture::GLRenderTexture() :mFB(nullptr) { } GLRenderTexture::~GLRenderTexture() { } void GLRenderTexture::destroy_internal() { if(mFB != nullptr) bs_delete(mFB); RenderTexture::destroy_internal(); } void GLRenderTexture::initialize_internal() { if(mFB != nullptr) bs_delete(mFB); mFB = bs_new(); GLSurfaceDesc surfaceDesc; surfaceDesc.numSamples = mMultisampleCount; surfaceDesc.zoffset = 0; GLTexture* glTexture = static_cast(mColorSurface->getTexture().get()); surfaceDesc.buffer = glTexture->getBuffer(mColorSurface->getFirstArraySlice(), mColorSurface->getMostDetailedMip()); mFB->bindSurface(0, surfaceDesc); GLTexture* glDepthStencilTexture = static_cast(mDepthStencilSurface->getTexture().get()); GLPixelBufferPtr depthStencilBuffer = glDepthStencilTexture->getBuffer(mDepthStencilSurface->getFirstArraySlice(), mDepthStencilSurface->getMostDetailedMip()); mFB->bindDepthStencil(depthStencilBuffer); RenderTexture::initialize_internal(); } void GLRenderTexture::getCustomAttribute(const String& name, void* pData) const { if(name=="FBO") { *static_cast(pData) = mFB; } else if (name == "GL_FBOID" || name == "GL_MULTISAMPLEFBOID") { *static_cast(pData) = mFB->getGLFBOID(); } } GLRTTManager::GLRTTManager() { detectFBOFormats(); glGenFramebuffersEXT(1, &mTempFBO); } GLRTTManager::~GLRTTManager() { glDeleteFramebuffersEXT(1, &mTempFBO); } bool GLRTTManager::_tryFormat(GLenum depthFormat, GLenum stencilFormat) { GLuint status, depthRB = 0, stencilRB = 0; bool failed = false; if(depthFormat != GL_NONE) { // Generate depth renderbuffer glGenRenderbuffersEXT(1, &depthRB); // Bind it to FBO glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, depthRB); // Allocate storage for depth buffer glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, depthFormat, PROBE_SIZE, PROBE_SIZE); // Attach depth glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, depthRB); } if(stencilFormat != GL_NONE) { // Generate stencil renderbuffer glGenRenderbuffersEXT(1, &stencilRB); // Bind it to FBO glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, stencilRB); glGetError(); // Allocate storage for stencil buffer glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, stencilFormat, PROBE_SIZE, PROBE_SIZE); if(glGetError() != GL_NO_ERROR) failed = true; // Attach stencil glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, stencilRB); if(glGetError() != GL_NO_ERROR) failed = true; } status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); // Detach and destroy glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, 0); glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, 0); if (depthRB) glDeleteRenderbuffersEXT(1, &depthRB); if (stencilRB) glDeleteRenderbuffersEXT(1, &stencilRB); return status == GL_FRAMEBUFFER_COMPLETE_EXT && !failed; } bool GLRTTManager::_tryPackedFormat(GLenum packedFormat) { GLuint packedRB = 0; bool failed = false; // flag on GL errors // Generate renderbuffer glGenRenderbuffersEXT(1, &packedRB); // Bind it to FBO glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, packedRB); // Allocate storage for buffer glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, packedFormat, PROBE_SIZE, PROBE_SIZE); glGetError(); // Attach depth glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, packedRB); if(glGetError() != GL_NO_ERROR) failed = true; // Attach stencil glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, packedRB); if(glGetError() != GL_NO_ERROR) failed = true; GLuint status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); // Detach and destroy glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, 0); glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, 0); glDeleteRenderbuffersEXT(1, &packedRB); return status == GL_FRAMEBUFFER_COMPLETE_EXT && !failed; } void GLRTTManager::detectFBOFormats() { // Try all formats, and report which ones work as target GLuint fb = 0, tid = 0; GLint old_drawbuffer = 0, old_readbuffer = 0; GLenum target = GL_TEXTURE_2D; glGetIntegerv (GL_DRAW_BUFFER, &old_drawbuffer); glGetIntegerv (GL_READ_BUFFER, &old_readbuffer); for(size_t x=0; x