I'm trying to use OpenGL inside of Qt using QOpenGLWidget, but I am having a hard time finding any relevant examples. I am new to OpenGL, so I am trying to learn how to use it, but the tutorials that I find don't seem to apply particularly well in QOpenGLWidget. Right now, all I want to do is render a triangle to start with.
Here's what I have so far.
Header:
namespace Ui {
class Widget;
}
class Widget : public QOpenGLWidget, protected QOpenGLFunctions
{
public:
explicit Widget(QWidget *parent = 0);
~Widget();
protected:
void initializeGL();
void resizeGL(int, int);
void paintGL();
private:
Ui::Widget *ui;
};
Class:
Widget::Widget(QWidget *parent) :
QOpenGLWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
}
void Widget::initializeGL()
{
// Set up the rendering context, load shaders and other resources, etc.:
initializeOpenGLFunctions();
glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
}
void Widget::resizeGL(int w, int h)
{
// Update projection matrix and other size-related settings:
}
void Widget::paintGL()
{
// Draw the scene:
glClear(GL_COLOR_BUFFER_BIT);
}
Widget::~Widget()
{
delete ui;
}
Is there any example I could use to just render a basic triangle? I tried the one from here: https://www.khronos.org/assets/uploads/books/openglr_es_20_programming_guide_sample.pdf, but it threw a lot of errors that I couldn't work out.
I also don't know how OpenGL contexts work in QOpenGLWidget.
*EDIT: So it turns out that the examples were a separate package on my distro (Arch Linux). I was able to install them, and it looks like there is plenty there to get started.
Thanks for your help!
If you want to use QOpenGLWidget not QGLWidget, then this is the way to do it.
Open Qt Creator and choose Qt Widgets Application. Add Widget and push button as follows
main.cpp
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
Now add New Class and name it OGLWidget which should be inherited from QOpenGLWidget
oglwidget.h
#ifndef OGLWIDGET_H
#define OGLWIDGET_H
#include <QWidget>
#include <QOpenGLWidget>
#include <gl/GLU.h>
#include <gl/GL.h>
class OGLWidget : public QOpenGLWidget
{
public:
OGLWidget(QWidget *parent = 0);
~OGLWidget();
protected:
void initializeGL();
void resizeGL(int w, int h);
void paintGL();
};
#endif // OGLWIDGET_H
oglwidget.cpp
#include "oglwidget.h"
OGLWidget::OGLWidget(QWidget *parent)
: QOpenGLWidget(parent)
{
}
OGLWidget::~OGLWidget()
{
}
void OGLWidget::initializeGL()
{
glClearColor(0,0,0,1);
glEnable(GL_DEPTH_TEST);
glEnable(GL_LIGHT0);
glEnable(GL_LIGHTING);
glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
glEnable(GL_COLOR_MATERIAL);
}
void OGLWidget::paintGL()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glBegin(GL_TRIANGLES);
glColor3f(1.0, 0.0, 0.0);
glVertex3f(-0.5, -0.5, 0);
glColor3f(0.0, 1.0, 0.0);
glVertex3f( 0.5, -0.5, 0);
glColor3f(0.0, 0.0, 1.0);
glVertex3f( 0.0, 0.5, 0);
glEnd();
}
void OGLWidget::resizeGL(int w, int h)
{
glViewport(0,0,w,h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45, (float)w/h, 0.01, 100.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(0,0,5,0,0,0,0,1,0);
}
Now go back to the form and right click on the widget. Select promoted widgets and type in the promoted class name OGLWidget. Hit the add button and then promote. Now click on the background and go to its properties and change windowModality to ApplicationModel.
and this is the result you should get
the .pro file is
#-------------------------------------------------
#
# Project created by QtCreator 2015-07-20T15:15:29
#
#-------------------------------------------------
QT += core gui opengl
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TARGET = test2
TEMPLATE = app
SOURCES += main.cpp\
mainwindow.cpp \
oglwidget.cpp
HEADERS += mainwindow.h \
oglwidget.h
FORMS += mainwindow.ui
Related
As is widely known that, to make a QWidget/QOpenGLWidget translucent/transparent, one only needs to:
widget->setAttribute(Qt::WA_TranslucentBackground)
However, since QWindow/QOpenGLWindow is not a widget and doesn't have setAttribute, I don't know how to do the same for a QOpenGLWindow. I guess this is theoretically possible since QWidget is backed by a QWindow according to Qt's source code.
I searched on Google but there's not much information about the transparency of QWindow
I found out that this will happen in QOpenGLWindow by QSurfaceFormat and setAlphaBufferSize(8);
Look at this example:
in mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QOpenGLWindow>
class MainWindow: public QOpenGLWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
// QOpenGLWindow interface
protected:
void initializeGL();
void resizeGL(int w, int h);
void paintGL();
// QWindow interface
void resizeEvent(QResizeEvent *);
// QPaintDeviceWindow interface
void paintEvent(QPaintEvent *event);
};
#endif // MAINWINDOW_H
in mainwindow.cpp
#include "mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
{
}
MainWindow::~MainWindow()
{
}
void MainWindow::initializeGL()
{
// Set the transparency to the scene to use the transparency of the fragment shader
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
// set the background color = clear color
glClearColor(0.0f, 0.0f, 0.0f, .0f);
glClear(GL_COLOR_BUFFER_BIT);
}
void MainWindow::resizeGL(int w, int h)
{
}
void MainWindow::paintGL()
{
}
void MainWindow::resizeEvent(QResizeEvent *)
{
}
void MainWindow::paintEvent(QPaintEvent *event)
{
paintGL();
}
and finally in main.cpp
#include "mainwindow.h"
#include <QGuiApplication>
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
QSurfaceFormat format;
format.setRenderableType(QSurfaceFormat::OpenGL);
format.setProfile(QSurfaceFormat::CoreProfile);
format.setVersion(3, 3);
format.setAlphaBufferSize(8);
MainWindow w;
w.setFormat(format);
w.resize(640, 480);
w.show();
return app.exec();
}
I w.setFormat(format); which means that QOpenGLWindow or MainWindow not QOpenGLContext.
This will be the Result:
I have a simple form in which I add an OpenGLWidget, and then set my "MyOpenGLWidget" class to the Promoted Class,
it is successfully created, but is not displayed.
Its constructor is called, but the initializeGL, resizeGL, and paintGL functions are not called.
Here is all my code:
main.cpp
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
ui_mainwindow.h
class Ui_MainWindow
{
public:
QWidget *centralwidget;
MyOpenGLWidget *openGLWidget;
void setupUi(QMainWindow *MainWindow)
{
if (MainWindow->objectName().isEmpty())
MainWindow->setObjectName(QString::fromUtf8("MainWindow"));
MainWindow->resize(420, 300);
centralwidget = new QWidget(MainWindow);
centralwidget->setObjectName(QString::fromUtf8("centralwidget"));
openGLWidget = new MyOpenGLWidget(centralwidget);
openGLWidget->setObjectName(QString::fromUtf8("openGLWidget"));
openGLWidget->setGeometry(QRect(60, 50, 300, 200));
MainWindow->setCentralWidget(centralwidget);
retranslateUi(MainWindow);
QMetaObject::connectSlotsByName(MainWindow);
} // setupUi
void retranslateUi(QMainWindow *MainWindow)
{
MainWindow->setWindowTitle(QCoreApplication::translate("MainWindow", "MainWindow", nullptr));
} // retranslateUi
};
namespace Ui {
class MainWindow: public Ui_MainWindow {};
} // namespace Ui
QT_END_NAMESPACE
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
myopenglwidget.cpp
#include "myopenglwidget.h"
#include "globalvars.h"
#include "gl/GLU.h"
MyOpenGLWidget::MyOpenGLWidget(QWidget* parent)
{
qInfo() << "MyOpenGLWidget called";
}
MyOpenGLWidget::~MyOpenGLWidget()
{
qInfo() << "~MyOpenGLWidget called";
}
void MyOpenGLWidget::initializeGL()
{
qInfo() << "initializeGL called!";
initializeOpenGLFunctions();
globalOpenGLContext = this->context();
glClearColor(0.0, 0.0, 0.0, 0.0);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(-this->width() / 2, this->width() / 2, -this->height() / 2, this->height() / 2);
glViewport(0, 0, this->width(), this->height());
}
void MyOpenGLWidget::resizeGL(int w, int h)
{
qInfo() << "resizeGL called!";
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(-w / 2, w / 2, -h / 2, h / 2);
glViewport(0, 0, w, h);
}
void MyOpenGLWidget::paintGL()
{
qInfo() << "paintGL called!";
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glColor3f(1, 1, 1);
glPushMatrix();
glBegin(GL_POLYGON);
glVertex3f(-100, 100, 0);
glVertex3f(100, 100, 0);
glVertex3f(100, -100, 0);
glVertex3f(-100, -100, 0);
glEnd();
glPopMatrix();
update();
}
myopenglwidget.h
#ifndef MYOPENGLWIDGET_H
#define MYOPENGLWIDGET_H
#include <QDebug>
#include <QOpenGLWidget>
#include <qopenglfunctions_3_3_core.h>
#include <gl/GLU.h>
class MyOpenGLWidget : public QOpenGLWidget, protected QOpenGLFunctions_3_3_Core
{
Q_OBJECT
public:
MyOpenGLWidget(QWidget *parent = nullptr);
~MyOpenGLWidget();
protected:
void initializeGL();
void resizeGL(int w, int h);
void paintGL();
};
#endif // MYOPENGLWIDGET_H
#include "gl/GLU.h"
This is not portable and, in particular, doesn't compile on Linux. The proper include is <GL/glu.h>.
MyOpenGLWidget::MyOpenGLWidget(QWidget* parent)
{
qInfo() << "MyOpenGLWidget called";
}
You ignore the parent parameter, thus leaving your widget a window, rather than a child of its parent. But then you don't call QWidget::show() on it, so this separate window remains invisible, unlike the main window.
#include <qopenglfunctions_3_3_core.h>
It's not the public header. You should include <QOpenGLFunctions_3_3_Core> instead.
glBegin(GL_POLYGON);
glVertex3f(-100, 100, 0);
glVertex3f(100, 100, 0);
glVertex3f(100, -100, 0);
glVertex3f(-100, -100, 0);
glEnd();
Given that you include OpenGL 3.3 Core functions header, these long-obsolete functions aren't supposed to be used. They don't exist in OpenGL Core profile.
Moreover, just calling them as this, directly, ignores the QOpenGLOpenGLFunctions... class completely. You should get an instance of this class from OpenGL context and call its methods.
I am trying to run basic examples of OpenGL using QT Creator to give color to a window. However, I am getting error in the compilation when calling the OpenGL instruction:
glClearColor(1.0,1.0,0.0,1.0);
The *.pro file is the next:
QT += core gui opengl
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TARGET = test2
TEMPLATE = app
SOURCES += main.cpp\
mainwindow.cpp \
glwidget.cpp
HEADERS += mainwindow.h \
glwidget.h
FORMS += mainwindow.ui
The glwidget.h is the next:
#ifndef GLWIDGET_H
#define GLWIDGET_H
#include <QGLWidget>
class GLWidget : public QGLWidget
{
Q_OBJECT
public:
explicit GLWidget(QWidget *parent = 0);
void initializeGL();
};
#endif // GLWIDGET_H
The glwidget.cpp is the next:
#include "glwidget.h"
GLWidget::GLWidget(QWidget *parent) :
QGLWidget(parent)
{
}
void GLWidget::initializeGL(){
glClearColor(1.0,1.0,0.0,1.0);
}
The main.cpp:
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
I have checked that in the *.pro I have included opengl:
QT += core gui opengl
In addition, I have deleted the "YourProjectName-build-desktop" folder created by QT Creator and build again without success.
The error is:
C:\test2\glwidget.cpp:9: error: undefined reference to `_imp__glClearColor#16'
where line 9 is glClearColor(1.0,1.0,0.0,1.0);
Which extra step I am missing?
Thank you in advance for your help
Cheers
© 2016 Microsoft Terms Privacy & cookies Developers English (United States)
try adding LIBS += -lOpengl32 to .pro file
and if you`re using qt 5 you might as well take this route
QOpenGLFunctions *f = QOpenGLContext::currentContext()->functions();
f->glClearColor(1.0f, 1.0f, 0.0f, 1.0f);
http://doc.qt.io/qt-5/qopenglwidget.html
http://doc.qt.io/qt-5/qopenglcontext.html
EDIT:
just tested this an it works. but requires qt5.
Legacy functions seem to be defined in qt 5 so i left out QOpenGLFunctions.
#include <QOpenGLWidget>
class GLWidget : public QOpenGLWidget
{
public:
GLWidget(QWidget* parent) :
QOpenGLWidget(parent)
{
}
protected:
void initializeGL()
{
glClearColor(1.0f, 1.0f, 0.0f, 1.0f);
}
void paintGL()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glColor3f(1,0,0);
glBegin(GL_TRIANGLES);
glVertex3f(-0.5, -0.5, 0);
glVertex3f( 0.5, -0.5, 0);
glVertex3f( 0.0, 0.5, 0);
glEnd();
}
void resizeGL(int w, int h)
{
glViewport(0, 0, w, h);
}
};
I want to make simple opengl project as in this tutorial.
I add new class GLWidget that inherit from QGLWidget, and promote my QWidget object to GLWidget class that i already made. When i run project i can't refresh QWidget object. Every time i see what's behind that window when I build and run project.
This is how it should look like Correct
And this is what it really looks not correct
.
GLWidget.h
#ifndef GLWIDGET_H
#define GLWIDGET_H
#include <GL/glew.h>
#include <QGLWidget>
#include <QTimer>
class GLWidget : public QGLWidget
{
Q_OBJECT
public:
explicit GLWidget(QWidget *parent = 0);
GLWidget(int width, int height);
void initializeGL();
void paintGL();
void resizeGL(int w, int h);
private:
void timerEvent(QTimerEvent *);
};
#endif // GLWIDGET_H
GlWidget.cpp
#include "glwidget.h"
#include<QMessageBox>
GLWidget::GLWidget(QWidget *parent) :
QGLWidget(parent)
{
}
void GLWidget::initializeGL()
{
// Init Glew
glewExperimental = GL_TRUE;
GLenum error = glewInit();
if(error != GLEW_OK)
{
exit(1);
}
glClearColor( 0.2f, 0.45f, 0.8f, 1.0f ); // blue background
glClearDepth( 1.0f );
}
GLWidget::GLWidget(int width, int height) : QGLWidget()
{
startTimer(30);
resize(width, height);
}
void GLWidget::paintGL()
{
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
}
void GLWidget::resizeGL(int width, int height)
{
glViewport(0, 0, width, height);
}
void GLWidget::timerEvent(QTimerEvent *)
{
updateGL();
}
Mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
mainwindow cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
pro
#-------------------------------------------------
#
# Project created by QtCreator 2014-10-16T20:17:33
#
#-------------------------------------------------
QT += core gui opengl
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TARGET = Manipulatorv2
TEMPLATE = app
SOURCES += main.cpp\
mainwindow.cpp \
glwidget.cpp
HEADERS += mainwindow.h \
glwidget.h
FORMS += mainwindow.ui
INCLUDEPATH += "/home/szczepan/glew-1.11.0/include"
LIBS += -L"/home/szczepan/glew-1.11.0/lib"-lGLEW
When using the GLWidget you should override the paintGL and do a glClearBuffer with the correct bits set in the argument. Otherwise it will just take whatever was in the buffer at the time.
This is an example to create with Qt, a simple class named OpenGLWindow from QGLWidget:
configure .pro
Download the GLEW library according to your OpenGL Version : Glew library
For instance, if I choose glew-1.5.6:
INCLUDEPATH += "path/to/glew-1.5.6/include"
LIBS += -L"path/to/glew-1.5.6/lib" -lGLEW #UNIX
LIBS += -L"path/to/glew-1.5.6/lib" -lglew32 #WINDOWS
With windows, you have to place glew32.dll in the same folder that your .exe.
openglwindow.h
#include <GL/glew.h>
#include <QGLWidget>
#include <QTimerEvent>
class OpenGLWindow : public QGLWidget
{
public:
OpenGLWindow(int width, int height);
~OpenGLWindow();
void initializeGL();
void paintGL();
void resizeGL(int width, int height);
private:
void timerEvent(QTimerEvent *);
};
openglwindow.cpp
OpenGLWindow::OpenGLWindow(int width, int height) : QGLWidget()
{
startTimer(30);
resize(width, height);
}
OpenGLWindow::~OpenGLWindow()
{
}
void OpenGLWindow::timerEvent(QTimerEvent *)
{
updateGL();
}
void OpenGLWindow::initializeGL()
{
// Init Glew
glewExperimental = GL_TRUE;
GLenum error = glewInit();
if(error != GLEW_OK)
{
exit(1);
}
glClearColor( 0.2f, 0.45f, 0.8f, 1.0f ); // blue background
glClearDepth( 1.0f );
}
void OpenGLWindow::paintGL()
{
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
}
void OpenGLWindow::resizeGL(int width, int height)
{
glViewport(0, 0, width, height);
}
Hope this code will be helpful.
I want to control the paintGL method by a keypress-event. The aim is show an additional point by pushing return.
In other words: I have painted a nice background scene and now i want to push return (in a lineEdit) and there appears a red point in front of the already shown background.
//MainWindow.cpp
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow)
{
ui->setupUi(this);
glWidget = new GLWidget;
connect(ui->lineEdit, SIGNAL(returnPressed()), glWidget, SLOT (set_draw()));
}
//glwidget.h
#ifndef GLWIDGET_H
#define GLWIDGET_H
#include <QGLWidget>
#include <QMessageBox>
#include "mainwindow.h"
#include "cstdio"
class MainWindow;
class GLWidget : public QGLWidget
{
Q_OBJECT
MainWindow *myMainWindow;
public:
GLWidget(QWidget *parent = 0);
//~GLWidget;
int draw;
void initializeGL();
void paintGL();
void resizeGL(int w, int h);
public slots:
void set_draw();
};
#endif // GLWIDGET_H
//glwidget.cpp
GLWidget::GLWidget(QWidget *parent) : QGLWidget(parent)
{
draw = 0;
}
//-------------
void GLWidget::set_draw() //this SLOT is activated by pushing return
{
draw = 1;
updateGL(); //updating paintGL...
}
//-------------
void GLWidget::paintGL()
{
swapBuffers();
glClear(GL_COLOR_BUFFER_BIT);
/* drawing a lot of stuff*/
if( draw == 1 )
{
/*the following messagebox is shown at the screen*/
QMessageBox* Box = new QMessageBox();
Box->setText("Bert");
Box->show();
/*this big red point is NOT shown at the screen*/
glPointSize(30);
glBegin(GL_POINTS);
glColor3f(1.0, 0.0, 0.0);
glVertex3f(45,45,0);
glEnd();
}
}
Can someone explain, why this is not working? The red point does not appear... Is the value of int draw influenced by the paintGL method?
In OpenGL you always redraw the whole scene. Store the additional point in some array. When drawing you iterate over that array and draw the points according to the array's content.