Offscreen rendering to framebuffer object



  • Hi all,

    I need help with rendering to framebuffer object.
    I am making CAD viewer, 3D viewer as QOpenGLWidget embedded in QMainWindow.

    Problem is in picking mechanism. Described in:
    http://www.opengl-tutorial.org/miscellaneous/clicking-on-objects/picking-with-an-opengl-hack/

    In my Viewer class object, in its initializeGL() function I create FBO, initialize it and check if FBO isValid() and isBound(). Both are true.

    Viewer class has few viewer modes. But they render to default framebuffer fine.
    I pass created fbo* to temporary ViewerMode object, and bind it before calling glDraw**** functions.

    I have no idea why nothing gets rendered to it? It is empty. Besides, when saving framebuffer content, not only I get content of OpenGLWidget, but also part of Qt buttons. Like currently bound FBO is the one of the QMainWindow, not just from QOpenGLWidget, that is Viewer.

    My code is designed like this :

    class CentralWidget : public QWidget {
      Q_OBJECT
    public:
      explicit CentralWidget(QWidget *parent = nullptr);
      ~CentralWidget();
    private:
      void initializeCentralWidget();
      void connectObjects();
    
      QPushButton cancelBtn;
      QPushButton importBtn;
      QPushButton captureBtn;
      QPushButton defaultSelectionBtn;
      QPushButton pickSelectionBtn;
      QPushButton polySelectionBtn;
      QPushButton clearBtn;
    
      // Set layout
      QHBoxLayout *hBoxLayoutButtons = new QHBoxLayout;
      QVBoxLayout *vBoxLayoutGeneralButtons = new QVBoxLayout;
      QVBoxLayout *vBoxLayoutSelectionButtons = new QVBoxLayout;
      QVBoxLayout *vBoxLayout = new QVBoxLayout;
    
      FileManager fileManager_;
      QSignalMapper *signalMapper_;
      Viewer viewer_;
    }
    
    class Viewer : public QOpenGLWidget,
                   protected QOpenGLFunctions_4_3_Compatibility {
      Q_OBJECT
    
    public:
      Viewer();
      void initializeGL();
      void resizeGL(int width, int height);
      void paintGL();
    
      ~Viewer();
    
    public slots:
      void capture(uint xpos, uint ypos);
      void activateViewerMode(QString mode);
    
    protected slots:
      void teardownGL();
      void update();
    
    protected:
      void keyPressEvent(QKeyEvent *event);
      void keyReleaseEvent(QKeyEvent *event);
      void mousePressEvent(QMouseEvent *event);
      void mouseReleaseEvent(QMouseEvent *event);
      void wheelEvent(QWheelEvent *wheel);
    
    private:
      std::map<QString, ViewerMode *> viewerModeMap_;
      ViewerMode *tmpViewerMode;
      QOpenGLFramebufferObject *fbo_;    //< --  this is created  FBO
      bb::nVec<uint> selected_;
    
      QMatrix4x4 m_projection;
      Camera3D m_camera;
      Transform3D m_model;
    };
    

    creation of FBO inside Viewer::initializeGL() function :

      makeCurrent();
      QOpenGLFramebufferObjectFormat fbof;
      fbof.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
      fbof.setInternalTextureFormat(GL_RGB32F);
      fbo_ = new QOpenGLFramebufferObject(this->width(), this->height(), fbof);
    

    Viewer modes classes:

    class ViewerMode : public QOpenGLFunctions_4_3_Core ; // abstract class interface
    class DefaultViewerMode : public ViewerMode ;
    class PickViewerMode : public ViewerMode ;
    

    so rendering function is :

    void Viewer::paintGL() {
      makeCurrent();
      tmpViewerMode->paintGL();  // pickViewerMode object, for which fbo_ is both valid and bound in time of draw calls;
      return;
    }
    

    But when Viewer::mouseReleaseEvent() callback function try to fbo_->toImage().save("name", "png"), then the state is like this:

     fbo_->bind();
    std::cout << "is valid " << fbo_->isValid() << std::endl;                            // true 
    
    std::cout << "is NULL " << fbo_->toImage().isNull() << std::endl;           // false 
    std::cout << "bound " << fbo_->isBound() << std::endl;                          // false
    std::cout << "saved " << fbo_->toImage().save("pajdsad", "png") << std::endl; //  true
    std::cout << "is bound() after capture " << fbo_->isBound() << std::endl;    // FALSE
    

    this is the result ?
    0_1557751653122_pajdsad.png

    What am I missing ? Is it even possible to render to offscreen fbo this way? Documentation says that FBO need to have context properly set.
    But I don't know how to set it, or when was that lost, simply because nondefault FBO is bound ?

    Any link, idea, example or hint how to setup this context, or why my FBO saves whole widget, not only QOpenGLWidget content is very much appreciated.

    Sorry for noob question. I am new to this.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.