void ShaderEffectSource::updateBackbuffer() { if (!m_sourceItem || !QGLContext::currentContext()) return; // Multisampling is not (for now) supported. QSize size = QSize(m_sourceItem->width(), m_sourceItem->height()); if (!m_textureSize.isEmpty()) size = m_textureSize; if (size.height() > 0 && size.width() > 0) { QGLFramebufferObjectFormat format; format.setAttachment(QGLFramebufferObject::CombinedDepthStencil); format.setInternalTextureFormat(m_format); if (!m_fbo) { m_fbo = new ShaderEffectBuffer(size, format); } else { if (!m_fbo->isValid() || m_fbo->size() != size || m_fbo->format().internalTextureFormat() != GLenum(m_format)) { delete m_fbo; m_fbo = 0; m_fbo = new ShaderEffectBuffer(size, format); } } } // Note that real update for the source content happens in shadereffect.cpp m_dirtyTexture = false; }
void NightModeGraphicsEffect::draw(QPainter* painter) { int pixelRatio = painter->device()->devicePixelRatio(); QSize size(painter->device()->width() * pixelRatio, painter->device()->height() * pixelRatio); if (fbo && fbo->size() != size) { delete fbo; fbo = NULL; } if (!fbo) { QGLFramebufferObjectFormat format; format.setAttachment(QGLFramebufferObject::CombinedDepthStencil); format.setInternalTextureFormat(GL_RGBA); fbo = new NightModeGraphicsEffectFbo(size, format, pixelRatio); } QPainter fboPainter(fbo); drawSource(&fboPainter); painter->save(); painter->beginNativePainting(); program->bind(); const GLfloat pos[] = {-1, -1, +1, -1, -1, +1, +1, +1}; const GLfloat texCoord[] = {0, 0, 1, 0, 0, 1, 1, 1}; program->setUniformValue(vars.source, 0); program->setAttributeArray(vars.pos, pos, 2); program->setAttributeArray(vars.texCoord, texCoord, 2); program->enableAttributeArray(vars.pos); program->enableAttributeArray(vars.texCoord); glBindTexture(GL_TEXTURE_2D, fbo->texture()); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); program->release(); painter->endNativePainting(); painter->restore(); }
QPaintEngine* QGLPixmapData::paintEngine() const { if (!isValid()) return 0; if (m_renderFbo) return m_engine; if (useFramebufferObjects()) { extern QGLWidget* qt_gl_share_widget(); if (!QGLContext::currentContext()) qt_gl_share_widget()->makeCurrent(); QGLShareContextScope ctx(qt_gl_share_widget()->context()); QGLFramebufferObjectFormat format; format.setAttachment(QGLFramebufferObject::CombinedDepthStencil); format.setSamples(4); format.setInternalTextureFormat(GLenum(m_hasAlpha ? GL_RGBA : GL_RGB)); m_renderFbo = qgl_fbo_pool()->acquire(size(), format); if (m_renderFbo) { if (!m_engine) m_engine = new QGL2PaintEngineEx; return m_engine; } qWarning() << "Failed to create pixmap texture buffer of size " << size() << ", falling back to raster paint engine"; } // If the application wants to paint into the QPixmap, we first // force it to QImage format and then paint into that. // This is simpler than juggling multiple GL contexts. const_cast<QGLPixmapData *>(this)->forceToImage(); if (m_hasFillColor) { m_source.fill(PREMUL(m_fillColor.rgba())); m_hasFillColor = false; } return m_source.paintEngine(); }
QPaintEngine* QGLPixmapData::paintEngine() const { if (!isValid()) return 0; if (m_renderFbo) return m_engine; if (useFramebufferObjects()) { extern QGLWidget* qt_gl_share_widget(); if (!QGLContext::currentContext()) const_cast<QGLContext *>(qt_gl_share_context())->makeCurrent(); QGLShareContextScope ctx(qt_gl_share_context()); QGLFramebufferObjectFormat format; format.setAttachment(QGLFramebufferObject::CombinedDepthStencil); format.setSamples(4); format.setInternalTextureFormat(GLenum(m_hasAlpha ? GL_RGBA : GL_RGB)); m_renderFbo = qgl_fbo_pool()->acquire(size(), format); if (m_renderFbo) { if (!m_engine) m_engine = new QGL2PaintEngineEx; return m_engine; } qWarning() << "Failed to create pixmap texture buffer of size " << size() << ", falling back to raster paint engine"; } m_dirty = true; if (m_source.size() != size()) m_source = QImage(size(), QImage::Format_ARGB32_Premultiplied); if (m_hasFillColor) { m_source.fill(PREMUL(m_fillColor.rgba())); m_hasFillColor = false; } return m_source.paintEngine(); }
void FrameInfo::resize(uint w, uint h) // ---------------------------------------------------------------------------- // Change the size of the frame buffer used for rendering // ---------------------------------------------------------------------------- { assert(QGLContext::currentContext() || !"FrameInfo::resize without an OpenGL context???"); // Don't change anything if size stays the same if (renderFBO && renderFBO->width()==int(w) && renderFBO->height()==int(h)) return; IFTRACE(fbo) std::cerr << "[FrameInfo] Resize " << w << "x" << h << "\n"; GraphicSave *save = GL.Save(); // Delete anything we might have purge(); // If the size is too big, we shouldn't use multisampling, it crashes // on MacOSX const uint SAMPLES = 4; const uint maxTextureSize = GL.MaxTextureSize(); bool canMultiSample = QGLFramebufferObject::hasOpenGLFramebufferBlit() && TaoApp->hasFBOMultisample; if (w >= maxTextureSize || h >= maxTextureSize) { IFTRACE(fbo) std::cerr << "[FrameInfo] Disable multisample, too big " << maxTextureSize << "\n"; canMultiSample = false; } // Select whether we draw directly in texture or blit to it // If we can blit and suceed in creating a multisample buffer, // we first draw in a multisample buffer // with 4 samples per pixel. This cannot be used directly as texture. QGLFramebufferObjectFormat format; format.setInternalTextureFormat(this->format); // Enable mipmap for fbo if(PerformancesPage::texture2DMipmap()) format.setMipmap(true); format.setAttachment(QGLFramebufferObject::CombinedDepthStencil); if (canMultiSample) { QGLFramebufferObjectFormat mformat(format); mformat.setSamples(SAMPLES); renderFBO = new QGLFramebufferObject(w, h, mformat); // REVISIT: we pass format to have a depth buffer attachment. // This is required only when we want to later use depthTexture(). // TODO: specify at object creation? textureFBO = new QGLFramebufferObject(w, h, format); } else { renderFBO = new QGLFramebufferObject(w, h, format); textureFBO = renderFBO; } // The value of the min and mag filters of the underlying texture // are forced to GL_NEAREST by Qt, which are not the GL defaults. // => We must synchronize our cache or some later GL.TexParameter calls // may be ignored. GLint min, mag; GLuint tex = textureFBO->texture(); glBindTexture(GL_TEXTURE_2D, tex); // Query the actual values to be safe glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, &min); glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, &mag); glBindTexture(GL_TEXTURE_2D, 0); GL.BindTexture(GL_TEXTURE_2D, tex); GL.TexParameter(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min); GL.TexParameter(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, mag); if(PerformancesPage::texture2DMipmap()) GL.GenerateMipmap(GL_TEXTURE_2D); GL.Sync(STATE_textures); GL.BindTexture(GL_TEXTURE_2D, 0); // depthTextureID is optional, resize if we have one if (depthTextureID) resizeDepthTexture(w, h); // Store what context we created things in this->w = w; this->h = h; this->context = (QGLContext *) QGLContext::currentContext(); IFTRACE(fbo) std::cerr << "[FrameInfo] Resized " << w << "x" << h << " in " << context << "\n"; GL.Restore(save); // Clear the contents of the newly created frame buffer begin(true); end(); }
bool AmbientOcclusionPlugin::applyFilter(QAction *filter, MeshDocument &md, RichParameterSet & par, vcg::CallBackPos *cb) { MeshModel &m=*(md.mm()); if(ID(filter)==FP_FACE_AMBIENT_OCCLUSION ) perFace=true; else perFace = false; useGPU = par.getBool("useGPU"); useVBO = par.getBool("useVBO"); depthTexSize = par.getInt("depthTexSize"); depthTexArea = depthTexSize*depthTexSize; numViews = par.getInt("reqViews"); errInit = false; float dirBias = par.getFloat("dirBias"); Point3f coneDir = par.getPoint3f("coneDir"); float coneAngle = par.getFloat("coneAngle"); if(perFace) m.updateDataMask(MeshModel::MM_FACEQUALITY | MeshModel::MM_FACECOLOR); else m.updateDataMask(MeshModel::MM_VERTQUALITY | MeshModel::MM_VERTCOLOR); std::vector<Point3f> unifDirVec; GenNormal<float>::Uniform(numViews,unifDirVec); std::vector<Point3f> coneDirVec; GenNormal<float>::UniformCone(numViews, coneDirVec, math::ToRad(coneAngle), coneDir); std::random_shuffle(unifDirVec.begin(),unifDirVec.end()); std::random_shuffle(coneDirVec.begin(),coneDirVec.end()); int unifNum = floor(unifDirVec.size() * (1.0 - dirBias )); int coneNum = floor(coneDirVec.size() * (dirBias )); viewDirVec.clear(); viewDirVec.insert(viewDirVec.end(),unifDirVec.begin(),unifDirVec.begin()+unifNum); viewDirVec.insert(viewDirVec.end(),coneDirVec.begin(),coneDirVec.begin()+coneNum); numViews = viewDirVec.size(); this->glContext->makeCurrent(); this->initGL(cb,m.cm.vn); unsigned int widgetSize = std::min(maxTexSize, depthTexSize); QSize fbosize(widgetSize,widgetSize); QGLFramebufferObjectFormat frmt; frmt.setInternalTextureFormat(GL_RGBA); frmt.setAttachment(QGLFramebufferObject::Depth); QGLFramebufferObject fbo(fbosize,frmt); qDebug("Start Painting window size %i %i", fbo.width(), fbo.height()); GLenum err = glGetError(); fbo.bind(); processGL(m,viewDirVec); fbo.release(); err = glGetError(); const GLubyte* errname = gluErrorString(err); qDebug("End Painting"); this->glContext->doneCurrent(); return !errInit; }
void RenderHelper::renderScene(vcg::Shotf &view, MeshModel *mesh, RenderingMode mode, float camNear = 0, float camFar = 0) { int wt = view.Intrinsics.ViewportPx[0]; int ht = view.Intrinsics.ViewportPx[1]; rendmode = mode; QSize fbosize(wt, ht); QGLFramebufferObjectFormat frmt; frmt.setInternalTextureFormat(GL_RGBA); frmt.setAttachment(QGLFramebufferObject::Depth); QGLFramebufferObject fbo(fbosize,frmt); float _near, _far; if((camNear <= 0) || (camFar == 0)) // if not provided by caller, then evaluate using bbox { _near=0.1; _far=20000; GlShot< vcg::Shot<float> >::GetNearFarPlanes(view, mesh->cm.bbox, _near, _far); if(_near <= 0) _near = 0.01; if(_far < _near) _far = 1000; } else { _near = camNear; _far = camFar; } assert(_near <= _far); GLenum err = glGetError(); //render to FBO fbo.bind(); glViewport(0, 0, wt, ht); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); GlShot< vcg::Shot<float> >::SetView(view, _near, _far); err = glGetError(); bool use_colors=false; bool use_normals=false; if(rendmode == NORMAL) use_normals = true; if(rendmode == COLOR) use_colors = true; int program = programs[rendmode]; glDisable(GL_LIGHTING); //bind indices glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, ibo); //bind vertices glEnable(GL_COLOR_MATERIAL); glBindBufferARB(GL_ARRAY_BUFFER_ARB, vbo); glEnableClientState(GL_VERTEX_ARRAY); // activate vertex coords array glVertexPointer(3, GL_FLOAT, 0, 0); // last param is offset, not ptr err = glGetError(); glUseProgram(program); err = glGetError(); if(use_colors) { glBindBufferARB(GL_ARRAY_BUFFER_ARB, cbo); glEnableClientState(GL_COLOR_ARRAY); glColorPointer(4, GL_UNSIGNED_BYTE, 0, 0); } if(use_normals) { glBindBufferARB(GL_ARRAY_BUFFER_ARB, nbo); glEnableClientState(GL_NORMAL_ARRAY); glNormalPointer(GL_FLOAT, 0, 0); } err = glGetError(); if (mesh->cm.fn > 0) { glDrawElements(GL_TRIANGLES, mesh->cm.fn*3, GL_UNSIGNED_INT, (void *)0); } else { glDrawArrays(GL_POINTS, 0, mesh->cm.vn); } if(color != NULL) delete []color; if(depth != NULL) delete []depth; color = new unsigned char[wt * ht * 3]; depth = new floatbuffer(); depth->init(wt,ht); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glPixelStorei(GL_PACK_ALIGNMENT, 1); glReadPixels( 0, 0, wt, ht, GL_RGB, GL_UNSIGNED_BYTE, color); glReadPixels( 0, 0, wt, ht, GL_DEPTH_COMPONENT, GL_FLOAT, depth->data); //----- convert depth in world units mindepth = 1000000; maxdepth = -1000000; for(int pixit = 0; pixit<wt*ht; pixit++) { if (depth->data[pixit] == 1.0) depth->data[pixit] = 0; else depth->data[pixit] = _near*_far / (_far - depth->data[pixit]*(_far-_near)); // min and max for normalization purposes (e.g. weighting) if(depth->data[pixit] > maxdepth) maxdepth = depth->data[pixit]; if(depth->data[pixit] > maxdepth) maxdepth = depth->data[pixit]; } //----- err = glGetError(); glDisableClientState(GL_VERTEX_ARRAY); // deactivate vertex array if(use_colors) glDisableClientState(GL_COLOR_ARRAY); if(use_normals) glDisableClientState(GL_NORMAL_ARRAY); err = glGetError(); // bind with 0, so, switch back to normal pointer operation glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0); glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0); glEnable(GL_LIGHTING); // standard opengl pipeline is re-activated glUseProgram(0); GlShot< vcg::Shot<float> >::UnsetView(); glFinish(); //QImage l=fbo.toImage(); //l.save("rendering.jpg"); fbo.release(); }