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.
-
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 usingMyWidget.h
as promoted class for it.
In order to implement the way you described in the second approach, I had to pass a customizedQGLFormat
to the constructor ofMyWidget.h
when instantiating an object of it inui_mainwindow.h
, but the problem is thatui_mainwindow.h
is always automatically regenerated every time I make a change in themainwindow.ui
file! And I have, again, add this portion of code toui_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 inmainwindow.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? -
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. -
@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 nameddesgner_widget
, how can I addMyWidget.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 useQOpenGLWidget
instead, I have changed my base class toQOpenGLWidget
, but then I got some performance issues. My frame rate dropped down to half!! The same code without changing anything, just replacingQGLWidget
byQOpenGLWidget
as a base class forMyWidget.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 usingQGLWidget
, 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. -
@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 thisdesigner_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); }