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 CubeItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { // Render the inner scene into a framebuffer object. // We do this while the ordinary Qt paint engine has // control of the GL context rather than later when the // QGLPainter has control of the GL context. if (mScene) { if (!fbo) { QGLFramebufferObjectFormat format; format.setAttachment(QGLFramebufferObject::CombinedDepthStencil); //format.setSamples(8); fbo = new QGLFramebufferObject (mScene->sceneRect().size().toSize(), format); } QRectF rect(0, 0, fbo->size().width(), fbo->size().height()); QPainter fboPainter(fbo); fboPainter.save(); QLinearGradient gradient(rect.topLeft(), rect.bottomRight()); gradient.setColorAt(0, QColor(0, 128, 192, 255)); gradient.setColorAt(1, QColor(0, 0, 128, 255)); fboPainter.setPen(QPen(Qt::black, 3)); fboPainter.setBrush(gradient); fboPainter.drawRect(rect); fboPainter.restore(); mScene->render(&fboPainter, rect); } // Now render the GL parts of the item using QGLPainter. QGLGraphicsViewportItem::paint(painter, option, widget); }
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(); }
void SVG::renderToTexture(const QRectF& textureRect, QGLFramebufferObjectPtr targetFbo) { saveGLState(); // generate and set view box in logical coordinates QRectF viewbox(svgExtents_.x() + textureRect.x() * svgExtents_.width(), svgExtents_.y() + textureRect.y() * svgExtents_.height(), textureRect.width() * svgExtents_.width(), textureRect.height() * svgExtents_.height()); svgRenderer_.setViewBox(viewbox); // Multisampled FBO for anti-aliased rendering QGLFramebufferObjectFormat format; format.setAttachment(QGLFramebufferObject::CombinedDepthStencil); format.setSamples(MULTI_SAMPLE_ANTI_ALIASING_SAMPLES); QGLFramebufferObjectPtr renderFbo( new QGLFramebufferObject( targetFbo->size(), format )); // Render to multisampled FBO QPainter painter(renderFbo.get()); painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing); svgRenderer_.render(&painter); painter.end(); // Copy to texture FBO QGLFramebufferObject::blitFramebuffer( targetFbo.get(), QRect(0, 0, renderFbo->width(), renderFbo->height()), renderFbo.get(), QRect(0, 0, renderFbo->width(), renderFbo->height())); glBindTexture(GL_TEXTURE_2D, targetFbo->texture()); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); restoreGLState(); }
void FBORenderStrategy::createFBOs(const QSize& size) { if (multisampleFBO && resolveFBO && resolveFBO->size() == size) return; // Create a multisample FBO and an FBO to resolve into QGLFramebufferObjectFormat fboFormat; fboFormat.setSamples(4); fboFormat.setAttachment(QGLFramebufferObject::CombinedDepthStencil); delete multisampleFBO; multisampleFBO = new QGLFramebufferObject(size, fboFormat); delete resolveFBO; resolveFBO = new QGLFramebufferObject(size); }
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(); }
GLWidget::GLWidget(QWidget *parent) : QGLWidget(QGLFormat(QGL::SampleBuffers|QGL::AlphaChannel), parent) { setWindowTitle(tr("OpenGL framebuffer objects")); makeCurrent(); if (QGLFramebufferObject::hasOpenGLFramebufferBlit()) { QGLFramebufferObjectFormat format; format.setSamples(4); format.setAttachment(QGLFramebufferObject::CombinedDepthStencil); render_fbo = new QGLFramebufferObject(512, 512, format); texture_fbo = new QGLFramebufferObject(512, 512); } else { render_fbo = new QGLFramebufferObject(1024, 1024); texture_fbo = render_fbo; } rot_x = rot_y = rot_z = 0.0f; scale = 0.1f; anim = new QTimeLine(750, this); anim->setUpdateInterval(20); connect(anim, SIGNAL(valueChanged(qreal)), SLOT(animate(qreal))); connect(anim, SIGNAL(finished()), SLOT(animFinished())); svg_renderer = new QSvgRenderer(QLatin1String(":/res/bubbles.svg"), this); connect(svg_renderer, SIGNAL(repaintNeeded()), this, SLOT(draw())); logo = QImage(":/res/designer.png"); logo = logo.convertToFormat(QImage::Format_ARGB32); tile_list = glGenLists(1); glNewList(tile_list, GL_COMPILE); glBegin(GL_QUADS); { glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f); glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f, 1.0f); glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, 1.0f); glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 1.0f); glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f); glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f); glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f, 1.0f, -1.0f); glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f); glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f); glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, 1.0f, 1.0f); glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, 1.0f, 1.0f); glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, -1.0f); glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, -1.0f, -1.0f); glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f, -1.0f, -1.0f); glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, 1.0f); glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f); glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f); glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, -1.0f); glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f, 1.0f, 1.0f); glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, 1.0f); glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f); glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f); glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 1.0f); glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f); } glEnd(); glEndList(); wave = new GLfloat[logo.width()*logo.height()]; memset(wave, 0, logo.width()*logo.height()); startTimer(30); // wave timer }
void Layer::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { QtPainter *qvpainter = NULL; #ifdef QT_OPENGL_LIB QPainter *fboPainter; QGLFramebufferObject *fbo = NULL; QGLWidget *qglWidget = qobject_cast<QGLWidget *>(widget); if (qglWidget) { // on-screen OpenGL QGLContext *context = const_cast<QGLContext *>(qglWidget->context()); qvpainter = new OpenGLPainter(painter, context); } else if (cacheMode() != QGraphicsItem::NoCache && QGLFramebufferObject::hasOpenGLFramebufferObjects()) { // caching, try FBO // if we have direct rendering and FBO support, make use of // FBO, but this could still just be in software // NOTE: In Qt 4.6, 'painter' would already target an FBO, if we // were using the 'OpenGL2' paint engine. We have decided to stick // with the original engine for now, as the OpenGL2 engine relies // heavily on shaders, which is slow for our use case. // Apparently, we must use the QGLContext associated with // the view being painted. Thus, PlotView tracks whether it is // inside a paintEvent, so we can get the current QGLWidget. OverlayScene *overlayScene = qobject_cast<OverlayScene *>(scene()); if (overlayScene) qglWidget = qobject_cast<QGLWidget *>(overlayScene->view()->viewport()); else { QList<QGraphicsView *> views = scene()->views(); for (int i = 0; i < views.size() && !qglWidget; i++) { PlotView *view = qobject_cast<PlotView *>(views[i]); if (view && view->isPainting()) qglWidget = qobject_cast<QGLWidget *>(view->viewport()); } } if (qglWidget) { QSize size(painter->device()->width(), painter->device()->height()); QGLContext *context = const_cast<QGLContext *>(qglWidget->context()); // GC during paint callback may have reset this if (qglWidget->context() != QGLContext::currentContext()) qglWidget->makeCurrent(); // NOTE: need Qt 4.6 for antialiasing to work with FBOs #if QT_VERSION >= 0x40600 if (!fboMultisamplingFailed) { QGLFramebufferObjectFormat fboFormat; fboFormat.setAttachment(QGLFramebufferObject::CombinedDepthStencil); fboFormat.setSamples(4); // 4X antialiasing should be enough? qInstallMsgHandler(fboDebugMsgCatcher); fbo = new QGLFramebufferObject(size, fboFormat); qInstallMsgHandler(0); if (fboMultisamplingFailed) { delete fbo; fbo = NULL; } } #endif if (!fbo) fbo = new QGLFramebufferObject(size); // clear the FBO fboPainter = new QPainter(fbo); fboPainter->setCompositionMode(QPainter::CompositionMode_Source); fboPainter->fillRect(0, 0, size.width(), size.height(), Qt::transparent); fboPainter->setCompositionMode(QPainter::CompositionMode_SourceOver); qvpainter = new OpenGLPainter(fboPainter, context); qvpainter->setTransform(painter->worldTransform()); } } #endif if (!qvpainter) // fallback to Qt renderer qvpainter = new QtPainter(painter); // NOTE: in QT 4.6 exposedRect will just be the bounding rect, by default paintPlot(qvpainter, option->exposedRect); delete qvpainter; #ifdef QT_OPENGL_LIB if (fbo) { // silliness: download to image, only to upload to texture painter->setWorldMatrixEnabled(false); qglWidget->makeCurrent(); // gc during callback may have cleared this // need to tell Qt that 'fboImage' is actually premultiplied QImage fboImage = fbo->toImage(); const uchar *data = fboImage.bits(); // no deep copy QImage premultImage = QImage(data, fboImage.width(), fboImage.height(), QImage::Format_ARGB32_Premultiplied); // Not sure why this can't be (0, 0)... painter->drawImage(QPointF(1, -1), premultImage); delete fboPainter; delete fbo; } #endif }
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 MouseMagnifyingGlassInteractorComponent::generateMagnifyingGlassTexture(const Coord &magnifyingGlassCenterScr) { bool antialiased = false; bool canUseMultisampleFbo = OpenGlConfigManager::getInst().isExtensionSupported("GL_EXT_framebuffer_multisample"); if (QGLFramebufferObject::hasOpenGLFramebufferBlit() && canUseMultisampleFbo) { antialiased = true; } int fboSize = static_cast<int>(radius * 2); // instantiate fbo if needed if (fbo == NULL) { QGLFramebufferObjectFormat fboFormat; fboFormat.setAttachment(QGLFramebufferObject::CombinedDepthStencil); if (antialiased) { fboFormat.setSamples(OpenGlConfigManager::getInst().maxNumberOfSamples()); } fbo = new QGLFramebufferObject(fboSize, fboSize, fboFormat); if (antialiased) { fbo2 = new QGLFramebufferObject(fboSize, fboSize); } if (!antialiased) { GlTextureManager::getInst().registerExternalTexture(textureName, fbo->texture()); } else { GlTextureManager::getInst().registerExternalTexture(textureName, fbo2->texture()); } } Vector<int, 4> viewport = glWidget->getScene()->getViewport(); // get the magnifying glass bounding box in screen space BoundingBox boundingBox; boundingBox[0] = Coord(magnifyingGlassCenterScr.getX() - radius, magnifyingGlassCenterScr.getY() - radius); boundingBox[1] = Coord(magnifyingGlassCenterScr.getX() + radius, magnifyingGlassCenterScr.getY() + radius); // compute the zoom factor to apply to scene's camera to get the area under the magnifying glass displayed entirely in the viewport float bbWidthScreen = boundingBox[1][0] - boundingBox[0][0]; float bbHeightScreen = boundingBox[1][1] - boundingBox[0][1]; float startSize = glWidget->screenToViewport(min(glWidget->width(), glWidget->height())); float endSize = max(bbHeightScreen, bbWidthScreen); float zoomFactor = startSize / endSize; // backup current camera parameters float sceneRadiusBak = camera->getSceneRadius(); float zoomFactorBak = camera->getZoomFactor(); Coord eyesBak = camera->getEyes(); Coord centerBak = camera->getCenter(); Coord upBak = camera->getUp(); Coord move = boxCenter - centerBak; camera->setCenter(camera->getCenter() + move); camera->setEyes(camera->getEyes() + move); camera->setZoomFactor(magnifyPower * zoomFactor * zoomFactorBak); glPushAttrib(GL_ALL_ATTRIB_BITS); glMatrixMode(GL_PROJECTION); glPushMatrix(); glMatrixMode(GL_MODELVIEW); glPushMatrix(); // resize the viewport to the size of fbo and render the scene into this last one GlScene *scene = glWidget->getScene(); scene->setViewport(0, 0, fboSize, fboSize); fbo->bind(); Color color = scene->getBackgroundColor(); glClearColor(color.getRGL(), color.getGGL(), color.getBGL(), color.getAGL()); glClear(GL_COLOR_BUFFER_BIT); scene->draw(); fbo->release(); if (antialiased) { QGLFramebufferObject::blitFramebuffer(fbo2, QRect(0,0,fboSize, fboSize), fbo, QRect(0,0,fboSize, fboSize)); } // restore original camera parameters scene->setViewport(viewport[0], viewport[1], viewport[2], viewport[3]); camera->setSceneRadius(sceneRadiusBak); camera->setZoomFactor(zoomFactorBak); camera->setEyes(eyesBak); camera->setCenter(centerBak); camera->setUp(upBak); glMatrixMode(GL_MODELVIEW); glPopMatrix(); glMatrixMode(GL_PROJECTION); glPopMatrix(); glPopAttrib(); // need to call this explicitely otherwise we have to redraw the scene glViewport(viewport[0], viewport[1], viewport[2], viewport[3]); }
void QwtPlotGLCanvas::paintGL() { const bool hasFocusIndicator = hasFocus() && focusIndicator() == CanvasFocusIndicator; QPainter painter; #if QT_VERSION < 0x040600 painter.begin( this ); draw( &painter ); #else if ( testPaintAttribute( QwtPlotGLCanvas::BackingStore ) ) { if ( d_data->fbo == NULL || d_data->fbo->size() != size() ) { invalidateBackingStore(); const int numSamples = 16; QGLFramebufferObjectFormat format; format.setSamples( numSamples ); format.setAttachment(QGLFramebufferObject::CombinedDepthStencil); QGLFramebufferObject fbo( size(), format ); QPainter fboPainter( &fbo ); draw( &fboPainter); fboPainter.end(); d_data->fbo = new QGLFramebufferObject( size() ); QRect rect(0, 0, width(), height()); QGLFramebufferObject::blitFramebuffer(d_data->fbo, rect, &fbo, rect); } // drawTexture( QRectF( -1.0, 1.0, 2.0, -2.0 ), d_data->fbo->texture() ); if ( hasFocusIndicator ) painter.begin( this ); glBindTexture(GL_TEXTURE_2D, d_data->fbo->texture()); glEnable(GL_TEXTURE_2D); glBegin(GL_QUADS); glTexCoord2f(0.0f, 0.0f); glVertex2f(-1.0f, -1.0f); glTexCoord2f(1.0f, 0.0f); glVertex2f( 1.0f, -1.0f); glTexCoord2f(1.0f, 1.0f); glVertex2f( 1.0f, 1.0f); glTexCoord2f(0.0f, 1.0f); glVertex2f(-1.0f, 1.0f); glEnd(); } else { painter.begin( this ); draw( &painter ); } #endif if ( hasFocus() && focusIndicator() == CanvasFocusIndicator ) drawFocusIndicator( &painter ); }
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(); }