OpenGL and QT, crash at glDrawElements
-
Hi guys,
I am new here and new to OpenGL ;)So I was trying to make something to appear on my screen, but unfortunately it always crashes at glDrawElements.
I am glad if somebody could help. Here is the code://Initialization void Mesh::initialize() { this->initializeOpenGLFunctions(); vao = new QOpenGLVertexArrayObject(); vbo = new QOpenGLBuffer(QOpenGLBuffer::VertexBuffer); ebo = new QOpenGLBuffer(QOpenGLBuffer::IndexBuffer); vao->create(); vbo->create(); ebo->create(); vao->bind(); vbo->bind(); vbo->setUsagePattern(QOpenGLBuffer::StaticDraw); vbo->allocate(vertices.data(),vertices.size() * sizeof(Vertex)); ebo->bind(); ebo->setUsagePattern(QOpenGLBuffer::StaticDraw); ebo->allocate(indices.data(),indices.size()*sizeof(GLuint)); //Vertex position program->enableAttributeArray(0); program->setAttributeBuffer(0,GL_FLOAT,0,sizeof(Vertex)); program->enableAttributeArray(1); program->setAttributeBuffer(1,GL_FLOAT,offsetof(Vertex,Normal),3,sizeof(Vertex)); glEnableVertexAttribArray(2); program->setAttributeBuffer(2,GL_FLOAT,offsetof(Vertex,TextCoords),2,sizeof(Vertex)); vao->release(); }
It always crashes here:
void Mesh::DrawMesh() { vao->bind(); qDebug() << vertices.size(); glDrawElements(GL_TRIANGLES, indices.size(),GL_UNSIGNED_INT,0); vao->release(); }
Note: When I call vao->isCreated() it returns false even tough I made sure (100%) that initialize() is called BEFORE DrawMesh.
Here is my Vertex struct:
struct Vertex { QVector3D Position; QVector3D Normal; QVector2D TextCoords; };
This is my vertex shader:
#version 330 core layout(location=0) in vec3 position; layout(location=1) in vec3 normal; layout(location=2) in vec2 textCoords; uniform mat4 MVP; out vec4 color; void main(void) { gl_Position= MVP*vec4(position,1); color = vec4(1,1,1,1); }
Can somebody help me? I'm really stuck here. Also I don't know if I can pass an array of QVector3D like that to the graphicscard...
Thank you really for your help. ;)
-
Hi, welcome to the Qt forum! Seems like you forgot to create an OpenGL context and make it current, see: http://doc.qt.io/qt-5/qopenglfunctions.html#details
Edit: There is also a minimal example: http://doc.qt.io/qt-5/qtgui-openglwindow-example.html
-
@Wieland Thanks for the reply Wieland.
Inside paintGL I loop through a list of meshes and call the DrawMesh() method on all of them. I use a QOpenGLWidget for that.
So is manually creating a context still the recommended way to go?
Thanks you ;) -
@DaOnlyOwner said:
void Mesh::initialize()
That should be
void Mesh::initializeGL()
, in other words overridevoid QOpenGLWidget::initializeGL()
. Otherwise the function won't automatically use the correct OpenGL context. May I please see yourMesh
header file? -
@Wieland Of course,
class Mesh : public QOpenGLFunctions_3_3_Core { public: Mesh(const Mesh& mesh) { this->vertices = mesh.vertices; this->indices = mesh.indices; this->program = mesh.program; initialize(); } Mesh(){} ~Mesh() { vao->destroy(); vbo->destroy(); ebo->destroy(); } QVector<Vertex> vertices; QVector<GLuint> indices; QOpenGLShaderProgram* program; Mesh(const QVector<Vertex> &vertices, const QVector<GLuint> &indices, QOpenGLShaderProgram* program); void DrawMesh(); private: QOpenGLVertexArrayObject* vao; QOpenGLBuffer* vbo; QOpenGLBuffer* ebo; void initialize(); };
The code of my QOpenGLWidget:
void RenderingWindow::initializeGL() { this->initializeOpenGLFunctions(); program->create(); program->addShaderFromSourceFile(QOpenGLShader::Vertex, ":/testvert.vert" ); program->addShaderFromSourceFile(QOpenGLShader::Fragment, ":/testfrag.frag"); program->link(); Camera::instance().LookAt(0,0,5, 0,0,0 ,0,1,0); } void RenderingWindow::resizeGL(int w, int h) { Camera::instance().Perspective(60,w/h,0,10000); } void RenderingWindow::paintGL() { program->bind(); program->setUniformValue("MVP",Camera::instance().GetMVP()); model.Draw(); program->release(); } void RenderingWindow::LoadModel() { QString filename = QFileDialog::getOpenFileName(this,"Choose Model file",QString(),"Model files (*.fbx *.obj)"); model.LoadModel(*this, filename, program); }
model.Draw() goes through all the meshes currently attached to this model and draws them.
-
Mesh(const Mesh& mesh)
callsvoid Mesh::initialize()
. Who callsMesh(const Mesh& mesh)
? The constructor must be called from within the correct OpenGL context. -
@Wieland I think it's called when storing the Meshes inside a QVector. So the constructor is called somewhere in LoadModel().
-
Ok. Then call
makeCurrent()
invoid RenderingWindow::LoadModel()
. -
@Wieland somehow It's still not working.
The reason why I have to call initialize() inside the copyConstructor is, that you can't copy QOpenGLVertexArrayObject..