How to use anti-aliasing on QGLWidget?



  • I really can't find a straightforward example/tutorial of how to enable anti-aliasing on GQLWidget correctly!
    I have a 3D scene that contains tons of horizontal lines. Moving the camera around makes me feel like swimming in a sea of mirage, caused by these waving lines.

    My Widget, on which I render the scene, looks something like this:

    MyWidget.h

    class MyWidget : public QGLWidget, protected QOpenGLFunctions_3_0
    {
        Q_OBJECT
    public:
        // some other stuff
    
    protected:
        virtual void initializeGL() override;
        virtual void paintGL() override;
        virtual void resizeGL(int,int) override;
    
       // some other stuff
    
    private:
    
       // some other stuff
    
    

    MyWidget.cpp

    void MyWidget::initializeGL()
    {
        initializeOpenGLFunctions();
        glClearColor(someColor); 
        glEnable(GL_DEPTH_TEST);
        glEnable(GL_MULTISAMPLE);
        glEnable(GL_LINE_SMOOTH);
    
        glViewport(0, 0, this->width(), this->height());
         
        //  initialize the rest of the data to be drawn  
    }
    
    void MyWidget::paintGL()
    {
        // draw the items
    }
    
    void MyWidge::resizeGL(int W, int H)
    {
        glViewport(0, 0, W, H);
        repaint();
    }
    

    I need to know what I have to add "and where to add", to my program in order to get rid of this funky effect?! Appreciate any help.


  • Moderators

    Antialiasing is an umbrella term for a large number of techniques so you need to be more specific what you want to achieve.
    In the old days of OpenGL you would do line antialiasing by smoothing them. Unfortunately this smoothing technique uses alpha channel, so to achieve the expected result you have to enable blending too, otherwise the result would be just thicker lines:

    void initializeGL() override
    {
       // your init code
       glEnable(GL_LINE_SMOOTH);
       glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
    }
    
    void MyWidget::paintGL()
    {
       glEnable(GL_BLEND);
       glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
        // draw the items
    }
    

    Later a multisampling technique was introduced, which does not require blending, but instead requires platform support to setup a multisampled surface format. This is achieved when setting up your QGLWidget by passing a customized format:

    QGLFormat format;
    format.setSamples(4); //this creates a 4x MSAA surface format
    // other format setup
    your_widget = new QGLWidget(format, parent);
    

    and then you can enable multisampling like this:

    void initializeGL() override
    {
       glEnable(GL_MULTISAMPLE);
    }
    

    Both these techniques have the drawback that they are implementation specific, meaning the result will look different on different platformas, hardware and even on different driver versions. If you want a full control over how you smooth the lines use a shader based solution and add a postrpocess step to your rendering. A simple and popular one is FXAA, which you can find implementation of for example on shadertoy.



  • @Chris-Kawa I just decided for the second approach, and the result was somehow satisfying, so thanks for the infos.
    But I must say it was a bit tricky to get it works, at least for me!

    But after I got it works, I got another problem, somehow related.
    I'm not rendering on the whole main window, instead on a sub-QWidget on the main window by using MyWidget.h as promoted class for it.
    In order to implement the way you described in the second approach, I had to pass a customized QGLFormat to the constructor of MyWidget.h when instantiating an object of it in ui_mainwindow.h, but the problem is that ui_mainwindow.h is always automatically regenerated every time I make a change in the mainwindow.ui file! And I have, again, add this portion of code to ui_mainwindow.h to get it works properly!!

    I may not be an experienced Qt user, but adding the same code to ui_mainwindow.h every time I make a change in my design in mainwindow.ui, is kind of frustrating and makes no sense. I don't know if this is the only way to get it done, or there may be a better way to go around this and I'm doing it all wrong?


  • Moderators

    ui_mainwindow.h is a generated file. You should never modify it manually as any changes will be lost after regenerating or if you share the code with someone.

    The way to do it right is not add the QGLWidget in the designer. Add it in code in your MainWindow constructor, right after the setupUi() call.


  • Qt Champions 2018

    @Chris-Kawa said in How to use anti-aliasing on QGLWidget?:

    QGLWidget

    The best way is to not use QGLWidget at all anymore in new projects.



  • @Chris-Kawa Sorry for keeping this being open, but can you please describe in a bit more detail how to achieve this?
    Say that the Widget in the designer, on which I want to render, is named desgner_widget , how can I add MyWidget.h as promoted class for it in the MainWindow constructor?



  • @Christian-Ehrlicher For my implementation I began initially using QGLWidget, but as some online resources stated that it is the old version and that I should use QOpenGLWidget instead, I have changed my base class to QOpenGLWidget, but then I got some performance issues. My frame rate dropped down to half!! The same code without changing anything, just replacing QGLWidget by QOpenGLWidget as a base class for MyWidget.h reduced my frame rate from about ~74f/s to under ~29f/s!!
    More specifically it drops down dramatically when using inputs events (keys/mouse) extensively. But when using QGLWidget, there is no big changes in frame rate, it stays almost consistent!
    And I had this problem only on windows, where on linux there were no difference between them.
    On linux I do use Qt 5.11.1, and on window Qt 5.12.5, so almost the newest on both.


  • Moderators

    @BoboFuego said in How to use anti-aliasing on QGLWidget?:

    how can I add MyWidget.h as promoted class for it in the MainWindow constructor?

    Promoted class won't allow you to pass parameters to a constructor. Just don't add it in the designer at all.
    Lets say you've got this designer_widget as a central widget of the mian window in the designer. Just delete it entirely and add it in code:

    MainWindow::Mainwindow(QWidget* parent) : QMainWindow(parent)
    {
        ui->setupUi(this);
        
        MyWidget* gl_widget = new MyWidget();
        setCentralWidget(gl_widget);
    }