OpenGL 3 VBO Indexing Multiple figures (glDrawElements) - opengl

I'm working on my first steps with OpenGL (3.x) and I plan to use VAO & VBO's to draw several figures (triangle, cube,...):
Now i got the following setup:
VAO -->
VBO [vertices, colors] + VBO [indices]
Where "vertices" has [3 * 3floats vertices of triangle, 8*3floats of cube],
"colors" has RGB per vertex (no alpha),
"indices" has [ triangle: 0,1,2, square: 0,1,2, 0,2,3, ...]
Now if I draw using "glDrawElements". i only see the first figure on the series drawn correctly (and getting the right color), the second one doesn't works as it should.
So if i render the triangle data first, it goes like:
And if i render the cube first, it goes like:
Note: triangle is red, and cube is colourful, so the first figure is always shown as I expected
This worked ok drawing arrays with "glDrawArrays" (with offset + trianglecount) instead of drawElements but, of course, indexing makes the data arrays muuuuuch smaller. So i wanted to do the move.
How could i draw the same setup but with indexing? should i call another method?
This is the code I use to prepare the VBO's data, in case of doubt.
// VBOS solid
glBindBuffer(GL_ARRAY_BUFFER, vboSolid[0]);
glBufferData(GL_ARRAY_BUFFER, vertices.size()*sizeof(GLfloat),&vertices[0], GL_STATIC_DRAW);
glVertexAttribPointer((GLuint)0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vboSolid[1]);
glBufferData(GL_ARRAY_BUFFER, colors.size()*sizeof(GLfloat),&colors[0], GL_STATIC_DRAW);
glVertexAttribPointer((GLuint)1, 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(1);
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, vboIndex );
glBufferData( GL_ELEMENT_ARRAY_BUFFER, indices.size()*sizeof(GLuint),&indices[0], GL_STATIC_DRAW);
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, 0 );
And this is the call I do when rendering.
In this loop, the triangle would have indicesCount=3 & offset=0, while cube would have 24 & 3 respectively.
glDrawElements(
GL_TRIANGLES,
primitives[i]->indicesCount,
GL_UNSIGNED_INT,
(void*) (primitives[i]->offsetIndices*sizeof(GLuint))
);

Since i was still testing after posting, i finally made a working attempt, using:
glDrawElementsBaseVertex(
GL_TRIANGLES.
__INDICES_TO_RENDER__,
GL_UNSIGNED_INT,
(void*) (__INDICES_RENDERED___*sizeof(GLuint)),
_VERTICES_RENDERED_BEFORE_
);
where "INDICES_TO_RENDER" and "INDICES_RENDERED_" are values counting 3f, so for a cube you use 24floats as value "TO_RENDER", and 0 to "_RENDERED".
"_VERTICES_RENDERED_BEFORE_" worked being a human value of vertices rendered, so before cube is rendered, it is 0, after, it should be 8.
Kinda weird (probably i did something wrong), but it worked in my tests:
It was said at Using an offset with VBOs in OpenGL, but i tried several times till i found what to put into the call.
If an expert could verify this, i would be happier :P.

Related

Unexpected triangles rendered with OpenGL

I want to render blender's default cube and Suzanne. I have them both exported as OBJ-files. Loading and rendering works fine, but when I attempt to render them both in the same scene, things become confusing (to me).
The "relevant" code is in lines 48 to 56.
In the beginning there was just model1 (Line 51, Suzanne or a cube or anything else) and the scene was rendered as expected.
Then I added another model2 (Line 54), which happened to be the cube.
The unintended triangles (see rendered scene, Screenshot (I)) where drawn ontop of the cube, which was not translated "away" at this point.
Don't know my plans or thoughts of when I moved the cube into the back, but was surprised to find the garbage triangles stay where they are.
Since I had no idea where they came from, I started flipping lines around to get my hands on it:
It is of no importance whether model1 is rendered first, or model2.
When I load two default_cubes instead of one suzanne, one cube is perfectly fine, and the other one just like in the first screenshot.
The result is seen in Screenshot (II). I'm constructing model2 before model1 and the garbage is now rendered differently in a different place.
The code below shows the last part of the Model-constructor, where the VBA is configured. The render() function is the one being seen in the screenshots.
[...]
glGenVertexArrays( 1, &VBA );
glBindVertexArray( VBA );
glGenBuffers( 1, &VBO[0] );
glBindBuffer( GL_ARRAY_BUFFER, VBO[0] );
glBufferData( GL_ARRAY_BUFFER, sizeof(glm::vec3) * vertices.size(), vertices.data(), GL_STATIC_DRAW );
glEnableVertexAttribArray( 0 );
glVertexAttribPointer( 0, 3, GL_FLOAT, GL_FALSE, 0, 0 );
}
void Model::render( void )
{
glUniformMatrix4fv( model_location, 1, GL_FALSE, &model_matrix[0][0] );
glBindVertexArray( VBA );
// 'vertices' is of type std::vector<glm::vec3>
glDrawArrays( GL_TRIANGLES, 0, sizeof(glm::vec3) * vertices.size() );
}
You pass wrong data to glDrawArrays. The third parameter has to contain the number of vertices, not the size in bytes. The correct call would be:
glDrawArrays( GL_TRIANGLES, 0, vertices.size() );

Opengl vao with ebo

I'm currently learning OpenGL in my free time and lately I have been facing an "error" I don't understand.
The thing is, I have no errors, only nothing appear on my screen. I'm using OpenGL with SFML.
Here is my code. Here is my method:
void CreateObjet(GLuint& vao, GLuint& vbo, GLuint& ebo, GLuint& textureLocation)
//I create my arrays here.. Don't worry they are fine.
CreateTexture(textureLocation);
glGenBuffers(1, &vbo);
glGenBuffers(1, &ebo);
glGenVertexArrays (1, &vao);
glBindVertexArray (vao); //On travaille dans le VAO
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData (GL_ARRAY_BUFFER, sizeof(points), points, GL_STATIC_DRAW);
glVertexAttribPointer (0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), NULL);
glEnableVertexAttribArray(0);
glBufferData (GL_ARRAY_BUFFER, sizeof(colors), colors, GL_STATIC_DRAW);
glVertexAttribPointer (1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(3* sizeof(GLfloat)));
glEnableVertexAttribArray(1);
glBufferData (GL_ARRAY_BUFFER, sizeof(texCoords), texCoords, GL_STATIC_DRAW);
glVertexAttribPointer (2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(6* sizeof(GLfloat)));
glEnableVertexAttribArray(2);
//EBO
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indiceFinal), indiceFinal, GL_STATIC_DRAW);
glBindVertexArray(0);
I know my problem is not with my shaders because I receive no errors in my console with GlshaderRiv().
I would like to know if I'm doing the order properly.
I Create a VBO and a EBO
I Create a VAO
I bind the current VAO to modify it
I bind the current VBO inside the VAO
I bind my first array (Vertex Position vector3f) in my VBO and put them in the first pointer with the correct offset and stride.
I bind my second array (Color Position vector3f) in my VBO and put them in the first pointer with the correct offset and stride.
I bind my third array (Texture Position vector2f) in my VBO and put them in the first pointer with the correct offset and stride.
I bind a EBO within the VAO
I bind the EBO with my element position (Vector 3u).
I unbind the VAO from the memory because my drawing loop is quite later in the code and so, I don't want to use memory space for nothing. Don't worry, Before I draw I put glBindVertexArray(&vao);
That definitely does not look right. You're writing the values for all attributes to the same buffer, with each one overwriting the previous one:
glBufferData (GL_ARRAY_BUFFER, sizeof(points), points, GL_STATIC_DRAW);
glVertexAttribPointer (0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), NULL);
glEnableVertexAttribArray(0);
glBufferData (GL_ARRAY_BUFFER, sizeof(colors), colors, GL_STATIC_DRAW);
...
When you make the second glBufferData() call, it will overwrite the points data that you previously stored in the buffer with the colors data.
The misunderstanding is probably about what glVertexAttribPointer() does. It specifies which buffer the given attribute is sourced from, as well as the data layout (component count, type, etc). But it does not create a copy of the buffer data, or anything like that. The attribute data you want to use must still be stored in the buffer at the time of the draw call.
To fix this, you either have to use a different buffer for each attribute, or arrange the attribute data so that the values for all 3 attributes can be stored in the same buffer. The arguments of your glVertexAttribPointer() calls actually suggest that you were intending to store all attribute values interleaved in the same buffer. To get this working, you have to arrange the attribute values accordingly, and then store them in the buffer with a single glBufferData() call.
The memory arrangement you will need for this will have all the attribute values for the first vertex in sequence, followed by the values for the second vertex, etc. With pi the position of vertex i, ci the color, and ti the texture coordinates, the correct memory layout is:
p0x p0y p0z c0r c0g c0b t0s t0t
p1x p1y p1z c1r c1g c1b t1s t1t
p2x p2y p2z c2r c2g c2b t2s t2t
...

Dynamic VBO read/write in GLSL?

Right now it seems to me that my interleaved VBO is strictly ' read-only ' but I want to update it every frame (preferrably from GLSL).
I have a planet that moves around in an orbit, the code below is for rendering points of the orbit.
Problem outline:
I want each point on that orbit to have its own "lifetime", logic:
when the planet passes each consecutive point? update lifetime to 1.0 and reduce with time!
This will be used to create a fading orbitpath of each moving object. Right now Im just looking for ways to manipulate the vbo...
How can I read AND write within GLSL to and from a VBO ? Can anyone post example please?
Update: I modified the code above to work with transform feedback (suggested by user Andon M. Coleman) but I think I might be doing something wrong (I get glError):
Setup:
// Initialize and upload to graphics card
glGenVertexArrays(1, &_vaoID);
glGenBuffers(1, &_vBufferID);
glGenBuffers(1, &_iBufferID);
glGenBuffers(1, &_tboID);
// First VAO setup
glBindVertexArray(_vaoID);
glBindBuffer(GL_ARRAY_BUFFER, _vBufferID);
glBufferData(GL_ARRAY_BUFFER, _vsize * sizeof(Vertex), _varray, GL_DYNAMIC_DRAW);
// TRANSFORM FEEDBACK
glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, _tboID); // Specify buffer
// Allocate space without specifying data
glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER,
_vsize*sizeof(Vertex), NULL, GL_DYNAMIC_COPY);
// Tell OGL which object to store the results of transform feedback
glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, _vBufferID); //correct?
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE,
sizeof(Vertex), reinterpret_cast<const GLvoid*>(offsetof(Vertex, location)));
glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE,
sizeof(Vertex), reinterpret_cast<const GLvoid*>(offsetof(Vertex, velocity)));
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _iBufferID);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, _isize * sizeof(int), _iarray, GL_STREAM_DRAW);
render method():
//disable fragment, so that we do a first run with feedback
glEnable(GL_RASTERIZER_DISCARD);
glBindVertexArray(_vaoID);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _iBufferID);
glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, _tboID);
glBeginTransformFeedback(_mode);
glDrawElements(_mode, _isize, GL_UNSIGNED_INT, 0);
glEndTransformFeedback();
glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, 0);
glBindVertexArray(0);
glDisable(GL_RASTERIZER_DISCARD);
// then i attempt to do the actual draw
glBindVertexArray(_vaoID);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _iBufferID);
glDrawElements(_mode, _isize, GL_UNSIGNED_INT, 0);
glBindVertexArray(0);
And - right before linking:
const GLchar* feedbackVaryings[] = { "point_position" };
glTransformFeedbackVaryings(_ephemerisProgram->getProgramID(), 1, feedbackVaryings, GL_INTERLEAVED_ATTRIBS);
you can not change the content of your VBO from the rendering pipline of Opengl, but you can use tricks to update them depending on the time, also if you are using Opengl 4.4 you can use ComputeShaders but it's a little bit complicated to explain it in here, hust google for it, good luck.
How can I read AND write within GLSL to and from a VBO?
You can't. VBOs are strictly readonly from the normal rendering shaders. Modification is not possible at all (because that would open an infathomable deep barrel of worms) but using transformation feedback the results of the shader stages can be written into a buffer.
Or you use compute shaders.
Problem outline: I want each point on that orbit to have its own "lifetime", logic: When the planet passes each consecutive point? update lifetime to 1.0 and reduce with time!
Sound like a task for a compute shader. But honestly I don't think there's much to gain from processing this on a GPU.

Sending normalized vertex attribute produces garbage

I'm trying to send a color attribute to my GLSL shader.
The colors are stored in a tightly packed byte array with 3 consecutive bytes making up an RGB triplet.
The shader expects a vec3 so I call glVertexAttribPointer to send normalized float values to the shader.
glBindBuffer(GL_ARRAY_BUFFER, attributeBuffers[COLOR]);
glBufferData(GL_ARRAY_BUFFER, mesh.n_vertices() * 3 * sizeof(GLubyte), color, GL_STATIC_DRAW);
// a little later
glEnableVertexAttribArray(attributes[COLOR]);
glBindBuffer(GL_ARRAY_BUFFER, attributeBuffers[COLOR]);
glVertexAttribPointer(attributes[COLOR], 3, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0);
What happens is that:
The colors don't seem to arrive in the shader, the vertices are colored in a single green color
The application takes a massive performance hit
When I manually normalize the color values, copy them to a float array and send that to OpenGL it renders without any problem:
glBindBuffer(GL_ARRAY_BUFFER, attributeBuffers[COLOR]);
glBufferData(GL_ARRAY_BUFFER, mesh.n_vertices() * 3 * sizeof(GLfloat), colorf, GL_STATIC_DRAW);
// a little later
glEnableVertexAttribArray(attributes[COLOR]);
glBindBuffer(GL_ARRAY_BUFFER, attributeBuffers[COLOR]);
glVertexAttribPointer(attributes[COLOR], 3, GL_FLOAT, GL_FALSE, 0, 0);
I tested this on an AMD graphics card with an OpenGL 3.0 context.
Why is this happening? Am I missing something?
As per Bahbar's suggestion I am now aligning the color triplets to 32-bits and it works flawlessly. Colors arrive correctly in the shader and there is no performance hit at all.

Drawing OpenGL Lines & Squares in 3.2 using VAO & VBO's

I've been experimenting with OpenGL 3.2+.
I can successfully render either a line to the screen, or a square made up of two triangles...
I think I'm using VAO and VBO's correctly, yet somehow I can not rending both of them... I experience strange renders.
Obviously, I've coded it wrong... but how are you supposed to use VAO and VBO's when rending multiple objects defined in different Arrays?
My code is far too long to post here, so I've linked a copy on Pastebin > Here <
When you have multiple objects to display, each in its own buffer array, each buffer needs its own vertex array object handle :
int curr_num_object = 0;
static const int vertex_array_object_fish = curr_num_object++;
static const int vertex_array_object_shark = curr_num_object++;
static const int vertex_array_object_doughnut = curr_num_object++;
GLuint array_vertex_array_object[curr_num_object]; // one for each drawn object
glGenVertexArrays(curr_num_object, &array_vertex_array_object[0]);
then for each buffer array you bind then load its data onto the GPU :
// ----------------- fish
glBindVertexArray(array_vertex_array_object[vertex_array_object_fish]); // fish VAO
GLuint vertex_buffer_fish;
glGenBuffers(1, & vertex_buffer_fish);
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer_fish);
glBufferData(GL_ARRAY_BUFFER, audio_model->get_sizeof_fish_array(), audio_model->get_address_fish_array(), GL_DYNAMIC_DRAW);
glVertexAttribPointer(
0, // attribute. No particular reason for 0, but must match the layout in the shader.
2, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void*)0 // array buffer offset
);
glEnableVertexAttribArray(0);
above only deals with the first such buffer array, fish. Each subsequent object you wish to display wants a similar set of OpenGL calls. Above is called once outside of your windowing event loop (glfw, glut ...). Notice in the 2nd parm to glVertexAttribPointer its a 2D array ... here is its header entry :
float molecules_location_fish[max_fish][num_dimensions_2D_grid]; // X & Y per fish
Here is a second object I want to display (doughnut) with its similar calls to above fish :
// -----------
glBindVertexArray(array_vertex_array_object[vertex_array_object_doughnut]); // doughnut VAO
GLuint vertex_buffer_doughnut_box;
glGenBuffers(1, & vertex_buffer_doughnut_box);
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer_doughnut_box);
glBufferData(GL_ARRAY_BUFFER, audio_model->get_sizeof_doughnut_box_array(), audio_model->get_address_doughnut_box_array(), GL_DYNAMIC_DRAW);
glVertexAttribPointer(
0, // attribute. No particular reason for 0, but must match the layout in the shader.
3, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void*)0 // array buffer offset
);
glEnableVertexAttribArray(0);
// -----------
Now inside your windowing event loop, where perhaps you also make calls to update locations to data of your objects (lines, triangles, ...), you make these OpenGL calls for each object to display :
// ---------
glBindVertexArray(array_vertex_array_object[vertex_array_object_fish]);
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer_fish);
glBufferData(GL_ARRAY_BUFFER, audio_model->get_sizeof_fish_array(), audio_model->get_address_fish_array(), GL_DYNAMIC_DRAW);
glDrawArrays(GL_POINTS, 0, audio_model->get_curr_num_fish()); // 12*3 indices starting at 0 -> 12 triangles
And for completeness, here are the doughnut calls inside your event loop :
glBindVertexArray(array_vertex_array_object[vertex_array_object_doughnut]);
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer_doughnut_box);
glBufferData(GL_ARRAY_BUFFER,audio_model->get_sizeof_doughnut_box_array(),audio_model->get_address_doughnut_box_array(),GL_DYNAMIC_DRAW);
glDrawArrays(GL_TRIANGLES, 0, audio_model->get_curr_num_doughnut_boxes());
Notice in my fish I display its 2D as points, whereas the doughnut is 3D and displayed as a set of triangles (not indexed)
Let us know how you get on - this initial speed bump learning OpenGL is (^()&)(& Here is a really nice set of tutorials : http://www.opengl-tutorial.org