PDA

View Full Version : Cube OpenGL ES 2.0 example with QGraphicsScene



jannn
8th October 2015, 14:29
Hi,
I saw https://doc.qt.io/archives/qq/qq26-openglcanvas.html and tried to alter the code of the example "Cube OpenGL ES 2.0" so it uses a QGraphicsView. I only get black screen. I'm on Ubuntu 14.04 / Qt5.3.2.

main.cpp:


#include <QApplication>
#include <QGLWidget>

#include "scene.h"
#include "view.h"

int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QGLWidget *widget = new QGLWidget(QGLFormat(QGL::SampleBuffers));
widget->setAutoFillBackground(false);
widget->makeCurrent();
Scene *scene= new Scene();
View *mainView = new View();
mainView->setViewport(widget);
mainView->setViewportUpdateMode(QGraphicsView::FullViewportU pdate);
mainView->setScene(scene);
mainView->show();
mainView->resize(800,800);
return a.exec();
}


scene.cpp:
#include "scene.h"

#include <QGraphicsScene>
#include <QGraphicsSceneMouseEvent>
#include <QTimer>

Scene::Scene() : angularSpeed(0)
{
initializeGLFunctions();
glClearColor(0.0f,0.0f,0.0f,1.0f);
initShaders();
initTextures();
glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);
geometries.init();
timer.start(12, this);
}
void Scene::drawBackground(QPainter *painter, const QRectF &rect)
{
painter->beginNativePainting();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
QMatrix4x4 matrix;
matrix.translate(0.0, 0.0, -5.0);
matrix.rotate(rotation);
program.setUniformValue("mvp_matrix", projection * matrix);
program.setUniformValue("texture", 0);
geometries.drawCubeGeometry(&program);
}
void Scene::initShaders()
{
program.addShaderFromSourceFile(QGLShader::Vertex, ":/vshader.glsl");
program.addShaderFromSourceFile(QGLShader::Fragmen t, ":/fshader.glsl");
program.link();
program.bind();
}
void Scene::initTextures()
{
glEnable(GL_TEXTURE_2D);
textureData = new QOpenGLTexture(QImage(":/cube.png"));
textureData->bind();
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
}
void Scene::timerEvent(QTimerEvent *)
{
angularSpeed *= 0.99;
if (angularSpeed < 0.01) {
angularSpeed = 0.0;
} else {
rotation = QQuaternion::fromAxisAndAngle(rotationAxis, angularSpeed) * rotation;
update();
}
}
void Scene::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
mousePressPosition = QVector2D(event->scenePos());
}
void Scene::mouseReleaseEvent(QGraphicsSceneMouseEvent *e)
{
QVector2D diff = QVector2D(e->scenePos()) - mousePressPosition;
QVector3D n = QVector3D(diff.y(), diff.x(), 0.0).normalized();
qreal acc = diff.length() / 100.0;
rotationAxis = (rotationAxis * angularSpeed + n * acc).normalized();
angularSpeed += acc;
}

view.h

#include <QGraphicsView>
#include <QResizeEvent>
#include "geometryengine.h"


class View : public QGraphicsView
{
Q_OBJECT
protected:
void resizeEvent(QResizeEvent *event){
if (scene())
scene()->setSceneRect(
QRect(QPoint(0, 0), event->size()));
QGraphicsView::resizeEvent(event);
}
public:
View(){}
};

#endif // VIEW_H
Any ideas where it went wrong?

jannn
9th October 2015, 08:07
- Projection matrices were missing.
- Shader bindings must come after beginNativePainting()
- Buffers must be unbounded in geometryengine.cpp ( glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);)

Now program works as intended on ubuntu. When I try it on imx6 Sabre board (3.10.17 with eglfs) I got flicker (like two of the same image try to draw on another (one in smaller resolution, other in fullscreen)). Besides that, dice texture isn't shown (Black cube).

shader.cpp

#include "scene.h"

#include <QGraphicsScene>
#include <QGraphicsSceneMouseEvent>
#include <QTimer>
#include <QVBoxLayout>
#include <QLabel>
#include <QGraphicsItem>
#include <QRectF>

Scene::Scene() : angularSpeed(0)
{
QWidget *instructions = createDialog(tr("Instructions"));
instructions->layout()->addWidget(new QLabel(tr("Use mouse wheel to zoom model, and click and drag to rotate model")));
instructions->layout()->addWidget(new QLabel(tr("Move the sun around to change the light position")));
addWidget(instructions);

QPointF pos(10, 10);
foreach (QGraphicsItem *item, items()) {
item->setFlag(QGraphicsItem::ItemIsMovable);
item->setCacheMode(QGraphicsItem::DeviceCoordinateCache) ;

const QRectF rect = item->boundingRect();
item->setPos(pos.x() - rect.x(), pos.y() - rect.y());
pos += QPointF(0, 10 + rect.height());
}

uint32_t w = 800;
uint32_t h = 800;
//glViewport(0, 0, w, h);
qreal aspect = qreal(w) / qreal(h ? h : 1);
const qreal zNear = 1.0, zFar = 7.0, fov = 45.0;
projection.setToIdentity();
projection.perspective(fov, aspect, zNear, zFar);
initShaders();
//initTextures();
textureData = new QOpenGLTexture(QImage(":/cube.png"));
geometries.init();
timer.start(12, this);
}
void Scene::drawBackground(QPainter *painter, const QRectF &rect)
{
painter->beginNativePainting();
glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);
glClearColor(0.8f,0.8f,0.1f,1.0f);
program.bind();
textureData->bind();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
QMatrix4x4 matrix;
matrix.translate(0.0, 0.0, -5.0);
matrix.rotate(rotation);
program.setUniformValue("mvp_matrix", projection * matrix);
program.setUniformValue("texture", 0);
geometries.drawCubeGeometry(&program);
program.release();
textureData->release();
glDisable(GL_DEPTH_TEST);
glDisable(GL_CULL_FACE);
painter->endNativePainting();
QTimer::singleShot(20, this, SLOT(update()));
}
void Scene::initShaders()
{
program.addShaderFromSourceFile(QGLShader::Vertex, ":/vshader.glsl");
program.addShaderFromSourceFile(QGLShader::Fragmen t, ":/fshader.glsl");
program.link();
// program.bind();
}
void Scene::initTextures()
{
glEnable(GL_TEXTURE_2D);

// textureData->bind();
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
}
void Scene::timerEvent(QTimerEvent *)
{
angularSpeed *= 0.99;
if (angularSpeed < 0.01) {
angularSpeed = 0.0;
} else {
rotation = QQuaternion::fromAxisAndAngle(rotationAxis, angularSpeed) * rotation;
update();
}
}
void Scene::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
mousePressPosition = QVector2D(event->scenePos());
}
void Scene::mouseReleaseEvent(QGraphicsSceneMouseEvent *e)
{
QVector2D diff = QVector2D(e->scenePos()) - mousePressPosition;
QVector3D n = QVector3D(diff.y(), diff.x(), 0.0).normalized();
qreal acc = diff.length() / 100.0;
rotationAxis = (rotationAxis * angularSpeed + n * acc).normalized();
angularSpeed += acc;
}

QDialog *Scene::createDialog(const QString &windowTitle) const
{
QDialog *dialog = new QDialog(0, Qt::CustomizeWindowHint | Qt::WindowTitleHint);

dialog->setWindowOpacity(0.8);
dialog->setWindowTitle(windowTitle);
dialog->setLayout(new QVBoxLayout);

return dialog;
}