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:
Related
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'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
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 am using OpenGL in a QT project.
I am trying the most basic example now. http://programanddesign.com/cpp/qt-opengl-code-example/
GLWidget.hpp
#ifndef _GLWIDGET_H
#define _GLWIDGET_H
#include <QtOpenGL/QGLWidget>
class GLWidget : public QGLWidget {
Q_OBJECT // must include this if you use Qt signals/slots
public:
GLWidget(QWidget *parent = NULL);
protected:
void initializeGL();
void resizeGL(int w, int h);
void paintGL();
void mousePressEvent(QMouseEvent *event);
void mouseMoveEvent(QMouseEvent *event);
void keyPressEvent(QKeyEvent *event);
};
#endif /* _GLWIDGET_H */
GLWidget.cpp
#include <QtGui/QMouseEvent>
#include "GLWidget.h"
GLWidget::GLWidget(QWidget *parent) : QGLWidget(parent) {
setMouseTracking(true);
}
void GLWidget::initializeGL() {
glDisable(GL_TEXTURE_2D);
glDisable(GL_DEPTH_TEST);
glDisable(GL_COLOR_MATERIAL);
glEnable(GL_BLEND);
glEnable(GL_POLYGON_SMOOTH);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glClearColor(0, 0, 0, 0);
}
void GLWidget::resizeGL(int w, int h) {
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0, w, 0, h); // set origin to bottom left corner
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
void GLWidget::paintGL() {
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(1,0,0);
glBegin(GL_POLYGON);
glVertex2f(0,0);
glVertex2f(100,500);
glVertex2f(500,100);
glEnd();
}
void GLWidget::mousePressEvent(QMouseEvent *event) {
}
void GLWidget::mouseMoveEvent(QMouseEvent *event) {
printf("%d, %d\n", event->x(), event->y());
}
void GLWidget::keyPressEvent(QKeyEvent* event) {
switch(event->key()) {
case Qt::Key_Escape:
close();
break;
default:
event->ignore();
break;
}
}
However, GL_COLOR_MATERIAL, GL_POLYGON_SMOOTH, glColor3f,glBegin, GL_POLYGON,glVertex2f, glEnd can not be recognized. Can someone kindly show me how to solve the problem?
You need to add the Qt OpenGL header as follows:
#include <QtOpenGL>
Depending on which OpenGL functions you are using you may also need to have your GLWidget class inherit from QGLFunctions: http://qt-project.org/doc/qt-4.8/qglfunctions.html.
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.