Issue with QGLFunctions (Updated, now OpenGL issue)
-
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\qtopengl../../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::Vertex, ":/shaders/default.vert"); default_prog.addShaderFromSourceFile(QGLShader::Fragment, ":/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;
}
@ -
Hi,
I think you are missing the call to initializeGLFunctions in your initializeGL function
-
I tried it, got more issues, (now for something completely different!) and 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::Vertex, ":/shaders/default.vert"); default_prog.addShaderFromSourceFile(QGLShader::Fragment, ":/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;
}
@ -
IIRC, mixing with glew is a bad idea. Just thought about something, are you using Qt 5 ? If so you should move to the new QOpenGLXXX classes
-
Sooo close! But 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.
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::Vertex, ":/shaders/default.vert"); default_prog.addShaderFromSourceFile(QGLShader::Fragment, ":/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 150uniform 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 150uniform sampler2D texture;
in vec2 v_texcoord;
void main()
{
gl_FragColor = texture2D(texture, v_texcoord);
}
@ -
If you are using QOpenGLFunctions you should also use QOpenGLWidget to stay within the same api
-
Sorry, I've mixed it with something else, I meant QWindow
You can find an example "here":https://qt-project.org/doc/qt-5.0/qtgui/openglwindow.html