#ifndef FBO_H #define FBO_H #include #include #include class fbo { public: int width, height; GLuint fbo_number; std::map renderbuffers; GLuint texture_id; public: fbo(int width, int height) : width(width), height(height), fbo_number(0), renderbuffers(), texture_id(0) { glGenFramebuffers(1, &fbo_number); bind(); // generate texture glGenTextures(1, &texture_id); glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, texture_id); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_BYTE, 0); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture_id, 0); // attach depth create_attach_renderbuffer(GL_DEPTH_COMPONENT, GL_DEPTH_ATTACHMENT); // attach stencil //create_attach_renderbuffer(GL_STENCIL_INDEX, GL_STENCIL_ATTACHMENT); check_status(); glClearColor(0.0, 0.0, 0.0, 0.0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); unbind(); } ~fbo() { end(); glDeleteFramebuffers(1, &fbo_number); for(auto& it : renderbuffers){ glDeleteFramebuffers(1, &it.second); } glDeleteTextures(1, &texture_id); } void begin(){ bind(); //glPushAttrib(GL_VIEWPORT); //glViewport(0, 0, width, height); /*GLint savedFramebuffer = -1; glGetIntegerv(GL_FRAMEBUFFER_BINDING, &savedFramebuffer); std::cout << "sfb: " << savedFramebuffer << ", fbo: " << fbo_number << std::endl;*/ } void end(){ unbind(); //glPopAttrib(); } private: void bind(){ glBindFramebuffer(GL_FRAMEBUFFER, fbo_number); GLenum status = glGetError(); if(status != GL_NO_ERROR) throw std::runtime_error("i has error" + std::to_string(status) + "with fbo: " + std::to_string(fbo_number)); } void unbind(){ glBindFramebuffer(GL_FRAMEBUFFER, 0); } void create_attach_renderbuffer(GLenum format, GLenum attachment_point) { GLuint buffer; glGenRenderbuffers(1, &buffer); glBindRenderbuffer(GL_RENDERBUFFER, buffer); glRenderbufferStorage(GL_RENDERBUFFER, format, width, height); glFramebufferRenderbuffer(GL_FRAMEBUFFER, attachment_point, GL_RENDERBUFFER, buffer); renderbuffers[format] = buffer; } void check_status() { GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); switch(status) { case GL_FRAMEBUFFER_COMPLETE: std::cout << "FRAMEBUFFER_COMPLETE - OK" << std::endl; return; case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: std::cout << "FRAMEBUFFER_INCOMPLETE_ATTACHMENT" << std::endl; break; case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: std::cout << "FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT" << std::endl; break; /*case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS: std::cout << "FRAMEBUFFER_INCOMPLETE_DIMENSIONS" << std::endl; break; case GL_FRAMEBUFFER_INCOMPLETE_FORMATS: std::cout << "FRAMEBUFFER_INCOMPLETE_FORMATS" << std::endl; break;*/ case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER: std::cout << "FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER" << std::endl; break; case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER: std::cout << "FRAMEBUFFER_INCOMPLETE_READ_BUFFER" << std::endl; break; case GL_FRAMEBUFFER_UNSUPPORTED: std::cout << "FRAMEBUFFER_UNSUPPORTED" << std::endl; break; case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE: std::cout << "GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE" << std::endl; break; default: std::cout << "UNKNOWN FRAMEBUFFER ERROR" << std::endl; break; } //throw std::runtime_error("I will not continu.."); } void check_error(){ GLenum status = glGetError(); if(status != GL_NO_ERROR){ throw std::runtime_error("GL Error: " + std::to_string(status)); } } }; #endif // FBO_H