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() );
Related
I have some example code that calls glVertexAttribPointer() in 2 places. Is this necessary or can it just be done once?
First time - associating the vertex buffer data:
glVertexAttribPointer( 0, 3, GL_FLOAT, GL_FALSE, sizeof( COLVERTEX ), 0 );
glBufferData( GL_ARRAY_BUFFER, sizeof( v ), v, GL_STATIC_DRAW );
Second time - in the rendering callback function:
glEnableVertexAttribArray(0);
glBindBuffer( GL_ARRAY_BUFFER, vboQuad );
glVertexAttribPointer( 0, 3, GL_FLOAT, GL_FALSE, sizeof( COLVERTEX ), 0 );
glDrawArrays( GL_QUADS, 0, 4 );
glDisableVertexAttribArray(0);
Is it really necessary to describe the vertex attributes twice?
BufferData fills VBO with raw data. At this point it doesn't matter how data is supposed to be interpreted when drawing (e.g. the same data may be interpreted as vertex positions at one draw but as normals in another). So yes, you can remove this first call.
If you use vertex array objects, you could set vertex attribute pointers only once (via binding VBO, enabling vertex attibute, and setting vertex attribute pointer) and then just call glBindVertexArray before drawing and have all recorded vertex attrubtes set up (you don't even need to bind VBO containing vertex attributes before draw call).
If I got a cube model for example (cube got 6 faces). how can I draw each face with vbo? do I need to call glDrawElements 6 times? or is there another function to draw all at once? Usually I draw it like this:
for (int i = 0; i < facesNum; i++)
glDrawElements(GL_TRIANGLE_FAN, 4 + i*4, GL_UNSIGNED_INT, (GLvoid*)(i*4));
Is that the best way?
You can use Primitive Restart (OpenGL 3.1+) to restart a primitive such as a triangle fan while rendering, as if you started another glDraw* command.
Use glEnable(GL_PRIMITIVE_RESTART) to enable it, then glPrimitiveRestartIndex(restartIndex) to set an index (such as 0xFFFF) to use to signal a restart. Then whenever OpenGL encounters the restart index, it will stop the currently drawn primitive and start another one.
This lets you draw multiple triangle strips, fans, line loops, or strips with one index buffer and draw command. Just add the restart index between each primitive's index data.
Generally, what you would do is draw your object as GL_TRIANGLES instead of GL_TRIANGLE_FAN, which allows you to just draw all 12 triangles (6 faces * 2 triangles per face) with one call to glDrawElements.
To do this, you of course have to somewhat rearrange your Index Buffer, to include the information for the vertices of each triangle. This means you have to duplicate some indices, which should however not be a problem, as the point of the Index Buffer is precisely to be able to do this and not duplicate vertices.
Assuming your top face consists of the vertices index 0,1,2,3 in counterclockwise order,
you would change that part of the index buffer from 0,1,2,3 to 0,1,2,0,2,3 for example.
With this changed setup of the index buffer, all it should take would be a call to
glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, NULL);
(36 as we are drawing 12 triangles for the cube with 3 vertices each)
You should only have to call DrawElements once with a single VBO. There are alternatives such as IBO's, but I am going to provide an example for a VBO since that is what you requested. Ideally, you should store all the vertices in an array or std::vector holding Vertex objects. Put all of your cube face vertices in this array or std::vector. You do not need an array/vector for each face. You will want to keep the data tightly compact and avoid using the virtual keyword as it creates a non exposed pointer (vtptr) which adds to your class memory footprint. The reason you want to keep the data compact is for when you send it to OpenGL, it will expect step sizes. If you ever are in doubt of the memory footprint of a class, it never hurts to do a quick output with the sizeof( ClassName ) function.
Your vertex class would look something like as follows;
class Vertex {
public:
~Vertex() {}
Vertex() {}
Vector3<float> vertexPosition;
Vector4<float> vertexColor;
Vector2<float> vertexTextureCoords;
Vector3<float> vertexNormal;
Vector3<float> vertexTangent;
Vector3<float> vertexBitangent;
Vector4<int> vertexBoneIndexes;
Vector4<float> vertexBoneWeights;
};
Where all the vector classes are NON virtual and the only data members are the vector components.
Here are the steps I follow:
Create a std::vector (or array) of vertex objects and populate the vertex data
Generate the VBO with the appropriate OpenGL Calls (Here is an example from my engine). I use a singleton which has wrapper functions in order to be Graphics API agnostic. The parameters are in the exact same order OpenGL would expect them for their VBO generation functions.
cbengine::CBRenderer * sharedRenderer = cbengine::CBRenderer::sharedCBRenderer();
sharedRenderer->generateVBOBuffers( 1, &entityToCreate->m_VBOBufferID );
sharedRenderer->bindVBOBuffer( entityToCreate->m_VBOBufferID );
sharedRenderer->bufferDataForVBO( ( sizeof( cbengine::Vertex ) * entityToCreate- >m_verts.size() ), &entityToCreate->m_verts.front() );
In your render function make the following OpenGL Calls. This is why I advised keeping the data tightly compact earlier. OpenGL needs to know what type of data to expect, the size of the data type, and the offset from the start of the data.
glEnableVertexAttribArray( m_vertexLocation );
glVertexAttribPointer( m_vertexLocation, 3, GL_FLOAT, false, sizeof( cbengine::Vertex ), (float*) offsetof( cbengine::Vertex, vertexPosition ) );
glEnableVertexAttribArray( m_colorLocation );
glVertexAttribPointer( m_colorLocation, 4, GL_FLOAT, false, sizeof( cbengine::Vertex ), (float*) offsetof( cbengine::Vertex, vertexColor ) );
glEnableVertexAttribArray( m_diffuseTextureCoordLocation );
glVertexAttribPointer( m_diffuseTextureCoordLocation, 2, GL_FLOAT, false, sizeof( cbengine::Vertex ), (float*) offsetof( cbengine::Vertex, vertexTextureCoords ) );
glEnableVertexAttribArray( m_normalCoordLocation );
glVertexAttribPointer( m_normalCoordLocation, 3, GL_FLOAT, false, sizeof( cbengine::Vertex ), (float*) offsetof( cbengine::Vertex, vertexNormal ) );
glEnableVertexAttribArray( m_tangentLocation );
glVertexAttribPointer( m_tangentLocation, 3, GL_FLOAT, false, sizeof( cbengine::Vertex ), (float*) offsetof( cbengine::Vertex, vertexTangent ) );
glEnableVertexAttribArray( m_bitangentLocation );
glVertexAttribPointer( m_bitangentLocation, 3, GL_FLOAT, false, sizeof( cbengine::Vertex ), (float*) offsetof( cbengine::Vertex, vertexBitangent ) );
glEnableVertexAttribArray( m_boneIndexesLocation ); // Apparently GL_INT causes issues
glVertexAttribPointer( m_boneIndexesLocation, 4, GL_FLOAT, false, sizeof( cbengine::Vertex ), (float*) offsetof( cbengine::Vertex, vertexBoneIndexes ) );
glEnableVertexAttribArray( m_boneWeightsLocation );
glVertexAttribPointer( m_boneWeightsLocation, 4, GL_FLOAT, false, sizeof( cbengine::Vertex ), (float*) offsetof( cbengine::Vertex, vertexBoneWeights ) );
Lastly, make a call to DrawArrays
sharedRenderer->drawArrays( drawPrim, 0, verts.size() );
This is a very quick example of how to accomplish what you want. Other things to keep in mind are winding order for culling, enabling/disabling textures, and custom vertex attrib data you may want to send to your shaders. You may not want to include the Bone Weights and Bone Indexes vectors if your engine does not support skeletal animation.
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.
I've been trying to figure this out for a while, but I'm failing. I need to draw a cube, and then add a border around it. The cube works fine, and I got the border to draw, but there's always an extra line sticking in. I use the GL_ARRAY_BUFFER to store data and switch from GL_TRIANGLES (to draw the cube itself) to GL_LINES (to draw the outline borders). Each offset in the buffer has its own set of vertices.
My code for the display function (GLUT):
// cubeLen = number of cube's vertices in buffer
// sidesLen = number of side vertices in buffer
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glDrawArrays(GL_TRIANGLES, 0, cubeLen);
glDrawArrays(GL_LINES, cubeLen, cubeLen + sidesLen);
glutSwapBuffers();
My code to set up the buffers:
GLuint buffer;
glGenBuffers( 1, &buffer );
glBindBuffer( GL_ARRAY_BUFFER, buffer );
glBufferData( GL_ARRAY_BUFFER, sizeof(points) + sizeof(colors)
+ sizeof(points2) + sizeof(colors2),
NULL, GL_STATIC_DRAW );
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(points), points);
glBufferSubData(GL_ARRAY_BUFFER, sizeof(points), sizeof(colors), colors);
glBufferSubData(GL_ARRAY_BUFFER, sizeof(points) + sizeof(colors),
sizeof(points2), points2);
glBufferSubData(GL_ARRAY_BUFFER, sizeof(points) + sizeof(colors) + sizeof(points2),
sizeof(colors2), colors2);
I use 12 triangles (3 vertices each) for each side of the cube, and 12 lines (24 vertices) to cover all of the edges. The cube and edges are in sycn sitting at the center of the screen (centered at 0,0,0). The extra unwanted line (which appears to stretch from the center-left 3D position to the center-front 3D position) to comes in even if I disable drawing the cube in the display function. It does, however, go away when I do not set up vertices for the cube. Any ideas why this might be happening? Thanks for any and all help.
The extra line was a misplaced index to the buffer when it called the display function. Basically, it tried to display the color data instead of the actual vertex data.
I'm having an issue when first rendering a vertexbuffer with a program,
and then rendering a different vertexbuffer without program.
for the first buffer, when a program is enabled, i use code similar to:
glBindBuffer( GL_ARRAY_BUFFER, m_id );
GLint location = glGetAttribLocation( pID, "position" );
glEnableVertexAttribArray( location );
glVertexAttribPointer( location, 3, GL_FLOAT, GL_FALSE, 3 * sizeof( GLfloat ), 0 );
glDrawArrays( m_mode, 0, m_numVertices );
for the second, without program:
glBindBuffer( GL_ARRAY_BUFFER, m_id );
glEnableClientState( GL_VERTEX_ARRAY );
glVertexPointer( 3, GL_FLOAT, 3 * sizeof( GLfloat ), 0 );
glDrawArrays( m_mode, 0, m_numVertices );
both codepaths work fine individually, but when done in the order
"with program"->"without program", the second seems to use the buffer of the first,
and in the order "without program"->"with program", the first is not drawn (in the second iteration).
now this suggests to me that I'm missing some state change done by the glEnableVertexAttribArray block, but I don't understand what state change is causing the problems.
ps the reason I'm rendering with and without program is that in the scenegraph lib im using you can turn programs on or off per node.
Try adding
glDisableVertexAttribArray( location ); // location of "position"
before switching to fixed function rendering.