Qt5 QOpenGL does not draw anything - c++

I'm using a Widget inheriting QGLWidget to show an OpenGL viewport inside my Qt application.
The Widget does nothing more than creating three CRenderVectors and drawing them all the time.
A CRenderVector is simply a group of a QVector3D, a QOpenGLVertexArrayObject and three QOpenGLBuffers for vertices, indices and colors.
The vertex buffer objects get created with
const GLFloat color[] = {1, 0, 0, 1, 0, 0};
color_buffer.create();
color_buffer.setUsagePattern(QOpenGLBuffer::StaticDraw);
color_buffer.bind();
color_buffer.allocate(color, sizeof(color);
color_buffer.release();
respectively, using 0, 0, 0 and vec().{x,y,z}() for the vertex_buffer.
The vertex array object gets created via
vertex_array.create();
vertex_array.bind();
vertex_buffer.bind();
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_TRUE, 0, (void*)0);
index_buffer.bind();
color_buffer.bind();
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_TRUE, 0, (void*)0);
vertex_array.release();
Drawing of a vector looks like
vertex_array.bind();
glDrawElements(GL_LINES, elements, GL_UNSIGNED_INT, (void*)0);
vertex_array.release();
The problem is, that I can't see anything in the viewport except the clearing color although I think I'm using everything like shown in the official Qt documentation. Where did I misunderstand Qt or OpenGL documentations?
The stripped project for QtCreator can be downloaded at mediafire.

Related

Incorrect instanced rendering

Previously, to render a bunch of quads, I was simply using a few uniforms (One for a model matrix and another for the texture layer ID), however, I'd rather not have to loop through each quad and set both uniforms each time, each frame.
So I went ahead and looked for better alternatives with which I could render everything with a single call.
Now I'm using instanced rendering:
// In VAO definition
glGenBuffers(1, &instanceVBO);
glBindBuffer(GL_ARRAY_BUFFER, instanceVBO);
glBufferData(GL_ARRAY_BUFFER, 0, nullptr, GL_DYNAMIC_DRAW);
glEnableVertexAttribArray(3);
glVertexAttribPointer(3, 4, GL_FLOAT, GL_FALSE, sizeof(RenderingData), nullptr);
glVertexAttribDivisor(3, 1);
glEnableVertexAttribArray(4);
glVertexAttribPointer(4, 4, GL_FLOAT, GL_FALSE, sizeof(RenderingData), (GLvoid*)(sizeof(glm::vec4)));
glVertexAttribDivisor(4, 1);
glEnableVertexAttribArray(5);
glVertexAttribPointer(5, 4, GL_FLOAT, GL_FALSE, sizeof(RenderingData), (GLvoid*)(sizeof(glm::vec4) * 2));
glVertexAttribDivisor(5, 1);
glEnableVertexAttribArray(6);
glVertexAttribPointer(6, 4, GL_FLOAT, GL_FALSE, sizeof(RenderingData), (GLvoid*)(sizeof(glm::vec4) * 3));
glVertexAttribDivisor(6, 1);
glEnableVertexAttribArray(7);
glVertexAttribIPointer(7, 1, GL_UNSIGNED_INT, sizeof(RenderingData), (GLvoid*)(sizeof(glm::mat4)));
glVertexAttribDivisor(7, 1);
// In quad adding function
instanceData.push_back(quad->data);
glBindBuffer(GL_ARRAY_BUFFER, instanceVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(RenderingData) * quads.size(), &instanceData[0], GL_DYNAMIC_DRAW);
// Rendering
glDrawElementsInstanced(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0, quads.size());
I'm using 2 VBOs: one for per-vertex data (Position, normal, etc vectors) and another for per-instance data (Model matrix and texture layer ID).
My problem is the following: http://imgur.com/20Wb9pQ
As you can see, the middle and bottom images aren't rendering correctly (Middle one is way too stretched, whereas bottom one's UV are incorrect, since they aren't filling the whole quad), however, I'm 98% sure both my vertex and instance data are correct, since when I was using the previously mentioned uniforms, they were rendering correctly.
Also, I might 've spotted the problem: the indices. Somehow, if I change my glDrawElementsInstanced's count value to say, 12 indices, the middle one renders correctly, whereas the other 2, do not (Proof: http://imgur.com/PDQqbuT), same thing happens if I change them to 18 (The last one renders correctly and the other 2, do not).
What might the problem be?

Are a wgl contextfor FSAA multisampling and glVertexPointer/glColorpointer compatible

I hope this is the right lanuage to describe what I have done! I've created a WGL OpenGL context that supports FSAA. I have managed to render using shaders and VBOs through using
glBindBuffer(GL_ARRAY_BUFFER, my_gl_vertexbuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertex_buffer_data[0][0])*9, g_vertex_buffer_data, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, my_gl_vertexbuffer);
glVertexAttribPointer(
0,
3,
GL_FLOAT,
GL_FALSE,
0,
(void*)0
);
glBindBuffer(GL_ARRAY_BUFFER, my_gl_colorbuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(g_color_buffer_data[0][0])*9, g_color_buffer_data, GL_STATIC_DRAW);
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, my_gl_colorbuffer);
glVertexAttribPointer(
1, // attribute. No particular reason for 1, but must match the layout in the shader.
3, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void*)0 // array buffer offset
);
glDrawArrays(GL_TRIANGLES, 0, 3); // 3 indices starting at 0 -> 1 triangle
and I get an output, without lighting because I have no lighting calculations in my shader cause I have 3 lights lighting the scene.
So it was suggested that I could use
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, g_vertex_buffer_data);
glEnableClientState(GL_COLOR_ARRAY);
glColorPointer(3, GL_FLOAT, 0,g_color_buffer_data);
glDrawArrays(GL_TRIANGLES, 0, 3); // 3 indices starting at 0 -> 1 triangle
which sort of works in a simple OpenGL context [that does not support FSAA]. In an FSAA WGL context [without any shaders loaded so I can use the fixed pipeline] all I get is the background colour that I cleared the screen to - it does not seem to render anything. Are glVertexPointer etc commands not supported in a FSAA WGL context? Or is it a case that with WGL context I have to use shaders?
You cannot use glVertexPointer (...), glColorPointer (...), etc... in a forward-compatible context.
Your problem has nothing to do with MSAA (though using 64x raises eyebrows), rather you have told GL to eliminate everything deprecated. A forward-compatible context is one step beyond core in terms of restrictivity. There are things that are deprecated but not removed in core, like wide lines... forward-compatible removes anything deprecated that is still valid in core.
Nevertheless, glColorPointer (...) is both, deprecated and removed from core. You must remove the forward-compatible bit from your context flags to use it.

OpenGL Flicker with glBufferSubData [duplicate]

It seems like glBufferSubData is overwriting or somehow mangling data between my glDrawArrays calls. I'm working in Windows 7 64bit, with that latest drivers for my Nvidia GeForce GT520M CUDA 1GB.
I have 2 models, each with an animation. The models have 1 mesh, and that mesh is stored in the same VAO. They also have 1 animation each, and the bone transformations to be used for rendering the mesh is stored in the same VBO.
My workflow looks like this:
calculate bone transformation matrices for a model
load bone transformation matrices into opengl using glBufferSubData, then bind the buffer
render the models mesh using glDrawArrays
For one model, this works (at least, mostly - sometimes I get weird gaps in between the vertices).
However, for more than one model, it looks like bone transformation matrix data is getting mixed up between the rendering calls to the meshes.
Single Model Animated Windows
Two Models Animated Windows
I load my bone transformation data like so:
void Animation::bind()
{
glBindBuffer(GL_UNIFORM_BUFFER, bufferId_);
glBufferSubData(GL_UNIFORM_BUFFER, 0, currentTransforms_.size() * sizeof(glm::mat4), &currentTransforms_[0]);
bindPoint_ = openGlDevice_->bindBuffer( bufferId_ );
}
And I render my mesh like so:
void Mesh::render()
{
glBindVertexArray(vaoId_);
glDrawArrays(GL_TRIANGLES, 0, vertices_.size());
glBindVertexArray(0);
}
If I add a call to glFinish() after my call to render(), it works just fine! This seems to indicate to me that, for some reason, the transformation matrix data for one animation is 'bleeding' over to the next animation.
How could this happen? I am under the impression that if I called glBufferSubData while that buffer was in use (i.e. for a glDrawArrays for example), then it would block. Is this not the case?
It might be worth mentioning that this same code works just fine in Linux.
Note: Related to a previous post, which I deleted.
Mesh Loading Code:
void Mesh::load()
{
LOG_DEBUG( "loading mesh '" + name_ +"' into video memory." );
// create our vao
glGenVertexArrays(1, &vaoId_);
glBindVertexArray(vaoId_);
// create our vbos
glGenBuffers(5, &vboIds_[0]);
glBindBuffer(GL_ARRAY_BUFFER, vboIds_[0]);
glBufferData(GL_ARRAY_BUFFER, vertices_.size() * sizeof(glm::vec3), &vertices_[0], GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, vboIds_[1]);
glBufferData(GL_ARRAY_BUFFER, textureCoordinates_.size() * sizeof(glm::vec2), &textureCoordinates_[0], GL_STATIC_DRAW);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, vboIds_[2]);
glBufferData(GL_ARRAY_BUFFER, normals_.size() * sizeof(glm::vec3), &normals_[0], GL_STATIC_DRAW);
glEnableVertexAttribArray(2);
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, vboIds_[3]);
glBufferData(GL_ARRAY_BUFFER, colors_.size() * sizeof(glm::vec4), &colors_[0], GL_STATIC_DRAW);
glEnableVertexAttribArray(3);
glVertexAttribPointer(3, 4, GL_FLOAT, GL_FALSE, 0, 0);
if (bones_.size() == 0)
{
bones_.resize( vertices_.size() );
for (auto& b : bones_)
{
b.weights = glm::vec4(0.25f);
}
}
glBindBuffer(GL_ARRAY_BUFFER, vboIds_[4]);
glBufferData(GL_ARRAY_BUFFER, bones_.size() * sizeof(VertexBoneData), &bones_[0], GL_STATIC_DRAW);
glEnableVertexAttribArray(4);
glVertexAttribIPointer(4, 4, GL_INT, sizeof(VertexBoneData), (const GLvoid*)0);
glEnableVertexAttribArray(5);
glVertexAttribPointer(5, 4, GL_FLOAT, GL_FALSE, sizeof(VertexBoneData), (const GLvoid*)(sizeof(glm::ivec4)));
glBindVertexArray(0);
}
Animation UBO Setup:
void Animation::setupAnimationUbo()
{
bufferId_ = openGlDevice_->createBufferObject(GL_UNIFORM_BUFFER, Constants::MAX_NUMBER_OF_BONES_PER_MESH * sizeof(glm::mat4), &currentTransforms_[0]);
}
where Constants::MAX_NUMBER_OF_BONES_PER_MESH is set to 100.
In OpenGlDevice:
GLuint OpenGlDevice::createBufferObject(GLenum target, glmd::uint32 totalSize, const void* dataPointer)
{
GLuint bufferId = 0;
glGenBuffers(1, &bufferId);
glBindBuffer(target, bufferId);
glBufferData(target, totalSize, dataPointer, GL_DYNAMIC_DRAW);
glBindBuffer(target, 0);
bufferIds_.push_back(bufferId);
return bufferId;
}
Those usage flags are mostly correct for this scenario, though you might consider trying GL_STREAM_DRAW.
Your driver appears to be failing to implicitly synchronize for some reason, so you might want to try a technique that eliminates the need for synchronization in the first place. I would suggest Buffer Orphaning: call glBufferData (...) with NULL for the data pointer prior to sending data. This will allow commands that are currently using the UBO to continue using the original data store without forcing synchronization, since you will allocate a new data store before sending new data. When the earlier mentioned commands finish the original data store will be orphaned and the GL implementation will free it.
In newer OpenGL implementations you can use glInvalidateBuffer[Sub]Data (...) to hint the driver into doing what was discussed above. Likewise, you can use glMapBufferRange (...) with appropriate flags to control all of this behavior more explicitly. Unmapping will implicitly flush and synchronize access to a buffer object unless told otherwise, this might get your driver to do its job if you do not want to mess around with synchronization-free buffer update logic.
Most of what I mentioned is discussed in more detail here.

glBufferSubData between glDrawArrays calls mangling data

It seems like glBufferSubData is overwriting or somehow mangling data between my glDrawArrays calls. I'm working in Windows 7 64bit, with that latest drivers for my Nvidia GeForce GT520M CUDA 1GB.
I have 2 models, each with an animation. The models have 1 mesh, and that mesh is stored in the same VAO. They also have 1 animation each, and the bone transformations to be used for rendering the mesh is stored in the same VBO.
My workflow looks like this:
calculate bone transformation matrices for a model
load bone transformation matrices into opengl using glBufferSubData, then bind the buffer
render the models mesh using glDrawArrays
For one model, this works (at least, mostly - sometimes I get weird gaps in between the vertices).
However, for more than one model, it looks like bone transformation matrix data is getting mixed up between the rendering calls to the meshes.
Single Model Animated Windows
Two Models Animated Windows
I load my bone transformation data like so:
void Animation::bind()
{
glBindBuffer(GL_UNIFORM_BUFFER, bufferId_);
glBufferSubData(GL_UNIFORM_BUFFER, 0, currentTransforms_.size() * sizeof(glm::mat4), &currentTransforms_[0]);
bindPoint_ = openGlDevice_->bindBuffer( bufferId_ );
}
And I render my mesh like so:
void Mesh::render()
{
glBindVertexArray(vaoId_);
glDrawArrays(GL_TRIANGLES, 0, vertices_.size());
glBindVertexArray(0);
}
If I add a call to glFinish() after my call to render(), it works just fine! This seems to indicate to me that, for some reason, the transformation matrix data for one animation is 'bleeding' over to the next animation.
How could this happen? I am under the impression that if I called glBufferSubData while that buffer was in use (i.e. for a glDrawArrays for example), then it would block. Is this not the case?
It might be worth mentioning that this same code works just fine in Linux.
Note: Related to a previous post, which I deleted.
Mesh Loading Code:
void Mesh::load()
{
LOG_DEBUG( "loading mesh '" + name_ +"' into video memory." );
// create our vao
glGenVertexArrays(1, &vaoId_);
glBindVertexArray(vaoId_);
// create our vbos
glGenBuffers(5, &vboIds_[0]);
glBindBuffer(GL_ARRAY_BUFFER, vboIds_[0]);
glBufferData(GL_ARRAY_BUFFER, vertices_.size() * sizeof(glm::vec3), &vertices_[0], GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, vboIds_[1]);
glBufferData(GL_ARRAY_BUFFER, textureCoordinates_.size() * sizeof(glm::vec2), &textureCoordinates_[0], GL_STATIC_DRAW);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, vboIds_[2]);
glBufferData(GL_ARRAY_BUFFER, normals_.size() * sizeof(glm::vec3), &normals_[0], GL_STATIC_DRAW);
glEnableVertexAttribArray(2);
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, vboIds_[3]);
glBufferData(GL_ARRAY_BUFFER, colors_.size() * sizeof(glm::vec4), &colors_[0], GL_STATIC_DRAW);
glEnableVertexAttribArray(3);
glVertexAttribPointer(3, 4, GL_FLOAT, GL_FALSE, 0, 0);
if (bones_.size() == 0)
{
bones_.resize( vertices_.size() );
for (auto& b : bones_)
{
b.weights = glm::vec4(0.25f);
}
}
glBindBuffer(GL_ARRAY_BUFFER, vboIds_[4]);
glBufferData(GL_ARRAY_BUFFER, bones_.size() * sizeof(VertexBoneData), &bones_[0], GL_STATIC_DRAW);
glEnableVertexAttribArray(4);
glVertexAttribIPointer(4, 4, GL_INT, sizeof(VertexBoneData), (const GLvoid*)0);
glEnableVertexAttribArray(5);
glVertexAttribPointer(5, 4, GL_FLOAT, GL_FALSE, sizeof(VertexBoneData), (const GLvoid*)(sizeof(glm::ivec4)));
glBindVertexArray(0);
}
Animation UBO Setup:
void Animation::setupAnimationUbo()
{
bufferId_ = openGlDevice_->createBufferObject(GL_UNIFORM_BUFFER, Constants::MAX_NUMBER_OF_BONES_PER_MESH * sizeof(glm::mat4), &currentTransforms_[0]);
}
where Constants::MAX_NUMBER_OF_BONES_PER_MESH is set to 100.
In OpenGlDevice:
GLuint OpenGlDevice::createBufferObject(GLenum target, glmd::uint32 totalSize, const void* dataPointer)
{
GLuint bufferId = 0;
glGenBuffers(1, &bufferId);
glBindBuffer(target, bufferId);
glBufferData(target, totalSize, dataPointer, GL_DYNAMIC_DRAW);
glBindBuffer(target, 0);
bufferIds_.push_back(bufferId);
return bufferId;
}
Those usage flags are mostly correct for this scenario, though you might consider trying GL_STREAM_DRAW.
Your driver appears to be failing to implicitly synchronize for some reason, so you might want to try a technique that eliminates the need for synchronization in the first place. I would suggest Buffer Orphaning: call glBufferData (...) with NULL for the data pointer prior to sending data. This will allow commands that are currently using the UBO to continue using the original data store without forcing synchronization, since you will allocate a new data store before sending new data. When the earlier mentioned commands finish the original data store will be orphaned and the GL implementation will free it.
In newer OpenGL implementations you can use glInvalidateBuffer[Sub]Data (...) to hint the driver into doing what was discussed above. Likewise, you can use glMapBufferRange (...) with appropriate flags to control all of this behavior more explicitly. Unmapping will implicitly flush and synchronize access to a buffer object unless told otherwise, this might get your driver to do its job if you do not want to mess around with synchronization-free buffer update logic.
Most of what I mentioned is discussed in more detail here.

Moving to OpenGL 2.0, getting a black screen

I'm trying to modernize my OpenGL code a little bit by bringing it to OpenGL 2.0 time, but all I get is a black screen... perhaps someone spots a mistake in my code (not that much of code).
Here is a snip of the relevant bits of my old, fully working code.
// Send color data into GPU memory
glEnableClientState(GL_COLOR_ARRAY);
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, colorsHandle);
GL15.glBufferData(GL15.GL_ARRAY_BUFFER, colors, GL15.GL_DYNAMIC_DRAW);
glColorPointer(4, GL_FLOAT, 0, 0);
// Send vertex data into GPU memory
glEnableClientState(GL_VERTEX_ARRAY);
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, verticesHandle);
GL15.glBufferData(GL15.GL_ARRAY_BUFFER, GL15.GL_DYNAMIC_DRAW);
glVertexPointer(3, GL_FLOAT, 0, 0);
// Send texcoords data into GPU memory
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, texcoordsHandle);
GL15.glBufferData(GL15.GL_ARRAY_BUFFER, GL15.GL_DYNAMIC_DRAW);
glTexCoordPointer(2, GL_FLOAT, 0, 0);
for (Batch batch : batches) batch.render();
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
... batch calls glDrawArrays (amongst doing some opengl state changes) ...
glDrawArrays(GL_QUADS, spriteOffset * 4, spriteCount * 4);
And here is the new code:
// Send color data into GPU memory
GL20.glEnableVertexAttribArray(0);
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, colorsHandle);
GL15.glBufferData(GL15.GL_ARRAY_BUFFER, colors, GL15.GL_DYNAMIC_DRAW);
GL20.glVertexAttribPointer(0, 4, GL_FLOAT, false, 0, 0);
// Send vertex data into GPU memory
GL20.glEnableVertexAttribArray(1);
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, verticesHandle);
GL15.glBufferData(GL15.GL_ARRAY_BUFFER, vertices, GL15.GL_DYNAMIC_DRAW);
GL20.glVertexAttribPointer(1, 3, GL_FLOAT, false, 0, 0);
// Send texcoords data into GPU memory
GL20.glEnableVertexAttribArray(2);
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, texcoordsHandle);
GL15.glBufferData(GL15.GL_ARRAY_BUFFER, texcoords,GL15.GL_DYNAMIC_DRAW);
GL20.glVertexAttribPointer(2, 2, GL_FLOAT, false, 0, 0);
for (Batch batch : batches) batch.render();
GL20.glDisableVertexAttribArray(0);
GL20.glDisableVertexAttribArray(1);
GL20.glDisableVertexAttribArray(2);
Like I said the first bit of code works perfectly, but the second does not draw anything at all. Those are the only lines of code I changed in my renderer, and they look correct to me. But obviously there is a problem somewhere... What could possibly cause the absence of rendering?
If those are really the only lines you've changed, then I guess you haven't implemented any shaders?
In OpenGLES 2.0 there is no fixed function pipeline, so you need to write vertex/fragment shaders, compile them, link program objects, etc.
I'm sure you can find many tutorials for this if you search.