#include "pch.h" #include "log.h" #include "rtt.h" RTT::RTT() { fboID = 0; rboID = 0; w = 0; h = 0; } RTT::~RTT() { //destroy(); } void RTT::destroy() { if (rboID) { glDeleteRenderbuffers(1, &rboID); } if (texID) { unbindTexture(); glDeleteTextures(1, &texID); LOG("TEX rtt destroy %d", texID) } if (fboID) { unbindFramebuffer(); glDeleteFramebuffers(1, &fboID); LOG("RTT DESTROY %d", fboID); } texID = 0; fboID = 0; rboID = 0; // w = 0; // h = 0; } bool RTT::create(int width, int height, int tex/* = -1*/) { // Destroy any previously created object destroy(); w = width; h = height; if (tex == -1) { glGenTextures(1, &texID); LOG("TEX rtt create %d", texID); } else { texID = tex; } glBindTexture(GL_TEXTURE_2D, texID); if (tex == -1) glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glBindTexture(GL_TEXTURE_2D, 0); // Create a renderbuffer object to store depth info // glGenRenderbuffers(1, &rboID); // glBindRenderbuffer(GL_RENDERBUFFER, rboID); // glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, width, height); // glBindRenderbuffer(GL_RENDERBUFFER, 0); glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &oldFboID); // Create a framebuffer object glGenFramebuffers(1, &fboID); glBindFramebuffer(GL_FRAMEBUFFER, fboID); LOG("RTT CREATE %d - tex %d", fboID, texID); // Attach the texture to FBO color attachment point glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texID, 0); // Attach the renderbuffer to depth attachment point //glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rboID); auto err2str = [](GLenum err) { switch (err) { case GL_FRAMEBUFFER_UNDEFINED: return "GL_FRAMEBUFFER_UNDEFINED"; case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: return "GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT"; case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: return "GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT"; case GL_FRAMEBUFFER_UNSUPPORTED: return "GL_FRAMEBUFFER_UNSUPPORTED"; case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE: return "GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE"; default: return "UNKNOWN"; } }; // Check FBO status GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); if (status != GL_FRAMEBUFFER_COMPLETE) LOG("RTT::create failed because: %s", err2str(status)); // Switch back to window-system-provided framebuffer glBindFramebuffer(GL_FRAMEBUFFER, oldFboID); oldFboID = 0; return status == GL_FRAMEBUFFER_COMPLETE; } void RTT::bindFramebuffer() { #ifdef DEBUG if (bound) { LOG("framebuffer bound twice!"); #ifdef _WIN32 __debugbreak(); #endif } #endif // _DEBUG bound = true; glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &oldFboID); glBindFramebuffer(GL_FRAMEBUFFER, fboID); } void RTT::unbindFramebuffer() { glBindFramebuffer(GL_FRAMEBUFFER, oldFboID); oldFboID = 0; bound = false; } void RTT::clear(glm::vec4 color) { glClearColor(color.r, color.g, color.b, color.a); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); } void RTT::readTextureData(uint8_t* buffer) { glReadBuffer(GL_BACK); bindFramebuffer(); //glGetTexImage(GL_TEXTURE_2D, 0, GL_RGB, GL_UNSIGNED_BYTE, buffer); glReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, buffer); unbindFramebuffer(); glReadBuffer(GL_NONE); } uint8_t* RTT::createBuffer() { return new uint8_t[w * h * 4]; } void RTT::bindTexture() { glBindTexture(GL_TEXTURE_2D, texID); } void RTT::unbindTexture() { glBindTexture(GL_TEXTURE_2D, 0); }