PDA

View Full Version : Strange error with QGLFunctions



Zamaster
6th March 2014, 21:54
So I'm trying to make a QGLWidget function with Qt Creator and I'm running into a strange issue trying to use regular OpenGL functions. My program ASSERTS and crashes with: "QGLFunctions::isInitialized(d_ptr)" in "c:\work\build\qt5_workdir\w\s\qtbase\include\qtope ngl\../../src/opengl/qglfunctions.h, line 722"

I found this is called from the "glGenBuffers" call in my cpp code. Ill post the .h and .cpp here:

myglwidget.h

#ifndef MYGLWIDGET_H
#define MYGLWIDGET_H

#include <QGLWidget>
#include <QGLFunctions>
#include <QGLShaderProgram>


class MyGLWidget : public QGLWidget, protected QGLFunctions
{
Q_OBJECT
public:
explicit MyGLWidget(QWidget *parent = 0);
~MyGLWidget();

protected:
void initializeGL();
void paintGL();
void resizeGL(int width, int height);

private:
int width;
int height;
GLuint back_texture;
GLuint* vboid;
QGLShaderProgram default_prog;
};

#endif // MYGLWIDGET_H


myglwidget.cpp


#include "myglwidget.h"
#include <QDebug>
#include <QVector3D>
#include <QVector2D>
#include "locale.h"

#define BACK_TILE_S 48

struct VertexData
{
QVector3D position;
QVector2D texCoord;
};

MyGLWidget::MyGLWidget(QWidget *parent) :
QGLWidget(parent)
{
glGenBuffers(2, vboid);
}

MyGLWidget::~MyGLWidget(){
glDeleteBuffers(2, vboid);
}

void MyGLWidget::initializeGL(){
VertexData verts[] = {
{QVector3D(0, 0, 0), QVector2D(0, 0)},
{QVector3D(1, 0, 0), QVector2D(1, 0)},
{QVector3D(0, 1, 0), QVector2D(0, 1)},
{QVector3D(1, 1, 0), QVector2D(1, 1)}
};
GLushort indices[] = {
0, 1, 2, 3
};

setlocale(LC_NUMERIC, "C");

default_prog.addShaderFromSourceFile(QGLShader::Ve rtex, ":/shaders/default.vert");
default_prog.addShaderFromSourceFile(QGLShader::Fr agment, ":/shaders/default.frag");
default_prog.link();

default_prog.bind(); // this is in initgl since this is the
// only shader we use... FOR NOW, therefore
// we dont have to do it elsewhere
setlocale(LC_ALL, "");

glEnable(GL_TEXTURE_2D);
// normally here we would have the QImage buffered up already
// and would bind as needed, but again, this is the only
// texture we use for now
back_texture = bindTexture(QImage(":/gfx/gfx/back.png"));
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);

glBindBuffer(GL_ARRAY_BUFFER, vboid[0]);
glBufferData(GL_ARRAY_BUFFER, 4 * sizeof(VertexData), verts, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboid[1]);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, 4 * sizeof(GLushort), indices, GL_STATIC_DRAW);
}

void MyGLWidget::paintGL(){
int texw;
int texh;
QMatrix4x4 proj;
QMatrix2x2 scale;
quintptr offset;
int vertexLoc;
int texcoordLoc;

texw = (floor(width / ((double) BACK_TILE_S)) + 1);
texh = (floor(height / ((double) BACK_TILE_S)) + 1);

proj.setToIdentity();
proj.scale(texw * BACK_TILE_S, texh * BACK_TILE_S);
proj.ortho(0, width, 0, height, -1, 1);

scale.setToIdentity();
scale(0,0) = texw;
scale(1,1) = texh;

default_prog.setUniformValue("texScale", scale);
default_prog.setUniformValue("mvp_matrix", proj);
default_prog.setUniformValue("texture", 0);

glBindBuffer(GL_ARRAY_BUFFER, vboid[0]);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboid[1]);

offset = 0;

vertexLoc = default_prog.attributeLocation("a_position");
default_prog.enableAttributeArray(vertexLoc);
glVertexAttribPointer(vertexLoc, 3, GL_FLOAT, GL_FALSE, sizeof(VertexData), (const void*) offset);

offset += sizeof(QVector3D);

texcoordLoc = default_prog.attributeLocation("a_texcoord");
default_prog.enableAttributeArray(texcoordLoc);
glVertexAttribPointer(texcoordLoc, 2, GL_FLOAT, GL_FALSE, sizeof(VertexData), (const void*) offset);

glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, 0);
}


void MyGLWidget::resizeGL(int width, int height){
this->width = width;
this->height = height;
}

Zamaster
7th March 2014, 01:05
So I tried initQGLFunctions and it didn't do squat (now for something completely different!) so I switched to try using GLEW… now even MORE problems. It just crashes at glewInit. No reason just ends unexpectedly.


#include <GL/glew64.h>
#include "myglwidget.h"
#include <QDebug>
#include <QVector3D>
#include <QVector2D>
#include "locale.h"


#define BACK_TILE_S 48

struct VertexData
{
QVector3D position;
QVector2D texCoord;
};

MyGLWidget::MyGLWidget(QWidget *parent) :
QGLWidget(parent)
{

}

MyGLWidget::~MyGLWidget(){
//glDeleteBuffers(2, vboid);
}

void MyGLWidget::initializeGL(){
VertexData verts[] = {
{QVector3D(0, 0, 0), QVector2D(0, 0)},
{QVector3D(1, 0, 0), QVector2D(1, 0)},
{QVector3D(0, 1, 0), QVector2D(0, 1)},
{QVector3D(1, 1, 0), QVector2D(1, 1)}
};
GLushort indices[] = {
0, 1, 2, 3
};

makeCurrent();
glewExperimental = GL_TRUE;

int glewErr = glewInit();
// if( glewErr != GLEW_OK )
// {
// qDebug("Error %s", glewGetErrorString(glewErr) ) ;
// }
/*

setlocale(LC_NUMERIC, "C");

default_prog.addShaderFromSourceFile(QGLShader::Ve rtex, ":/shaders/default.vert");
default_prog.addShaderFromSourceFile(QGLShader::Fr agment, ":/shaders/default.frag");
default_prog.link();

default_prog.bind(); // this is in initgl since this is the
// only shader we use... FOR NOW, therefore
// we dont have to do it elsewhere
setlocale(LC_ALL, "");

glEnable(GL_TEXTURE_2D);
// normally here we would have the QImage buffered up already
// and would bind as needed, but again, this is the only
// texture we use for now
back_texture = bindTexture(QImage(":/gfx/gfx/back.png"));
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);

glGenBuffers(2, vboid);

glBindBuffer(GL_ARRAY_BUFFER, vboid[0]);
glBufferData(GL_ARRAY_BUFFER, 4 * sizeof(VertexData), verts, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboid[1]);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, 4 * sizeof(GLushort), indices, GL_STATIC_DRAW);
*/
}

void MyGLWidget::paintGL(){
int texw;
int texh;
QMatrix4x4 proj;
QMatrix2x2 scale;
quintptr offset;
int vertexLoc;
int texcoordLoc;

makeCurrent();


texw = (floor(width / ((double) BACK_TILE_S)) + 1);
texh = (floor(height / ((double) BACK_TILE_S)) + 1);
/*
proj.setToIdentity();
proj.scale(texw * BACK_TILE_S, texh * BACK_TILE_S);
proj.ortho(0, width, 0, height, -1, 1);

scale.setToIdentity();
scale(0,0) = texw;
scale(1,1) = texh;

default_prog.setUniformValue("texScale", scale);
default_prog.setUniformValue("mvp_matrix", proj);
default_prog.setUniformValue("texture", 0);

glBindBuffer(GL_ARRAY_BUFFER, vboid[0]);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboid[1]);

offset = 0;

vertexLoc = default_prog.attributeLocation("a_position");
default_prog.enableAttributeArray(vertexLoc);
glVertexAttribPointer(vertexLoc, 3, GL_FLOAT, GL_FALSE, sizeof(VertexData), (const void*) offset);

offset += sizeof(QVector3D);

texcoordLoc = default_prog.attributeLocation("a_texcoord");
default_prog.enableAttributeArray(texcoordLoc);
glVertexAttribPointer(texcoordLoc, 2, GL_FLOAT, GL_FALSE, sizeof(VertexData), (const void*) offset);

glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, 0);
*/
}


void MyGLWidget::resizeGL(int width, int height){
this->width = width;
this->height = height;
}

ChrisW67
7th March 2014, 01:58
In your call to glGenBuffers you are passing an unitialised pointer to a function expecting to have a valid pointer. You need to allocate space for 2 GLuint objects and pass a pointer to that.

Zamaster
7th March 2014, 07:26
Ah thanks, this alleviates a bug I haven't even gotten to yet (thought genBuffers returned the array). However in my initGL function glewInit is causing a crash with or without genBuffers.

Zamaster
7th March 2014, 15:09
So I fixed this issue by extending out to QOpenGLFunctions instead of QGLFunctions and calling makeCurrent() and initializeOpenGLFunctions in initializeGL(). Now I've run into the issue that my OpenGL code seems to flop, as in it won't draw anything but a black screen. Any takers?

Updated myglwidget.cpp

#include "myglwidget.h"
#include <QDebug>
#include <QVector3D>
#include <QVector2D>
#include "locale.h"


#define BACK_TILE_S 48

struct VertexData
{
QVector3D position;
QVector2D texCoord;
};

MyGLWidget::MyGLWidget(QWidget *parent) :
QGLWidget(parent)
{

}

MyGLWidget::~MyGLWidget(){
glDeleteBuffers(2, vboid);
}

void MyGLWidget::initializeGL(){
VertexData verts[] = {
{QVector3D(0, 0, 0), QVector2D(0, 0)},
{QVector3D(1, 0, 0), QVector2D(1, 0)},
{QVector3D(0, 1, 0), QVector2D(0, 1)},
{QVector3D(1, 1, 0), QVector2D(1, 1)}
};
GLushort indices[] = {
0, 1, 2, 3
};
makeCurrent();
initializeOpenGLFunctions();

setlocale(LC_NUMERIC, "C");

default_prog.addShaderFromSourceFile(QGLShader::Ve rtex, ":/shaders/default.vert");
default_prog.addShaderFromSourceFile(QGLShader::Fr agment, ":/shaders/default.frag");
default_prog.link();

default_prog.bind(); // this is in initgl since this is the
// only shader we use... FOR NOW, therefore
// we dont have to do it elsewhere
setlocale(LC_ALL, "");

glDisable(GL_DEPTH_TEST);
glEnable(GL_TEXTURE_2D);
// normally here we would have the QImage buffered up already
// and would bind as needed, but again, this is the only
// texture we use for now
back_texture = bindTexture(QImage(":/gfx/gfx/back.png"));
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);


glGenBuffers(2, vboid);

glBindBuffer(GL_ARRAY_BUFFER, vboid[0]);
glBufferData(GL_ARRAY_BUFFER, 4 * sizeof(VertexData), verts, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboid[1]);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, 4 * sizeof(GLushort), indices, GL_STATIC_DRAW);

}

void MyGLWidget::paintGL(){
int texw;
int texh;
QMatrix4x4 proj;
QMatrix2x2 scale;
quintptr offset;
int vertexLoc;
int texcoordLoc;

texw = (floor(width / ((double) BACK_TILE_S)) + 1);
texh = (floor(height / ((double) BACK_TILE_S)) + 1);

proj.setToIdentity();
proj.scale(texw * BACK_TILE_S, texh * BACK_TILE_S);
proj.ortho(0, width, 0, height, -1, 1);

scale.setToIdentity();
scale(0,0) = texw;
scale(1,1) = texh;

default_prog.setUniformValue("texScale", scale);
default_prog.setUniformValue("mvp_matrix", proj);
default_prog.setUniformValue("texture", 0);

glBindBuffer(GL_ARRAY_BUFFER, vboid[0]);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboid[1]);

offset = 0;

vertexLoc = default_prog.attributeLocation("a_position");
default_prog.enableAttributeArray(vertexLoc);
glVertexAttribPointer(vertexLoc, 3, GL_FLOAT, GL_FALSE, sizeof(VertexData), (const void*) offset);

offset += sizeof(QVector3D);

texcoordLoc = default_prog.attributeLocation("a_texcoord");
default_prog.enableAttributeArray(texcoordLoc);
glVertexAttribPointer(texcoordLoc, 2, GL_FLOAT, GL_FALSE, sizeof(VertexData), (const void*) offset);

glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, 0);

}


void MyGLWidget::resizeGL(int width, int height){
this->width = width;
this->height = height;
}

default.vert

#version 150

uniform mat4x4 mvp_matrix;
uniform mat2x2 texScale;

in vec4 a_position;
in vec2 a_texcoord;

out vec2 v_texcoord;

void main() {
v_texcoord = a_texcoord * texScale;
gl_Position = mvp_matrix * a_position;
}


default.frag

#version 150

uniform sampler2D texture;

in vec2 v_texcoord;

void main()
{
gl_FragColor = texture2D(texture, v_texcoord);
}