PDA

View Full Version : Difficulties rendering a 3D mesh



qqtolene
11-16-2016, 06:11 AM
Hello everyone I am pretty much a newbie and I would appreciate your assistance.

I have made a simple OpenGL application which reads an .obj file and renders it.

I read the file and put the vertex and indices data in two vectors: std::vector vertices<Vertex> and std::vector indices<GLuint>. Vertex is a struct I constructed:


struct Vertex{
glm::vec3 Position;
glm::vec3 Normal;
}


So now lets suppose I have read an .obj and have filled the above vectors with its data. After that, using the following code I setup my buffers before I render the mesh.


void Mesh::setupBuffers()
{
glGenVertexArrays(1,&VAO);
glGenBuffers(1,&VBO);
glGenBuffers(1,&EBO);

glBindVertexArray(VAO);

glBindBuffer(GL_ARRAY_BUFFER,VBO);
glBufferData(GL_ARRAY_BUFFER,vertices.size()*sizeo f(MyVertex),&vertices[0],GL_STATIC_DRAW);

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER,indices.size( )*sizeof(GLuint),&indices[0],GL_STATIC_DRAW);

glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,sizeof (MyVertex),(GLvoid*)0);
glEnableVertexAttribArray(0);

glVertexAttribPointer(1,3,GL_FLOAT,GL_FALSE,sizeof (MyVertex),(GLvoid*)offsetof(MyVertex,Normal));
glEnableVertexAttribArray(1);

glBindVertexArray(0);
}


Note that the above code is called only once, namely after I load a new .obj .

Finally to render the mesh I use:


void Mesh::Draw()
{
glBindVertexArray(VAO);
glDrawElements(GL_TRIANGLES,indices.size(),GL_UNSI GNED_INT,0);
glBindVertexArray(0);

GLenum error = glGetError();
if(error) std::cout << error << std::endl;
}


the Draw function is being called in every render iteration.

The problem arises when I have rendered the first model and want to draw another one. Lets say that by pressing button 'a' another model is being loaded (by clearing and filling the same vertices and indices vectors as above), setupBuffer() is being called and the program enters the rendering loop. That way the mesh is not being drawn and I get error 1282

I found out that if I instead call the setupBuffer() in every render iteration,namely:


void Mesh::Draw()
{
setupBuffers();

glBindVertexArray(VAO);
glDrawElements(GL_TRIANGLES,indices.size(),GL_UNSI GNED_INT,0);
glBindVertexArray(0);

GLenum error = glGetError();
if(error) std::cout << error << std::endl;
}

everything works fine and I get no errors.

Since the vertices and indices data don't change why do I have to use setupBuffers in every rendering iteration? If not how do I fix this or do you have any hints what I might be missing/doing wrong ?

Regards :)

Dark Photon
11-16-2016, 04:38 PM
What GPU drivers are you using? (e.g. query and print GL_VERSION, GL_RENDERER, and GL_VENDOR)

Also are you using a core or a compatibility context here (e.g. what's your context create call look like)?

On a hunch that you might be using drivers (vendor to remain nameless for now) with a buggy VAO implementation, try commenting out setupBuffers() at the top of your Draw() function, and add this right after glBindVertexArray(VAO):


glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,EBO);

qqtolene
11-17-2016, 01:47 AM
What GPU drivers are you using? (e.g. query and print GL_VERSION, GL_RENDERER, and GL_VENDOR)

Also are you using a core or a compatibility context here (e.g. what's your context create call look like)?

On a hunch that you might be using drivers (vendor to remain nameless for now) with a buggy VAO implementation, try commenting out setupBuffers() at the top of your Draw() function, and add this right after glBindVertexArray(VAO):


glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,EBO);




Thanks for your answer :)

What GPU drivers are you using? (e.g. query and print GL_VERSION, GL_RENDERER, and GL_VENDOR)

I get the following outputs:
version:4.1 (Core Profile) Mesa 12.1.0-devel
renderer:Gallium 0.4 on AMD PITCAIRN (DRM 2.43.0 / 4.4.0-47-generic, LLVM 3.8.0)
vendor:X.Org

Also are you using a core or a compatibility context here (e.g. what's your context create call look like)?

I don't have any context create call, I am not sure why.. I use Qt and glew I don't know whether this answers your question.. You can take a look at the widget I have created using Qt here:
https://github.com/IasonManolas/Thesis/blob/meshScene/glwidget.cpp


On a hunch that you might be using drivers (vendor to remain nameless for now) with a buggy VAO implementation, try commenting out setupBuffers() at the top of your Draw() function, and add this right after glBindVertexArray(VAO):
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,EBO);

I did what you suggested and my draw looks like this:

void Draw()
{
// setupDrawingBuffers();
glBindVertexArray(VAO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,EBO);
glDrawElements(GL_TRIANGLES,indices.size(),GL_UNSI GNED_INT,0);
glBindVertexArray(0);
}
but still nothing renders on screen..

Looking forward for any additional suggestions.
Best Regards

Dark Photon
11-18-2016, 04:51 PM
On a hunch that you might be using drivers (vendor to remain nameless for now) with a buggy VAO implementation, try commenting out setupBuffers() at the top of your Draw() function, and add this right after glBindVertexArray(VAO):
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,EBO);I did what you suggested and my draw looks like this:


void Draw()
{
// setupDrawingBuffers();
glBindVertexArray(VAO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,EBO);
glDrawElements(GL_TRIANGLES,indices.size(),GL_UNSI GNED_INT,0);
glBindVertexArray(0);
}

but still nothing renders on screen..

Ok. Try also copying "glBindBuffer(GL_ARRAY_BUFFER,VBO);" in there along with your vertex attribute pointer sets and enables. Does it work?

Now comment these out one-by-one until it doesn't work anymore. That should point you to one of these which isn't being captured in the VAO state for some reason.

qqtolene
11-19-2016, 02:29 AM
Thanks for your response! Following your advice I found out that the problem is that I have to call glGenVertexArrays(1,&VAO); at each draw call. The following draw function works:
void Draw()
{
glGenVertexArrays(1,&VAO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER,VBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,EBO);

glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,sizeof (MyVertex),(GLvoid*)0);
glEnableVertexAttribArray(0);

glVertexAttribPointer(1,3,GL_FLOAT,GL_FALSE,sizeof (MyVertex),(GLvoid*)offsetof(MyVertex,Normal));
glEnableVertexAttribArray(1);

glDrawElements(GL_TRIANGLES,indices.size(),GL_UNSI GNED_INT,0);
glBindVertexArray(0);
}
whatever combination of function calls in draw that doesnt regenerate the VAO is not working.. Isn't that strange?

Dark Photon
11-19-2016, 09:43 AM
Following your advice I found out that the problem is that I have to call glGenVertexArrays(1,&VAO); at each draw call. The following draw function works:

void Draw()
{
glGenVertexArrays(1,&VAO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER,VBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,EBO);

glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,sizeof (MyVertex),(GLvoid*)0);
glEnableVertexAttribArray(0);

glVertexAttribPointer(1,3,GL_FLOAT,GL_FALSE,sizeof (MyVertex),(GLvoid*)offsetof(MyVertex,Normal));
glEnableVertexAttribArray(1);

glDrawElements(GL_TRIANGLES,indices.size(),GL_UNSI GNED_INT,0);
glBindVertexArray(0);
}
whatever combination of function calls in draw that doesnt regenerate the VAO is not working.. Isn't that strange?

Really? Maybe I'm missing something but that's very strange.

So if you take the above and comment out the glGenVertexArrays() call you've pasted in Draw it doesn't work?

Are you sure the previous value of the variable "VAO" (the last VAO created with glGenVertexArrays) is being persisted into this Draw() call?

Are there "any" intervening GL calls between setupBuffers and Draw() that could mess up the VAO or its bindings?

Comment out the glGenVertexArrays() at the top of Draw(). Now, immediately after binding the VAO in Draw() "before" re-setting its state, query GL for the current values of the VAO state and print them:


for ( int i = 0; i <= 1; i++ )
{
GLint ival;
GLvoid *pval;

glGetVertexAttribiv ( i, GL_VERTEX_ATTRIB_ARRAY_ENABLED , &ival );
glGetVertexAttribiv ( i, GL_VERTEX_ATTRIB_ARRAY_SIZE , &ival );
glGetVertexAttribiv ( i, GL_VERTEX_ATTRIB_ARRAY_STRIDE , &ival );
glGetVertexAttribiv ( i, GL_VERTEX_ATTRIB_ARRAY_TYPE , &ival );
glGetVertexAttribiv ( i, GL_VERTEX_ATTRIB_ARRAY_NORMALIZED , &ival );
glGetVertexAttribiv ( i, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, &ival );
glGetVertexAttribPointerv ( i, GL_VERTEX_ATTRIB_ARRAY_POINTER , &pval );
}
// Also print the numeric handle of the VAO:
printf( "VAO = %ld\n", long( VAO ) );


Now, copy/paste this same logic into the end of setupBuffers() immediately before you bind VAO 0. That'll tell us the state right after setup too.

This should give you a clue about what VAO state is being corrupted (assuming that it is) and when.

qqtolene
11-19-2016, 10:34 AM
Really? Maybe I'm missing something but that's very strange.

So if you take the above and comment out the glGenVertexArrays() call you've pasted in Draw it doesn't work?

Yes thats right.
This works:

void Draw()
{
glGenVertexArrays(1,&VAO);

glBindBuffer(GL_ARRAY_BUFFER,VBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,EBO);

glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,sizeof (MyVertex),(GLvoid*)0);
glEnableVertexAttribArray(0);

glVertexAttribPointer(1,3,GL_FLOAT,GL_FALSE,sizeof (MyVertex),(GLvoid*)offsetof(MyVertex,Normal));
glEnableVertexAttribArray(1);

glDrawElements(GL_TRIANGLES,indices.size(),GL_UNSI GNED_INT,0);
glBindVertexArray(0);
}


This does not:


void Draw()
{
//glGenVertexArrays(1,&VAO);

glBindBuffer(GL_ARRAY_BUFFER,VBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,EBO);

glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,sizeof (MyVertex),(GLvoid*)0);
glEnableVertexAttribArray(0);

glVertexAttribPointer(1,3,GL_FLOAT,GL_FALSE,sizeof (MyVertex),(GLvoid*)offsetof(MyVertex,Normal));
glEnableVertexAttribArray(1);

glDrawElements(GL_TRIANGLES,indices.size(),GL_UNSI GNED_INT,0);
glBindVertexArray(0);
}




Are you sure the previous value of the variable "VAO" (the last VAO created with glGenVertexArrays) is being persisted into this Draw() call?

Are there "any" intervening GL calls between setupBuffers and Draw() that could mess up the VAO or its bindings?

Thats what bothers me too from the moment this problem came up. I don't explicitly change the VAO but I am not sure if I am changing it implicitly somehow..



Comment out the glGenVertexArrays() at the top of Draw(). Now, immediately after binding the VAO in Draw() "before" re-setting its state, query GL for the current values of the VAO state and print them:


for ( int i = 0; i <= 1; i++ )
{
GLint ival;
GLvoid *pval;

glGetVertexAttribiv ( i, GL_VERTEX_ATTRIB_ARRAY_ENABLED , &ival );
glGetVertexAttribiv ( i, GL_VERTEX_ATTRIB_ARRAY_SIZE , &ival );
glGetVertexAttribiv ( i, GL_VERTEX_ATTRIB_ARRAY_STRIDE , &ival );
glGetVertexAttribiv ( i, GL_VERTEX_ATTRIB_ARRAY_TYPE , &ival );
glGetVertexAttribiv ( i, GL_VERTEX_ATTRIB_ARRAY_NORMALIZED , &ival );
glGetVertexAttribiv ( i, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, &ival );
glGetVertexAttribPointerv ( i, GL_VERTEX_ATTRIB_ARRAY_POINTER , &pval );
}
// Also print the numeric handle of the VAO:
printf( "VAO = %ld\n", long( VAO ) );


Now, copy/paste this same logic into the end of setupBuffers() immediately before you bind VAO 0. That'll tell us the state right after setup too.

This should give you a clue about what VAO state is being corrupted (assuming that it is) and when.


So if I got it right my code should look like this:

void Draw()
{
glBindVertexArray(VAO);
for ( int i = 0; i <= 1; i++ )
{
GLint ival;
GLvoid *pval;

glGetVertexAttribiv ( i, GL_VERTEX_ATTRIB_ARRAY_ENABLED , &ival );
glGetVertexAttribiv ( i, GL_VERTEX_ATTRIB_ARRAY_SIZE , &ival );
glGetVertexAttribiv ( i, GL_VERTEX_ATTRIB_ARRAY_STRIDE , &ival );
glGetVertexAttribiv ( i, GL_VERTEX_ATTRIB_ARRAY_TYPE , &ival );
glGetVertexAttribiv ( i, GL_VERTEX_ATTRIB_ARRAY_NORMALIZED , &ival );
glGetVertexAttribiv ( i, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, &ival );
glGetVertexAttribPointerv ( i, GL_VERTEX_ATTRIB_ARRAY_POINTER , &pval );
}

// Also print the numeric handle of the VAO:
printf( "Draw VAO = %ld\n", long( VAO ) );

glBindBuffer(GL_ARRAY_BUFFER,VBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,EBO);

glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,sizeof (MyVertex),(GLvoid*)0);
glEnableVertexAttribArray(0);

glVertexAttribPointer(1,3,GL_FLOAT,GL_FALSE,sizeof (MyVertex),(GLvoid*)offsetof(MyVertex,Normal));
glEnableVertexAttribArray(1);

glDrawElements(GL_TRIANGLES,indices.size(),GL_UNSI GNED_INT,0);
glBindVertexArray(0);
}


and


void setupDrawingBuffers()
{
glGenVertexArrays(1,&VAO);
glGenBuffers(1,&VBO);
glGenBuffers(1,&EBO);

glBindVertexArray(VAO);

glBindBuffer(GL_ARRAY_BUFFER,VBO);
glBufferData(GL_ARRAY_BUFFER,vertices.size()*sizeo f(MyVertex),&vertices[0],GL_STATIC_DRAW);

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER,indices.size( )*sizeof(GLuint),&indices[0],GL_STATIC_DRAW);

glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,sizeof (MyVertex),(GLvoid*)0);
glEnableVertexAttribArray(0);

glVertexAttribPointer(1,3,GL_FLOAT,GL_FALSE,sizeof (MyVertex),(GLvoid*)offsetof(MyVertex,Normal));
glEnableVertexAttribArray(1);

for ( int i = 0; i <= 1; i++ )
{
GLint ival;
GLvoid *pval;

glGetVertexAttribiv ( i, GL_VERTEX_ATTRIB_ARRAY_ENABLED , &ival );
glGetVertexAttribiv ( i, GL_VERTEX_ATTRIB_ARRAY_SIZE , &ival );
glGetVertexAttribiv ( i, GL_VERTEX_ATTRIB_ARRAY_STRIDE , &ival );
glGetVertexAttribiv ( i, GL_VERTEX_ATTRIB_ARRAY_TYPE , &ival );
glGetVertexAttribiv ( i, GL_VERTEX_ATTRIB_ARRAY_NORMALIZED , &ival );
glGetVertexAttribiv ( i, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, &ival );
glGetVertexAttribPointerv ( i, GL_VERTEX_ATTRIB_ARRAY_POINTER , &pval );
}
// Also print the numeric handle of the VAO:
printf( "Setup VAO = %ld\n", long( VAO ) );
glBindVertexArray(0);

}


The output I get after i load the mesh is
Setup VAO=2
Draw VAO=2

So I guess this means there is no modification on the VAO between the setupBuffers() and the Draw() right?

Dark Photon
11-20-2016, 11:48 AM
So if I got it right my code should look like this: ... and ...

Yes, except that you need to add some printf() after each one of the glGetVertexAttrib* calls so you/we can see what the value of each VAO state setting is.

I didn't show this because I thought it was apparent and was trying to keep the verbosity down. But here you go:


for ( int i = 0; i <= 1; i++ )
{
GLint ival;
GLvoid *pval;

glGetVertexAttribiv ( i, GL_VERTEX_ATTRIB_ARRAY_ENABLED , &ival ); printf( "Attr %d: ENABLED = %d\n", i, ival );
glGetVertexAttribiv ( i, GL_VERTEX_ATTRIB_ARRAY_SIZE , &ival ); printf( "Attr %d: SIZE = %d\n", i, ival );
glGetVertexAttribiv ( i, GL_VERTEX_ATTRIB_ARRAY_STRIDE , &ival ); printf( "Attr %d: STRIDE = %d\n", i, ival );
glGetVertexAttribiv ( i, GL_VERTEX_ATTRIB_ARRAY_TYPE , &ival ); printf( "Attr %d: TYPE = 0x%x\n", i, ival );
glGetVertexAttribiv ( i, GL_VERTEX_ATTRIB_ARRAY_NORMALIZED , &ival ); printf( "Attr %d: NORMALIZED = %d\n", i, ival );
glGetVertexAttribiv ( i, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, &ival ); printf( "Attr %d: BUFFER = %d\n", i, ival );
glGetVertexAttribPointerv ( i, GL_VERTEX_ATTRIB_ARRAY_POINTER , &pval ); printf( "Attr %d: POINTER = %p\n", i, pval );
}
// Also print the numeric handle of the VAO:
printf( "Setup VAO = %ld\n", long( VAO ) );



The output I get after i load the mesh is
Setup VAO=2
Draw VAO=2

So I guess this means there is no modification on the VAO between the setupBuffers() and the Draw() right?

It means the bound VAO handle hasn't changed. But we need those other printfs to know whether any of the contents of VAO 2 have changed.

(Also, please include code fragments between ... or
... tags as it makes your post much easier to read.)

qqtolene
11-21-2016, 01:47 AM
Yes, except that you need to add some printf() after each one of the glGetVertexAttrib* calls so you/we can see what the value of each VAO state setting is.

I didn't show this because I thought it was apparent and was trying to keep the verbosity down. But here you go:


for ( int i = 0; i <= 1; i++ )
{
GLint ival;
GLvoid *pval;

glGetVertexAttribiv ( i, GL_VERTEX_ATTRIB_ARRAY_ENABLED , &ival ); printf( "Attr %d: ENABLED = %d\n", i, ival );
glGetVertexAttribiv ( i, GL_VERTEX_ATTRIB_ARRAY_SIZE , &ival ); printf( "Attr %d: SIZE = %d\n", i, ival );
glGetVertexAttribiv ( i, GL_VERTEX_ATTRIB_ARRAY_STRIDE , &ival ); printf( "Attr %d: STRIDE = %d\n", i, ival );
glGetVertexAttribiv ( i, GL_VERTEX_ATTRIB_ARRAY_TYPE , &ival ); printf( "Attr %d: TYPE = 0x%x\n", i, ival );
glGetVertexAttribiv ( i, GL_VERTEX_ATTRIB_ARRAY_NORMALIZED , &ival ); printf( "Attr %d: NORMALIZED = %d\n", i, ival );
glGetVertexAttribiv ( i, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, &ival ); printf( "Attr %d: BUFFER = %d\n", i, ival );
glGetVertexAttribPointerv ( i, GL_VERTEX_ATTRIB_ARRAY_POINTER , &pval ); printf( "Attr %d: POINTER = %p\n", i, pval );
}
// Also print the numeric handle of the VAO:
printf( "Setup VAO = %ld\n", long( VAO ) );




It means the bound VAO handle hasn't changed. But we need those other printfs to know whether any of the contents of VAO 2 have changed.

(Also, please include code fragments between ... or
... tags as it makes your post much easier to read.)

Hello again!
I was wondering why we don't use ival :doh: .
So you were right something is modifying the VAO..
Thats the output I get:

Loading /home/iason/Desktop/Projects/OpenGL_WithoutWrappers/Models/teapot.obj using Assimp library.
Loading was successfull.
Entering setup call
Attr 0: ENABLED = 1
Attr 0: ENABLED = 3
Attr 0: ENABLED = 24
Attr 0: ENABLED = 5126
Attr 0: ENABLED = 0
Attr 0: ENABLED = 3
Attr 0: ENABLED = 3
Attr 1: ENABLED = 1
Attr 1: ENABLED = 3
Attr 1: ENABLED = 24
Attr 1: ENABLED = 5126
Attr 1: ENABLED = 0
Attr 1: ENABLED = 3
Attr 1: ENABLED = 3
Setup VAO = 2
Building Polyhedron..
Finished building Polyhedron.
Computing center of mass..
Finished computing center of mass
Normalizing mesh..
finished mesh normalization.
Number of vertices:18960
Number of faces:6320
Entering draw call
Attr 0: ENABLED = 1
Attr 0: ENABLED = 4
Attr 0: ENABLED = 0
Attr 0: ENABLED = 5126
Attr 0: ENABLED = 0
Attr 0: ENABLED = 0
Attr 0: ENABLED = 0
Attr 1: ENABLED = 1
Attr 1: ENABLED = 4
Attr 1: ENABLED = 0
Attr 1: ENABLED = 5126
Attr 1: ENABLED = 0
Attr 1: ENABLED = 0
Attr 1: ENABLED = 0
DRAW VAO = 2

How can I get more information about where exactly between Draw() and setupBuffers() the modification of the VAO happens?

Best regards

Dark Photon
11-21-2016, 04:45 PM
How can I get more information about where exactly between Draw() and setupBuffers() the modification of the VAO happens?

Your prints are a bit difficult to digest because they all say ENABLED and don't use the best formats for type and pointer. But I think I see what you did.

You know your app better than we do, so you're the best person to figure this out.

A few ideas:

1) At the end of your setupBuffers(), "after" query/print the contents of the VAO and then bind VAO 0, bind VAO 2 again, then print out its contents (copy/paste the query/print logic). Then bind VAO 0 again.

That will tell you whether the VAO state seems to be properly kept across unbinds/rebinds.

2) In setupBuffers() and in Draw() (ONLY in these two functions): Don't use the global variable "VAO". Substitute 999 everywhere you were using it. But do NOT do this substitution anywhere else.

That should tell you whether some other code in your app was binding VAO 2 by getting its handle from the "VAO" state variable and modifying it.

arekkusu
11-21-2016, 08:42 PM
How can I get more information about where exactly between Draw() and setupBuffers() the modification of the VAO happens?


You could set a breakpoint on all of the API that can modify the VAO.

qqtolene
11-22-2016, 07:49 AM
1) At the end of your setupBuffers(), "after" query/print the contents of the VAO and then bind VAO 0, bind VAO 2 again, then print out its contents (copy/paste the query/print logic). Then bind VAO 0 again.

That will tell you whether the VAO state seems to be properly kept across unbinds/rebinds.

So for 1) i modified the setupDrawingBuffers() to:


void setupDrawingBuffers()
{
std::cout<<"Entering setupBuffers().."<<std::endl;

glGenVertexArrays(1,&VAO);
glGenBuffers(1,&VBO);
glGenBuffers(1,&EBO);

glBindVertexArray(VAO);

glBindBuffer(GL_ARRAY_BUFFER,VBO);
glBufferData(GL_ARRAY_BUFFER,vertices.size()*sizeo f(MyVertex),&vertices[0],GL_STATIC_DRAW);

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER,indices.size( )*sizeof(GLuint),&indices[0],GL_STATIC_DRAW);

glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,sizeof (MyVertex),(GLvoid*)0);
glEnableVertexAttribArray(0);

glVertexAttribPointer(1,3,GL_FLOAT,GL_FALSE,sizeof (MyVertex),(GLvoid*)offsetof(MyVertex,Normal));
glEnableVertexAttribArray(1);

for ( int i = 0; i <= 1; i++ )
{
GLint ival;
GLvoid *pval;

glGetVertexAttribiv ( i, GL_VERTEX_ATTRIB_ARRAY_ENABLED , &ival );printf( "Attr %d: ENABLED = %d\n", i, ival );
glGetVertexAttribiv ( i, GL_VERTEX_ATTRIB_ARRAY_SIZE , &ival );printf( "Attr %d: SIZE = %d\n", i, ival );
glGetVertexAttribiv ( i, GL_VERTEX_ATTRIB_ARRAY_STRIDE , &ival );printf( "Attr %d: STRIDE = %d\n", i, ival );
glGetVertexAttribiv ( i, GL_VERTEX_ATTRIB_ARRAY_TYPE , &ival );printf( "Attr %d: TYPE =0x%x\n",i, ival);
glGetVertexAttribiv ( i, GL_VERTEX_ATTRIB_ARRAY_NORMALIZED , &ival );printf( "Attr %d: NORMALIZED = %d\n", i, ival );
glGetVertexAttribiv ( i, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, &ival );printf( "Attr %d: BUFFER = %d\n", i, ival );
glGetVertexAttribPointerv ( i, GL_VERTEX_ATTRIB_ARRAY_POINTER , &pval );printf( "Attr %d: POINTER = %p\n", i, ival );
}
// Also print the numeric handle of the VAO:
printf( "Setup VAO = %ld\n", long( VAO ) );
std::cout<<"Unbinding Vertex Array"<<std::endl;
glBindVertexArray(0);
std::cout<<"Binding Vertex Array to 2"<<std::endl;
glBindVertexArray(2);
for ( int i = 0; i <= 1; i++ )
{
GLint ival;
GLvoid *pval;

glGetVertexAttribiv ( i, GL_VERTEX_ATTRIB_ARRAY_ENABLED , &ival );printf( "Attr %d: ENABLED = %d\n", i, ival );
glGetVertexAttribiv ( i, GL_VERTEX_ATTRIB_ARRAY_SIZE , &ival );printf( "Attr %d: SIZE = %d\n", i, ival );
glGetVertexAttribiv ( i, GL_VERTEX_ATTRIB_ARRAY_STRIDE , &ival );printf( "Attr %d: STRIDE = %d\n", i, ival );
glGetVertexAttribiv ( i, GL_VERTEX_ATTRIB_ARRAY_TYPE , &ival );printf( "Attr %d: TYPE =0x%x\n",i, ival);
glGetVertexAttribiv ( i, GL_VERTEX_ATTRIB_ARRAY_NORMALIZED , &ival );printf( "Attr %d: NORMALIZED = %d\n", i, ival );
glGetVertexAttribiv ( i, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, &ival );printf( "Attr %d: BUFFER = %d\n", i, ival );
glGetVertexAttribPointerv ( i, GL_VERTEX_ATTRIB_ARRAY_POINTER , &pval );printf( "Attr %d: POINTER = %p\n", i, ival );
}

printf( "Setup VAO = %ld\n", long( VAO ) );
std::cout<<"Unbinding Vertex Array"<<std::endl;
glBindVertexArray(0);
std::cout<<"Exiting setupBuffers().."<<std::endl;
}

The output was:
Loading /home/iason/Desktop/Projects/OpenGL_WithoutWrappers/Models/teapot.obj using Assimp library.
Loading was successfull.
Entering setupBuffers()..
Attr 0: ENABLED = 1
Attr 0: SIZE = 3
Attr 0: STRIDE = 24
Attr 0: TYPE =0x1406
Attr 0: NORMALIZED = 0
Attr 0: BUFFER = 3
Attr 0: POINTER = 0x3
Attr 1: ENABLED = 1
Attr 1: SIZE = 3
Attr 1: STRIDE = 24
Attr 1: TYPE =0x1406
Attr 1: NORMALIZED = 0
Attr 1: BUFFER = 3
Attr 1: POINTER = 0x3
Setup VAO = 2
Unbinding Vertex Array
Binding Vertex Array to 2
Attr 0: ENABLED = 1
Attr 0: SIZE = 3
Attr 0: STRIDE = 24
Attr 0: TYPE =0x1406
Attr 0: NORMALIZED = 0
Attr 0: BUFFER = 3
Attr 0: POINTER = 0x3
Attr 1: ENABLED = 1
Attr 1: SIZE = 3
Attr 1: STRIDE = 24
Attr 1: TYPE =0x1406
Attr 1: NORMALIZED = 0
Attr 1: BUFFER = 3
Attr 1: POINTER = 0x3
Setup VAO = 2
Unbinding Vertex Array
So it seems that the unbinding works as it was meant to..



2) In setupBuffers() and in Draw() (ONLY in these two functions): Don't use the global variable "VAO". Substitute 999 everywhere you were using it. But do NOT do this substitution anywhere else.

That should tell you whether some other code in your app was binding VAO 2 by getting its handle from the "VAO" state variable and modifying it.

Do I have to call glGenVertexArrays and if yes how do I do that with an rvalue?

I commented glGenVertexArrays out like this:


void Draw()
{
std::cout<<"Entered Draw.."<<std::endl;
// glGenVertexArrays(1,&VAO);
glBindVertexArray(999);
std::cout<<"printDebugInformation was called in :"<<__func__<<std::endl;
printDebugInformation();
glBindBuffer(GL_ARRAY_BUFFER,VBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,EBO);

glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,sizeof (MyVertex),(GLvoid*)0);
glEnableVertexAttribArray(0);

glVertexAttribPointer(1,3,GL_FLOAT,GL_FALSE,sizeof (MyVertex),(GLvoid*)offsetof(MyVertex,Normal));
glEnableVertexAttribArray(1);

glDrawElements(GL_TRIANGLES,indices.size(),GL_UNSI GNED_INT,0);
glBindVertexArray(0);
}


and I got:
Loading /home/iason/Desktop/Projects/OpenGL_WithoutWrappers/Models/teapot.obj using Assimp library.
Loading was successfull.
Entering setupBuffers()..
printDebugInformation was called in :setupDrawingBuffers
Attr 0: ENABLED = 1
Attr 0: SIZE = 3
Attr 0: STRIDE = 24
Attr 0: TYPE = 0x1406
Attr 0: NORMALIZED = 0
Attr 0: BUFFER = 3
Attr 0: POINTER = 0x3
Attr 1: ENABLED = 1
Attr 1: SIZE = 3
Attr 1: STRIDE = 24
Attr 1: TYPE = 0x1406
Attr 1: NORMALIZED = 0
Attr 1: BUFFER = 3
Attr 1: POINTER = 0x3
VAO = 999
Exiting setupBuffers()..
Building Polyhedron..
Finished building Polyhedron.
Computing center of mass..
Finished computing center of mass
center of mass=(0.0374835,1.72705,-1.12805e-07)
Normalizing mesh..
finished mesh normalization.
Number of vertices:18960
Number of faces:6320
Entered Draw..
printDebugInformation was called in :Draw
Attr 0: ENABLED = 1
Attr 0: SIZE = 4
Attr 0: STRIDE = 0
Attr 0: TYPE = 0x1406
Attr 0: NORMALIZED = 0
Attr 0: BUFFER = 0
Attr 0: POINTER = (nil)
Attr 1: ENABLED = 1
Attr 1: SIZE = 4
Attr 1: STRIDE = 0
Attr 1: TYPE = 0x1406
Attr 1: NORMALIZED = 0
Attr 1: BUFFER = 0
Attr 1: POINTER = (nil)
VAO = 999

Dark Photon
11-22-2016, 07:09 PM
So it seems that the unbinding works as it was meant to..

Yes.


Do I have to call glGenVertexArrays and if yes how do I do that with an rvalue?

Strictly speaking, no. You can just bind an unused ID and it'll create a new VAO on that ID. The helpful thing about the glGen* functions is you don't have to keep track of what IDs you haven't used yet. You just use the IDs returned by it.

I only suggested forceably creating 999 here because it's very unlikely to be used elsewhere in your application, and so very unlikely to be stomped on by some other code.



printDebugInformation was called in :setupDrawingBuffers
...
Entered Draw..
...


Ok. So the setupDrawingBuffers VAO state looks good. But not so much the Draw(). Same problem as before.

At this point if I were you I'd be inclined to just capture a full GL call trace for your application and go digging. If you're on Windows, apitrace (https://github.com/apitrace/apitrace) is one good free choice for this. Just run this:



apitrace trace --api gl --output out.trace /path/to/application [args...]
apitrace dump out.trace > out.trace.txt


And on Linux, IIRC BuGLe (https://sourceforge.net/projects/bugle/) was one good free option.

However, here are a few other suggestions...

As arekkusu said, you can put a breakpoint on the APIs that can modify the VAO. For instance, put a breakpoint on the function pointers for glBindVertexArray, glDeleteVertexArrays, glCreateVertexArrays, etc. (that'll probably do unless your application is using Direct State Access (https://www.opengl.org/wiki/Direct_State_Access) on VAOs.

You can also put a breakpoint on context delete, recreate, and bind calls to see if there's any context switch funny-business going on (e.g. {}MakeCurrent, {}CreateContext, {}CreateContextAttribs, {}DeleteContext where {} is one of "wgl" or "glX" depending on your platform.

Another thing you can try: At the very top of your Draw() method, you can verify that the VAO you're about to bind still exists:


printf( "VAO %d still exists = %d\n", 999, glIsVertexArray( 999 ) );


If not, you know that some code deleted it via glDeleteVertexArrays or other method (e.g. deleted and recreated the context? bound a new context? etc.)

qqtolene
11-23-2016, 07:05 AM
At this point if I were you I'd be inclined to just capture a full GL call trace for your application and go digging. If you're on Windows, apitrace (https://github.com/apitrace/apitrace) is one good free choice for this. Just run this:



apitrace trace --api gl --output out.trace /path/to/application [args...]
apitrace dump out.trace > out.trace.txt


And on Linux, IIRC BuGLe (https://sourceforge.net/projects/bugle/) was one good free option.


The need of an OpenGL debugger is obvious.. I am on Linux and I tried to install Bugle and Vogl but I had no luck with that..

As arekkusu said, you can put a breakpoint on the APIs that can modify the VAO. For instance, put a breakpoint on the function pointers for glBindVertexArray, glDeleteVertexArrays, glCreateVertexArrays, etc. (that'll probably do unless your application is using Direct State Access (https://www.opengl.org/wiki/Direct_State_Access) on VAOs.

You can also put a breakpoint on context delete, recreate, and bind calls to see if there's any context switch funny-business going on (e.g. {}MakeCurrent, {}CreateContext, {}CreateContextAttribs, {}DeleteContext where {} is one of "wgl" or "glX" depending on your platform.


Do you know if I have to do that manually ,namely setting a breakpoint at every call?

I found out that when I don't use Qt to load the model , but rather loading it by default in initializeGL(I explain below when initializeGL is being called) it renders the model.
Let me explain a bit the design of my code so you can understand what is happening. I use a class MainWindow which has a member of type GLWidget which has a member of type Scene which has a member of type Polyhedron(aka Mesh. I just named it MyPolyhedron).
So if A->B means B is a class member of A my design can be represented as:
MainWindow (https://github.com/IasonManolas/Thesis/blob/meshScene/mainwindow.h)->GLWidget (https://github.com/IasonManolas/Thesis/blob/meshScene/glwidget.h)->Scene (https://github.com/IasonManolas/Thesis/blob/meshScene/scene.h)->MyPolyhedron (https://github.com/IasonManolas/Thesis/blob/meshScene/mypolyhedron.h) (1).

What we were discussing until now (VAO,Draw,setupDrawingBuffers) are all members of MyPolyhderon.

What I was doing until now was whenever the user pressed a button,that I have set in MainWindow, a signal is being propagaded along (1) until it reaches GLWidget which calls scene.P.MyPolyhedron::load(filename) which calls MyPolyhedron::setupDrawingBuffers(). After that at some point the function GLWidget::paintGL() is being called which calls MyPolyhedron::Draw() . So as we found out this is not working. So our guess was that something alters the VAO between MyPolyhedron::setupDrawingBuffers() until the program reaches MyPolyhedron::Draw().

Now I tried in GLWidget::initializeGL() to load the model using the same function I used before (scene.P.MyPolyhedron::load(filename)) and it actually rendered the model correctly. So that means that there is nothing wrong with how the mesh is being loaded and there is also nothing wrong with MyPolyhedron::setupDrawingBuffers() . So now that the application was running I tried to use the button that loads a new mesh and that actually worked too. I tried to load another model ( totally excited now that I could see models on my screen) and it worked again! The fourth time I tried to load a model I got a black screen again and the VAO attributes were:
Attr 0: ENABLED = 1
Attr 0: SIZE = 4
Attr 0: STRIDE = 0
Attr 0: TYPE = 0x1406
Attr 0: NORMALIZED = 0
Attr 0: BUFFER = 0
Attr 0: POINTER = (nil)
Attr 1: ENABLED = 1
Attr 1: SIZE = 4
Attr 1: STRIDE = 0
Attr 1: TYPE = 0x1406
Attr 1: NORMALIZED = 0
Attr 1: BUFFER = 0
Attr 1: POINTER = (nil)
again. So all in all (if you are still reading this) the pattern that is being produced by my code is:
if I do not load a model by default in GLWidget::initializeGL() namely:

void GLWidget::initializeGL()
{

....

// scene.loadMesh("../OpenGL_WithoutWrappers/Models/Alien Bust.obj"); <---------- I dont load any models by default


}

I get a black screen since something alters the VAO as we noticed.

If a load a model by default namely:

void GLWidget::initializeGL()
{
....

scene.loadMesh("../OpenGL_WithoutWrappers/Models/Alien Bust.obj");

}

the model is rendered and the button on my app's window is working until the fourth time I use it. After that the screen is black again and the VAO altered.





Another thing you can try: At the very top of your Draw() method, you can verify that the VAO you're about to bind still exists:


printf( "VAO %d still exists = %d\n", 999, glIsVertexArray( 999 ) );


If not, you know that some code deleted it via glDeleteVertexArrays or other method (e.g. deleted and recreated the context? bound a new context? etc.)


I found this QOpenGLDebugLogger class (http://doc.qt.io/qt-5/qopengldebuglogger.html) so I dropped it in also. It seems as the vertex array object is being deleted, which is not a suprise I guess.. The QOpenGLDebugLogger class did not give much additional info just that in the Draw function the VAO does not exist anymore..

Loading /home/iason/Desktop/Projects/OpenGL_WithoutWrappers/Models/teapot.obj using Assimp library.
Loading was successfull.
Entering setupDrawingBuffers()..
printDebugInformation was called in :setupDrawingBuffers
Attr 0: ENABLED = 1
Attr 0: SIZE = 3
Attr 0: STRIDE = 24
Attr 0: TYPE = 0x1406
Attr 0: NORMALIZED = 0
Attr 0: BUFFER = 3
Attr 0: POINTER = 0x3
Attr 1: ENABLED = 1
Attr 1: SIZE = 3
Attr 1: STRIDE = 24
Attr 1: TYPE = 0x1406
Attr 1: NORMALIZED = 0
Attr 1: BUFFER = 3
Attr 1: POINTER = 0x3
VAO = 0
Exiting setupDrawingBuffers()..
Entered Draw..
VAO 999 still exists = 0
QOpenGLDebugMessage("APISource", 2, "GL_INVALID_OPERATION in glBindVertexArray(non-gen name)", "HighSeverity", "ErrorType")
QOpenGLDebugMessage("APISource", 2, "GL_INVALID_OPERATION in glVertexAttribPointer(no array object bound)", "HighSeverity", "ErrorType")
QOpenGLDebugMessage("APISource", 2, "GL_INVALID_OPERATION in glVertexAttribPointer(no array object bound)", "HighSeverity", "ErrorType")
QOpenGLDebugMessage("APISource", 2, "GL_INVALID_OPERATION in glDrawElements(no VAO bound)", "HighSeverity", "ErrorType")

Dark Photon
11-23-2016, 05:32 PM
It sounds like you've found the other GL code that was fouling up your state: Qt. I suspect now it's down to just reading up and figuring out how to properly use OpenGL in a Qt application.


So all in all (if you are still reading this) the pattern that is being produced by my code is:

if I do not load a model by default in GLWidget::initializeGL() namely:

void GLWidget::initializeGL()
{
// scene.loadMesh("../OpenGL_WithoutWrappers/Models/Alien Bust.obj"); <---------- I dont load any models by default
}


I get a black screen since something alters the VAO as we noticed.

If a load a model by default namely:

void GLWidget::initializeGL()
{
scene.loadMesh("../OpenGL_WithoutWrappers/Models/Alien Bust.obj");
}

the model is rendered and the button on my app's window is working until the fourth time I use it. After that the screen is black again and the VAO altered.

Ok. I gather your load() function is calling setupDrawingBuffers() which utilizes GL. The latter above works because at this point in the code, Qt has bound your GL context (according to this (https://doc.qt.io/qt-4.8/qglwidget.html#initializeGL)):



Your widget's OpenGL (https://doc.qt.io/qt-4.8/opengl-module.html) rendering context is made current when paintGL (https://doc.qt.io/qt-4.8/qglwidget.html#paintGL)(), resizeGL (https://doc.qt.io/qt-4.8/qglwidget.html#resizeGL)(), or initializeGL (https://doc.qt.io/qt-4.8/qglwidget.html#initializeGL)() is called. If you need to call the standard OpenGL (https://doc.qt.io/qt-4.8/opengl-module.html) API functions from other places (e.g. in your widget's constructor or in your own paint functions), you must call makeCurrent (https://doc.qt.io/qt-4.8/qglwidget.html#makeCurrent)() first.


So the question is: is all of your GL rendering code inside of one of these 3 functions? If not, are you calling makeCurrent() first?


It seems as the vertex array object is being deleted, which is not a suprise I guess..

Or the currently bound context has been changed and/or deleted, which seems more likely. At the top of each section of GL code, put some printfs in to report the currently-bound GL context (glXGetCurrentContext() (https://www.opengl.org/sdk/docs/man2/xhtml/glXGetCurrentContext.xml)). That may help you.

Dark Photon
11-23-2016, 05:48 PM
The need of an OpenGL debugger is obvious.. I am on Linux and I tried to install Bugle and Vogl but I had no luck with that..

It worked right off the bat for me.

Fetch from here: https://sourceforge.net/projects/bugle/

Now build:


tar -xojvf bugle-0.0.20150628.tar.bz2
cd bugle-0.0.20150628
scons
su
scons install
exit
rehash


Now run your program within BuGLe and capture a GL call trace:


gldb-gui MY_PROGRAM
Options -> Target -> Filter chain -> trace
Run -> Run
File -> Quit


Finally, bring up "bugle.log" in a text editor and see what's been hosing up your GL context state.

qqtolene
11-25-2016, 05:44 AM
Or the currently bound context has been changed and/or deleted, which seems more likely. At the top of each section of GL code, put some printfs in to report the currently-bound GL context (glXGetCurrentContext() (https://www.opengl.org/sdk/docs/man2/xhtml/glXGetCurrentContext.xml)). That may help you.

The behaviour of my code depends on whether MyPolyhedron::Draw() calls glGenVertexArrays. If I call it meshes are being rendered on screen and if I don't I get a black screen.
So consider the case in which we don't call glGenVertexArrays, namely:

// glGenVertexArrays(1,&VAO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER,VBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,EBO);

glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,sizeof (MyVertex),(GLvoid*)0);
glEnableVertexAttribArray(0);

glVertexAttribPointer(1,3,GL_FLOAT,GL_FALSE,sizeof (MyVertex),(GLvoid*)offsetof(MyVertex,Normal));
glEnableVertexAttribArray(1);

glDrawElements(GL_TRIANGLES,indices.size(),GL_UNSI GNED_INT,0);
glBindVertexArray(0);


I have put three glXGetCurrentContext() calls. One in GLWidget::initializeGL(), one in GLWidget::paintGL() and one in GLWidget::modelWasChosen() (the function which is triggered whenever the user presses the Load new mesh button) .
Thats the output I get:
glXGetCurrentContext() was called in :initializeGL
0x6e2240
glXGetCurrentContext() was called in :paintGL
0x6e2240
//when I load a mesh
glXGetCurrentContext() was called in :modelWasChosen
0x74c540
//programm control returns to GLWidget::paintGL()
glXGetCurrentContext() was called in :paintGL
0x6e2240

So the above means that the information of the loaded mesh( VBO's,VAO's etc.) are not bound to the context that paintGL uses (0x6e2240) rather to another one(0x74c540) and thats why nothing gets drawn on screen. More precisely GLWidget::modelWasChosen() is the only function that calls MyPolyhedron::setupDrawingBuffers() which is the function that calls glGenVertexArrays. But because the context of GLWidget::modelWasChosen() (and consequently all of the subsequent calls) is not the same as that of GLWidget::paintGL() the generated VAO is bound to the false context. Right?

Now in case I call glGenVertexArrays, namely:

glGenVertexArrays(1,&VAO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER,VBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,EBO);

glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,sizeof (MyVertex),(GLvoid*)0);
glEnableVertexAttribArray(0);

glVertexAttribPointer(1,3,GL_FLOAT,GL_FALSE,sizeof (MyVertex),(GLvoid*)offsetof(MyVertex,Normal));
glEnableVertexAttribArray(1);

glDrawElements(GL_TRIANGLES,indices.size(),GL_UNSI GNED_INT,0);
glBindVertexArray(0);


I get again the same output as before, namely:
glXGetCurrentContext() was called in :initializeGL
0x6e2240
glXGetCurrentContext() was called in :paintGL
0x6e2240
//same output from GLWidget::paintGL()
//when I load a mesh
glXGetCurrentContext() was called in :modelWasChosen
0x74c540
//programm control returns to GLWidget::paintGL()
glXGetCurrentContext() was called in :paintGL
0x6e2240
but the model now is rendered. My guess is that this happens because although MyPolyhedron::setupDrawingBuffers() is again being called with the wrong context GLWidget::paintGL() calls MyPolyhedron::Draw() which calls glGenVertexArrays with the correct context this time.

A question
If you agree with what I said above why do the buffers remember their data (which are set only when MyPolyhedron::setupDrawingBuffers() is being called through GLWidget::modelWasChosen ) and the VAO does not? If what I have said above is true I would expect that I would have to call glBufferData in every draw call..

How to solve the problem
The obvious solution that comes to my mind is making GLWidget::modelWasChosen context(0x74c540) the current, namely the context that paintGL will use from now on, or setting as the current context before I load the mesh the one that paintGL is using.
To do the first I tried:


void GLWidget::modelWasChosen(std::__cxx11::string filename)
{


scene.loadMesh(filename);
std::cout<<"glXGetCurrentContext() was called in :"<<__func__<<std::endl;
std::cout<<glXGetCurrentContext()<<std::endl;
std::cout<<glXMakeCurrent(glXGetCurrentDisplay(),glXGetCurren tDrawable(),glXGetCurrentContext())<<std::endl; //this call outputs 1(aka true)
}

but paintGL continued using 0x6e2240..

Dark Photon
11-25-2016, 06:42 AM
So the above means that the information of the loaded mesh( VBO's,VAO's etc.) are not bound to the context that paintGL uses (0x6e2240) rather to another one(0x74c540) and thats why nothing gets drawn on screen.

...because the context of GLWidget::modelWasChosen() (and consequently all of the subsequent calls) is not the same as that of GLWidget:: PaintGL() the generated VAO is bound to the false context. Right?

That sounds right to me. It's not the context you're wanting to be active anyway.




Now in case I call glGenVertexArrays, namely:

glGenVertexArrays(1,&VAO);
...
glDrawElements(GL_TRIANGLES,indices.size(),GL_UNSI GNED_INT,0);
glBindVertexArray(0);


...the model now is rendered. My guess is that this happens because although MyPolyhedron::setupDrawingBuffers() is again being called with the wrong context GLWidget:: PaintGL() calls MyPolyhedron:: Draw() which calls glGenVertexArrays with the correct context this time.

That sounds right to me too.


A question
If you agree with what I said above why do the buffers remember their data (which are set only when MyPolyhedron::setupDrawingBuffers() is being called through GLWidget::modelWasChosen ) and the VAO does not? If what I have said above is true I would expect that I would have to call glBufferData in every draw call..

I think the answer to your question can be found by searching the OpenGL wiki ( (https://www.opengl.org/wiki)https://www.opengl.org/wiki) (https://www.opengl.org/wiki) for "context sharing". When you do so, you'll find this:

* https://www.opengl.org/wiki/OpenGL_Object#Object_Sharing

See the 3rd paragraph.

Based on your evidence I suspect Qt is creating multiple GL contexts with object sharing enabled. You might do some reading in the Qt docs on this to be sure.

In summary, buffer objects can be shared across different GL contexts. VAOs (as container objects) cannot.


How to solve the problem
The obvious solution that comes to my mind is making GLWidget::modelWasChosen context(0x74c540) the current, namely the context that paintGL will use from now on, or setting as the current context before I load the mesh the one that paintGL is using.

A couple thoughts come to mind. Assuming you stick with Qt and its usage of GL contexts (which is not a given), then...

One idea is to just set a flag inside modelWasChosen() to indicate that model load work needs to be done, and set state in Qt to indicate that a repaint needs to be done (check the docs, but websearching suggests you call update() to trigger that). And then the next time you paint the window, you can test this flag and if set, do the load work. (I'm not saying this is the most efficient way you could implement model loading, but this would solve your problem).

Another possible solution is to just call (as mentioned above) QGLWidget::makeCurrent() (https://doc.qt.io/qt-4.8/qglwidget.html#makeCurrent) inside modelWasChosen to force the draw GL context to be made active before you create and setup your VAO. Check the Qt docs to see if you need to unbind this and rebind some other context at the end though.

Here's some related reading and a few other ideas for you from a quick websearch:

* OpenGL VAO's - Handling VAO's in multiple contexts [in Qt] (https://stackoverflow.com/questions/13258345/opengl-vaos-handling-vaos-in-multiple-contexts)
* Multiple QGLWidgets with a single openGL Context in C++ (https://stackoverflow.com/questions/8496728/multiple-qglwidgets-with-a-single-opengl-context-in-c)
* Render one scene to multiple windows with same context (https://www.opengl.org/discussion_boards/showthread.php/198707-Render-one-scene-to-multiple-windows-with-same-context)
* Sharing OpenGL VAO/VBO/etc. via QGLWidget contexts (https://www.opengl.org/discussion_boards/showthread.php/174358-Sharing-OpenGL-VAO-VBO-etc-via-QGLWidget-contexts)

qqtolene
11-28-2016, 10:42 AM
Just wanted to say thanks for the assistance. The problem was solved using in GLWidget::modelWasChosen the command makeCurrent() before I load the mesh as you suggested.

Best regards,
Iason

Dark Photon
11-28-2016, 05:37 PM
Just wanted to say thanks for the assistance. The problem was solved using in GLWidget::modelWasChosen the command makeCurrent() before I load the mesh as you suggested.
No problem. Glad you've got it solved.