/* QGLView Ivan Pelipenko peri4ko@yandex.ru This program is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program. If not, see . */ #include "glframebuffer.h" GLFramebuffer::GLFramebuffer(int colorAttachments_, bool withDepth, GLenum colorFormat_, GLenum target__) { is_depth = withDepth; color_format = colorFormat_; target_ = target__; colors.fill(0, colorAttachments_); fbo = drbo = 0; tex_d = 0; wid = hei = 0; is_changed = false; } GLFramebuffer::~GLFramebuffer() { deleteGLFramebuffer(fbo); deleteGLRenderbuffer(drbo); for (int i = 0; i < colors.size(); ++i) deleteGLTexture(colors[i]); deleteGLTexture(tex_d); } void GLFramebuffer::resize(int width, int height, bool force) { if ((wid == width) && (hei == height) && !force) return; initializeOpenGLFunctions(); wid = width; hei = height; deleteGLFramebuffer(fbo); glGenFramebuffers(1, &fbo); glBindFramebuffer(GL_FRAMEBUFFER, fbo); for (int i = 0; i < colors.size(); ++i) { deleteGLTexture(colors[i]); createGLTexture(colors[i], width, height, color_format, target_); glTexParameteri(target_, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(target_, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(target_, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(target_, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(target_, GL_TEXTURE_MAX_LEVEL, 4); glTexParameteri(target_, GL_GENERATE_MIPMAP_SGIS, GL_FALSE); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, target_, colors[i], 0); } if (is_depth) { deleteGLTexture(tex_d); deleteGLRenderbuffer(drbo); glGenRenderbuffers(1, &drbo); glBindRenderbuffer(GL_RENDERBUFFER, drbo); glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, width, height); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, drbo); createGLTexture(tex_d, width, height, GL_DEPTH_COMPONENT); glTexParameteri(target_, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(target_, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(target_, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(target_, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(target_, GL_GENERATE_MIPMAP_SGIS, GL_FALSE); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, target_, tex_d, 0); } glBindFramebuffer(GL_FRAMEBUFFER, 0); is_changed = false; } QImage GLFramebuffer::grab() const { //glReadPixels(0, 0, wid, hei, GL_RGBA, ); //QImage ret(); return QImage(); } void GLFramebuffer::bind() { if (is_changed) resize(wid, hei); if (fbo == 0) return; initializeOpenGLFunctions(); //glFlush(); glGetIntegerv(GL_VIEWPORT, prev_view); //glClearError(); glBindFramebuffer(GL_FRAMEBUFFER, fbo); //qDebug() << QString::number(glGetError(), 16); QVector buffers; for (int i = 0; i < colors.size(); ++i) buffers << GL_COLOR_ATTACHMENT0 + i; glDrawBuffers(buffers.size(), buffers.constData()); glReadBuffer(GL_COLOR_ATTACHMENT0); //glDrawBuffer(GL_COLOR_ATTACHMENT0); glViewport(0, 0, wid, hei); } void GLFramebuffer::release() { is_changed = false; if (fbo == 0) return; //glFlush(); glBindFramebuffer(GL_FRAMEBUFFER, 0); glViewport(prev_view[0], prev_view[1], prev_view[2], prev_view[3]); } void GLFramebuffer::setWriteBuffer(int index) { //QVector buffers; buffers << GL_COLOR_ATTACHMENT0 + index; GLenum e = GL_COLOR_ATTACHMENT0 + index; glDrawBuffer(e); //glDrawBuffers(1, &e); } void GLFramebuffer::setWriteBuffers(int * indeces, int count) { QVector buffers; for (int i = 0; i < count; ++i) buffers << GL_COLOR_ATTACHMENT0 + indeces[i]; glDrawBuffers(buffers.size(), buffers.constData()); } void GLFramebuffer::bindColorTextures() { for (int i = colors.size() - 1; i >= 0; --i) { glActiveTexture(GL_TEXTURE0 + i); glBindTexture(GL_TEXTURE_2D, colors[i]); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); } } void GLFramebuffer::bindDepthTexture(int channel) { glActiveTexture(GL_TEXTURE0 + channel); glBindTexture(GL_TEXTURE_2D, tex_d); }