QT5 and opengl core profile not show me simple shader - qt

i'm a new member and i have a question.
I want to develope a simple project with QT5 and opengl core profile for an end term project.
I first tried with a simple example but nothing happen. The screen show me only the red background but not the shader that i have write.
the code is the following:
main.cpp
#include <QApplication>
#include <QGLFormat>
#include "glwidget.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
//specify oepngl version and other stuff
QGLFormat glFormat;
glFormat.setVersion(4, 3);
glFormat.setProfile(QGLFormat::CoreProfile);
glFormat.setSampleBuffers(true);
GLWidget w(glFormat);
w.show();
return a.exec();
}
glwidget.h
#ifndef GLWIDGET_H
#define GLWIDGET_H
#include <QGLWidget>
#include <QGLBuffer>
#include <QGLShaderProgram>
#include <QOpenGLVertexArrayObject>
class GLWidget : public QGLWidget
{
Q_OBJECT
public:
GLWidget(const QGLFormat& format, QWidget* parent = 0);
protected:
virtual void initializeGL();
virtual void resizeGL(int w, int h);
virtual void paintGL();
//virtual void keyPressEvent(QKeyEvent* e);
private:
bool prepareShaderProgram(const QString& vertexShaderPath, const QString& fragmentShaderPath);
QGLShaderProgram m_shader;
QGLBuffer m_vertexBuffer;
GLuint vertex_array_object;
};
#endif // GLWIDGET_H
glwidget.cpp
#include "glwidget.h"
GLWidget::GLWidget(const QGLFormat& format, QWidget* parent)
:QGLWidget(format, parent),
m_vertexBuffer(QGLBuffer::VertexBuffer)
{
}
void GLWidget::initializeGL()
{
QGLFormat glFormat = QGLWidget::format();
if(!glFormat.sampleBuffers())
qWarning() << "Can't enable sample buffers";
//set background color
glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
//load the shaders
if(!prepareShaderProgram("/home/sera/workspace/qtWorkspace/provaShader/simple.vert",
"/home/sera/workspace/qtWorkspace/provaShader/simple.frag"))
return;
//create and bind the vertex buffer to the context
m_vertexBuffer.create();
if(!m_vertexBuffer.bind())
{
qWarning() << "could not bind vertex buffer to the opengl context";
return;
}
//bind program to the context
if(!m_shader.bind())
{
qWarning() << "could not bind shader program to the context";
return;
}
}
bool GLWidget::prepareShaderProgram(const QString &vertexShaderPath, const QString &fragmentShaderPath)
{
//load and compile shaders
bool result = m_shader.addShaderFromSourceFile(QGLShader::Vertex, vertexShaderPath);
if(!result)
qWarning() << m_shader.log();
result = m_shader.addShaderFromSourceFile(QGLShader::Fragment, fragmentShaderPath);
if(!result)
qWarning() << m_shader.log();
//link shaders into program
result = m_shader.link();
if(!result)
qWarning() << "could not link shader program" << m_shader.log();
return result;
}
void GLWidget::resizeGL(int w, int h)
{
//set the viewport
glViewport(0, 0, w, qMax(h, 1));
}
void GLWidget::paintGL()
{
//clear buffer with current color
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glPointSize(40.0);
glDrawArrays(GL_POINTS, 0, 1);
}
/*
void GLWidget::keyPressEvent( QKeyEvent* e )
{
switch (e->key())
{
case Qt::Key_Escape:
QCoreApplication::instance()->quit();
break;
default:
QGLWidget::keyPressEvent( e );
}
}
*/
simple.vert
#version 430 core
void main(void)
{
gl_Position = vec4(1.0, 0.0, 0.0, 1.0);
}
simple.frag
#version 430 core
out vec4 color;
void main(void)
{
color = vec4(1.0, 1.0, 1.0, 1.0);
}
And the result is this in the figure, but i'm aspected a point in the middle
result
What is wrong?

Related

how to get drop events of object which is placed in graphic scene?

i have graphic view(QGraphics view) setted scene(QGraphic scene) i am dropping objects on scene its working fine, i have to assign parameter for dropped object by dragging parameter from parameter list .i have implemented drag drop events of object.but when i am dragging parameter from param list non- acceptance symbol on object.how to assign param to object by dropping ? Any other suggestions and examples are welcome where i can get ideas to implementation.
image of gui
speedometer.cpp
#include <QMimeData>
SpeedoMeter::SpeedoMeter( QWidget *parent ):
QwtDial( parent ),
d_label( "km/h" )
{
setAcceptDrops(true);
}
void SpeedoMeter::dragEnterEvent(QDragEnterEvent *event)
{
if (event->mimeData()->hasFormat(paramlistMimeType()))
{
qDebug()<<"dragenter event in speedo" ;
event->accept();
}
}
void SpeedoMeter::dragMoveEvent(QDragMoveEvent *event)
{
if (event->mimeData()->hasFormat(paramlistMimeType()))
{
qDebug()<<"dragmove event in speedo" ;
event->acceptProposedAction();
}
}
void SpeedoMeter::dropEvent(QDropEvent *event)
{
if (event->mimeData()->hasFormat(paramlistMimeType()))
{
qDebug()<<"dragmove event in speedo" ;
event->accept();
}
}
The following example shows how to implement the logic to accept the drag-and-drop:
speedometer.h
#ifndef SPEEDOMETER_H
#define SPEEDOMETER_H
#include <qwt_dial.h>
class SpeedoMeter : public QwtDial
{
public:
SpeedoMeter(QWidget *parent=nullptr);
protected:
void dragEnterEvent(QDragEnterEvent *event);
void dropEvent(QDropEvent *event);
void dragMoveEvent(QDragMoveEvent *event);
void paintEvent(QPaintEvent *event);
private:
QString d_label;
};
#endif // SPEEDOMETER_H
speedometer.cpp
#include "speedometer.h"
#include <qwt_dial_needle.h>
#include <QDragEnterEvent>
#include <QMimeData>
#include <QPainter>
SpeedoMeter::SpeedoMeter(QWidget *parent):
QwtDial(parent),
d_label( "km/h" )
{
setAcceptDrops(true);
QwtDialSimpleNeedle *nd = new QwtDialSimpleNeedle(QwtDialSimpleNeedle::Arrow, Qt::white, Qt::red);
setNeedle(nd);
setValue(80);
}
void SpeedoMeter::dragEnterEvent(QDragEnterEvent *event)
{
if(event->mimeData()->hasFormat("application/x-qabstractitemmodeldatalist"))
event->acceptProposedAction();
}
void SpeedoMeter::dropEvent(QDropEvent *event)
{
const QMimeData *mimedata = event->mimeData();
if(mimedata->hasFormat("application/x-qabstractitemmodeldatalist")){
QString text;
// https://stackoverflow.com/questions/1723989/how-to-decode-application-x-qabstractitemmodeldatalist-in-qt-for-drag-and-drop
QByteArray encoded = mimedata->data("application/x-qabstractitemmodeldatalist");
QDataStream stream(&encoded, QIODevice::ReadOnly);
while (!stream.atEnd()) {
int row, col;
QMap<int, QVariant> roleDataMap;
stream >> row >> col >> roleDataMap;
if(roleDataMap.contains(Qt::DisplayRole)){
text = roleDataMap[Qt::DisplayRole].toString();
break;
}
}
// your text
d_label = text;
update();
}
}
void SpeedoMeter::dragMoveEvent(QDragMoveEvent *event)
{
if(event->mimeData()->hasFormat("application/x-qabstractitemmodeldatalist"))
event->accept();
}
void SpeedoMeter::paintEvent(QPaintEvent *event)
{
// https://stackoverflow.com/questions/43904204/qwt-dial-show-unit
QwtDial::paintEvent(event);
QPainter painter(this);
painter.setPen(Qt::black);
QFont font;
font.setPointSize(11);
painter.setFont(font);
QString text = QString("%1 %2").arg(value()).arg(d_label);
QPoint c = rect().center();
QSize Size = painter.fontMetrics().size(Qt::TextSingleLine, text);
painter.drawText(QPointF(c.x() -Size.width()/2, c.y() + 2.5*Size.height()), text);
}
main.cpp
#include "speedometer.h"
#include <QApplication>
#include <QGraphicsView>
#include <QHBoxLayout>
#include <QListWidget>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QWidget w;
QHBoxLayout *layout = new QHBoxLayout(&w);
QListWidget listWidget;
listWidget.setDragDropMode(QAbstractItemView::DragOnly);
listWidget.addItems({"km/h", "ft/s", "m/s", "miles/h"});
QGraphicsView view;
QGraphicsScene scene;
view.setScene(&scene);
SpeedoMeter speed;
scene.addWidget(&speed);
layout->addWidget(&listWidget);
layout->addWidget(&view);
w.show();
return a.exec();
}
In the following link you can find the complete example.

Offscreen rendering with QOffscreenSurface - QPainter with Alpha pen-color failing

I have tried this method (Answer of NikitaFeodonit) for offscreen rendering and creating a QImage and saving to disk. Everything is working fine, except when using a QColor with Alpha-Channel for QPen.
QPainter.drawEllipse without ALPHA in Pen-Color
QPainter.drawEllipse with ALPHA in Pen-Color
Here is my source:
Using OpenGlOffscreenSurface from this method:
Header ExamplePaintSurface.h:
#ifndef EXAMPLEPAINTSURFACE_H
#define EXAMPLEPAINTSURFACE_H
#include <QPainter>
#include "OpenGlOffscreenSurface.h"
class ExamplePaintSurface
: public OpenGlOffscreenSurface
{
public:
explicit ExamplePaintSurface(
QScreen* targetScreen = nullptr,
const QSize& size = QSize (1, 1));
void renderImage(bool useAlpha);
virtual ~ExamplePaintSurface() override;
protected:
virtual void initializeGL() override;
virtual void resizeGL(
int width,
int height) override;
virtual void paintGL() override;
private:
bool m_useAlpha;
};
#endif // EXAMPLEPAINTSURFACE_H
Source ExamplePaintSurface.cpp:
#include "ExamplePaintSurface.h"
ExamplePaintSurface::ExamplePaintSurface(
QScreen* targetScreen,
const QSize& size)
: OpenGlOffscreenSurface(targetScreen, size) {}
void ExamplePaintSurface::renderImage(bool useAlpha)
{
m_useAlpha = useAlpha;
this->paintGL();
}
ExamplePaintSurface::~ExamplePaintSurface() {}
void ExamplePaintSurface::initializeGL() {}
void ExamplePaintSurface::resizeGL(int width, int height) {}
void ExamplePaintSurface::paintGL()
{
QPainter painter(getPaintDevice());
painter.eraseRect(0,0,200,200);
painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing);
painter.setCompositionMode (QPainter::CompositionMode_Source);
painter.fillRect(0,0,200,200, Qt::transparent);
painter.setCompositionMode (QPainter::CompositionMode_SourceOver);
QPen pen;
if(m_useAlpha == true)
pen.setColor(QColor(255, 0, 0, 150));
else
pen.setColor(QColor(255, 0, 0, 255));
QBrush brush(Qt::yellow);
brush.setStyle(Qt::SolidPattern);
pen.setWidth(8);
painter.setPen(pen);
painter.setBrush(brush);
painter.drawEllipse(50,50,100,100);
//painter.drawText(20, 40, "Test"); // <-- drawing here
painter.end();
}
Source main.cpp:
#include <QApplication>
#include "ExamplePaintSurface.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
ExamplePaintSurface paintSurface;
paintSurface.resize(200, 200);
paintSurface.renderImage(false);
paintSurface.render();
QImage image = paintSurface.grabFramebuffer();
image.save("Ellipse_noAlpha.png");
paintSurface.renderImage(true);
paintSurface.render();
image = paintSurface.grabFramebuffer();
image.save("Ellipse_alpha.png");
return a.exec();
}

Unexpected behaviour with QMouseMoveEvent and QKeyEvent modifiers

I am encountering unexpected behaviour in my code.
I have a QGraphicsView containing a QGraphicsScene. Now I want to detect the mouse wheel for zooming the view and mouse moving for moving items in the scene, the latter only while controll is pressed. Now I have two Problems:
MouseMoveEvent is called even when the mouse is not moved but only the mouse wheel.
Moving with and without controll pressed works fine but when I stop moving while controll is pressed and continue using the mouse wheel not only the mousemoveevent is called but also the controllmodifier is still active. What is the problem?
main.cpp
#include "ppi.h"
#include <QtGui/QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
PPI w;
w.show();
return a.exec();
}
ppi.h
#ifndef PPI_H
#define PPI_H
#include <QtGui/QMainWindow>
#include <QGraphicsView>
#include <QDebug>
#include <QWheelEvent>
#include "ui_ppi.h"
#include "ppiView.h"
#include "ppiscene.h"
class PPI : public QMainWindow
{
Q_OBJECT
public:
PPI(QWidget *parent = 0, Qt::WFlags flags = 0);
~PPI();
int i;
private:
Ui::ppiClass ui;
PPIScene* ppiScene;
protected slots:
void onZoom(QWheelEvent *event);
void onMouseMoved(QGraphicsSceneMouseEvent *event);
};
#endif // PPI_H
ppi.cpp
#include "ppi.h"
PPI::PPI(QWidget *parent, Qt::WFlags flags)
: QMainWindow(parent, flags)
{
ui.setupUi(this);
ppiScene = new PPIScene(this);
connect(ppiScene, SIGNAL(mouseMoved(QGraphicsSceneMouseEvent*)), this, SLOT(onMouseMoved(QGraphicsSceneMouseEvent*)));
connect(ui.gVPPI, SIGNAL(zoom(QWheelEvent*)), this, SLOT(onZoom(QWheelEvent*)));
ppiScene->setSceneRect(0,0,1024,1024);
ui.gVPPI->setScene(ppiScene);
ui.gVPPI->setMouseTracking(true);
i = 0;
}
PPI::~PPI()
{
}
void PPI::onZoom(QWheelEvent *event)
{
if(event->delta() > 0)
ui.gVPPI->scale(1.01, 1.01);
else
ui.gVPPI->scale(1/1.01, 1/1.01);
}
void PPI::onMouseMoved(QGraphicsSceneMouseEvent *event)
{
i++;
qDebug() << "slot" << i << event->modifiers();
if(event->modifiers() & Qt::ControlModifier)
{
qDebug() << "ctrl pressed";
}
}
ppiview.h
#ifndef PPIVIEW_H
#define PPIVIEW_H
#include <QGraphicsView>
#include <QMouseEvent>
class PPIView : public QGraphicsView
{
Q_OBJECT
public:
PPIView(QWidget * parent = 0);
~PPIView();
private:
void wheelEvent(QWheelEvent *event);
signals:
void zoom(QWheelEvent *event);
};
#endif // PPIVIEW_H
ppiview.cpp
#include "ppiview.h"
PPIView::PPIView(QWidget * parent)
: QGraphicsView(parent)
{
}
PPIView::~PPIView()
{
}
void PPIView::wheelEvent(QWheelEvent *event)
{
emit zoom(event);
}
ppiscene.h
#ifndef PPISCENE_H
#define PPISCENE_H
#include <QGraphicsScene>
#include <QGraphicsSceneMouseEvent>
#include <QDebug>
class PPIScene : public QGraphicsScene
{
Q_OBJECT
public:
PPIScene(QObject *parent);
~PPIScene();
int i;
private:
void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
signals:
void mouseMoved(QGraphicsSceneMouseEvent *event);
};
#endif // PPISCENE_H
ppiscene.cpp
#include "ppiscene.h"
PPIScene::PPIScene(QObject *parent)
: QGraphicsScene(parent)
{
i = 0;
}
PPIScene::~PPIScene()
{
}
void PPIScene::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
i++;
qDebug() << "signal" << i << event->modifiers();
emit mouseMoved(event);
}
It is really strange. It looks like the Qt::KeyboardModifiers status, which QGraphicsSceneMouseEvent::modifiers returns, is only updated, when the mouse is physically moved. What is even more strange, is that in your code QGraphicsSceneMouseEvents of type QGraphicsSceneMouseMove are sent even when the mouse is not moved at all, but only the wheel is turned. Maybe the relative movement due to your scaling counts as movement, but not as movement, which updates the modifiers.
I was able to reproduce your problem: The status of the modifiers don't change unless the mouse is physically moved.
Fortunately there is an easy workaround. In
void PPI::onMouseMoved(QGraphicsSceneMouseEvent *event)
{
i++;
qDebug() << "slot" << i << event->modifiers();
if(event->modifiers() & Qt::ControlModifier)
{
qDebug() << "ctrl pressed";
}
}
replace:
if(event->modifiers() & Qt::ControlModifier)
with:
if(QApplication::queryKeyboardModifiers() & Qt::ControlModifier)
QApplication::queryKeyboardModifiers() is updated immediately when you press or release the control key.

glewInit with Qt5 returns Missing GL version

I have been trying to use Qt5 to give me an OpenGL context, which I believe it does, but when I try to call glewInit() from within the initializeGL function, the error returns back "Missing GL version," which I have been led to believe indicates that there is no valid context. The solution I saw was to call glewInit() from within initializeGL... but I'm already doing that.
I am setting the clear color and clearing to dark red to verify that gl calls are working, which they appear to be.
Any suggestions?
main.c
#define QT_NO_OPENGL_ES_2
#include <QApplication>
#include "glwidget.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
GLWidget w;
w.show();
return a.exec();
}
glwidget.h
#ifndef GLWIDGET_H
#define GLWIDGET_H
#include <GL/glew.h>
#define QT_NO_OPENGL_ES_2
#include <QGLWidget>
class GLWidget : public QGLWidget
{
Q_OBJECT
public:
explicit GLWidget(QGLWidget *parent = 0);
~GLWidget();
QSize minimumSizeHint() const;
QSize sizeHint() const;
protected:
void initializeGL();
void paintGL();
void resizeGL(int width, int height);
};
#endif // GLWIDGET_H
glwidget.cpp
#include "glwidget.h"
GLWidget::GLWidget(QGLWidget *parent) :
QGLWidget(parent)
{
}
GLWidget::~GLWidget() {}
QSize GLWidget::minimumSizeHint() const {
return QSize(640, 480);
}
QSize GLWidget::sizeHint() const {
return QSize(800, 600);
}
void GLWidget::initializeGL() {
GLenum err = glewInit();
if (GLEW_OK != err) {
printf("GLEW error: %s\n", glewGetErrorString(err));
} else {
printf("Glew loaded; using version %s\n", glewGetString(GLEW_VERSION));
}
glClearColor(0.2f, 0, 0, 1.0f);
}
void GLWidget::resizeGL(int w, int h) {
}
void GLWidget::paintGL() {
glClear( GL_COLOR_BUFFER_BIT );
}
Something tells me this is because of the QGLWidget's default QGLFormat using OpenGL version 1.0 (Looking through GLEW's change logs, it seems the earliest version they claim to fully support is 1.5) . Try instead to override the QGLWidget constructor that requires a QGLFormat and pass it an instance of QGLFormat that uses the version you are targeting.
The call to your widget should look something like:
QGLFormat format;
format.setVersion(3,3); // or whatever version you are targeting.
format.setDoubleBuffer(true);
GLWidget * widget = new GLWidget(format);

Horde3D Particle System not rendering in Qt OpenGL

Horde3d come with 2 samples, compiled with GLFW. One of them, Knight, shows a particle emitter. I've ported the samples to Qt, with a thin layer I wrote that leave unchanged the applicative code (i.e. scene setup, rendering and events handling).
Indeed, the functionality is ok, except the particle emitter doesn't show. I can't see anything specific in GLFW initialization, and I tried some setting I found in Qt, without success. Horde3d takes care of OpenGL interface, and expose a higher level, clean C interface. Any clue?
EDIT : Most Rilevant Sources of qtKnight.pro
here (cleaned :) main.cpp
#include "glwidget.h"
#include <QApplication>
int main(int argc, char* argv[]) {
QApplication app(argc, argv);
GLWidget glw;
glw.show();
return app.exec();
}
here glWidget.h
#ifndef GL_WIDGET_H
#define GL_WIDGET_H
#include <QtOpenGL>
#include <QTimer>
#include <QKeyEvent>
#include <Horde3D.h>
#include <Horde3DUtils.h>
#include <sstream>
#include <app.h>
class GLWidget : public QGLWidget, Application {
Q_OBJECT
public:
GLWidget();
~GLWidget();
QSize minimumSizeHint() const { return sizeHint(); }
QSize sizeHint() const { return QSize(640, 480); }
protected:
void initializeGL();
void paintGL();
void resizeGL(int width, int height);
void mousePressEvent(QMouseEvent *event);
void mouseMoveEvent(QMouseEvent *event);
void mouseReleaseEvent(QMouseEvent *event);
void keyPressEvent(QKeyEvent *e) { keyEvent(e, true); QGLWidget::keyPressEvent(e); }
void keyReleaseEvent(QKeyEvent *e) { keyEvent(e, false); QGLWidget::keyReleaseEvent(e); }
void keyEvent(QKeyEvent *, bool);
public slots:
void appLoop() { updateGL(); }
private:
QPoint lastPos;
QTimer evloop;
};
#endif
and here glWidget.cpp
#include "glwidget.h"
#include <stdexcept>
#include <QtDebug>
#include <QTextStream>
#include <QGLFormat>
GLWidget::GLWidget() :
QGLWidget(QGLFormat(QGL::AlphaChannel | QGL::SampleBuffers)),
Application("/home/carlo/horde3d/SDK_1.0.0_Beta5/Horde3D/Binaries/Content")
{
connect(&evloop, SIGNAL(timeout()), this, SLOT(appLoop()));
evloop.start(0);
}
GLWidget::~GLWidget()
{
h3dutDumpMessages();
h3dRelease();
}
void GLWidget::initializeGL()
{
if (!init())
throw std::runtime_error("Could not initialize renderer");
}
void GLWidget::paintGL()
{
keyStateHandler();
mainLoop(30);
}
void GLWidget::resizeGL(int width, int height)
{
Application::resize(width, height);
}
void GLWidget::mousePressEvent(QMouseEvent *event)
{
lastPos = event->pos();
}
void GLWidget::mouseMoveEvent(QMouseEvent *event)
{
QPoint cPos = event->pos();
float dX = cPos.x() - lastPos.x(); //event->x() - lastPos.x();
float dY = cPos.y() - lastPos.y(); //event->y() - lastPos.y();
Application::mouseMoveEvent(dX, dY);
lastPos = cPos;
}
void GLWidget::mouseReleaseEvent(QMouseEvent * /* event */)
{
}
void GLWidget::keyEvent(QKeyEvent *k, bool on_off)
{
#define setK(X,Y) case Qt::X: setKeyState(Y, on_off); break;
#define setF(X) case Qt::Key_##X: setKeyState(X, on_off); break;
#define R(X, Y) (v >= #X[0] && v <= #Y[0])
int v = k->key();
switch (v) {
case Qt::Key_F1: if (on_off) showFullScreen(); break;
case Qt::Key_F2: if (on_off) showNormal(); break;
setF(F3)
setF(F6)
setF(F7)
setF(F8)
setK(Key_Space, SP)
default:
if (R(A, Z) || R(0, 9))
setKeyState(v, on_off);
}
}
Since you say it is only the particles that aren't shown, it could have to do with alpha blending. I also saw from your code that you don't specify a format when constructing the QGLWidget, in which case the default format is used which explicitly disables the alpha channel.
Though I don't know if this has any effect (shouldn't there always be an A in RGBA?), but maybe this really requests a pixel format where there is no storage for the A channel, in which case things like alpha blending (used for the transparent particles) won't work.
So just try to request it explicitly by using an appropriate format in the QGLWidget constructor:
GLWidget::GLWidget()
: QGLWidget(QGLFormat(QGL::AlphaChannel))
You actually were on the right track with your outcommented QGLFormat argument, but it hasn't anything to do with the HasOverlay option, which you don't really need, as Horde3d does it's own overlay rendering.

Resources