Multiple meshes or multiple objects in a single mesh? - c++

I'm trying to load multiple objects into a vbo in opengl. If I want to be able to move these objects independently should I use a mesh for each object or should I load all the objects to a single mesh?
Also in my code I have...
loc1 = glGetAttribLocation(shaderP, "vertex_position");
Now I understand that this gets the vertex positions in my current program but if I want to load another object I load the mesh and then how can I get the vertex positions again but for only that mesh?

The answer is, as often, "it depends". Having one "mesh" (i.e. one buffer) per object is arguably "cleaner" but it is also likely slower. One buffer per object will make you bind a different buffer much more often. Tiny vertex buffer objects (a few dozen vertices) are as bad as huge ones (gigabytes of data). You should try to find a "reasonable" thing in between
The as of version 3.2 readily available glDrawElementsBaseVertex (also exists as instanced version) will allow you to seamlessly draw several objects or pieces from one buffer without having to fiddle with renumbering indices, and without having to switch buffers.
You should preferrably (presuming OpenGL 3.3 availability) not use glGetAttribLocation at all, but assign the attribute to a location using the layout specifier. That way you know the location, you don't need to ask every time, and you don't have to worry that "weird, unexpected stuff" might happen.
If you can't do it in the shader, use glBindAttribLocation (available since version 2.0) instead. It is somewhat less comfortable, but does the same thing. You get to decide the location instead of asking for it and worrying that the compiler hopefully didn't change the order for two different shaders.

It's generally cleaner if you use different buffers for different objects.
According to:
http://www.opengl.org/sdk/docs/man/xhtml/glGetAttribLocation.xml
This will only returned the pointer to the location of the data. You use this to bind you vertex info to the program. When you render your other object you will bind to the vbo that stores the other vertices.

Related

What exactly is a VBO in OpenGL?

I am trying to understand the theory behind OpenGL and I'm studying VBOs at the moment.
This is what I understand so far: when we declare a series of vertices, let's say 3 vertices that form a triangle primitive, we basically store those nowhere, they're simply declared in code.
But, if we want to store them somewhere we can use a VBO that stores the definition of those vertices. And, through the same VBO we send all that vertex info to the Vertex Shader (which is a bunch of code). Now, the VBO is located in the GPU, so we are basically storing all that info on the GPU's memory when we call the VBO. Then the Vertex Shader, which is part of the Pipeline Rendering process, "comes" to the GPU's memory, "looks" into the VBO and retrieves all that info. In other words, the VBO stores the vertex data (triangle vertices) and sends it to the Vertex Shader.
So, VBO -> send info to -> Vertex Shader.
Is this correct? I'm asking to make sure if this is the correct interpretation, as I find myself drawing triangles on screen and sometimes letters made up of many triangles with a bunch of code and functions that I basically learned by memory but don't really understand what they do.
To break it down:
// here I declare the VBO
unsigned int VBO;
// we have 1 VBO, so we generate an ID for it, and that ID is: GL_ARRAY_BUFFER
glGenBuffers(1, &VBO)
// GL_ARRAY_BUFFER is the VBO's ID, which we are going to bind to the VBO itself
glBindBuffer(GL_ARRAY_BUFFER, VBO)
// bunch of info in here that basically says: I want to take the vertex data (the
// triangle that I declared as a float) and send it to the VBO's ID, which is
// GL_ARRAY_BUFFER, then I want to specify the size of the vertex
// data, the vertex data itself and the 'static draw' thingy
glBufferData(...).
After doing all that, the VBO now contains all the vertex data within. So we tell the VBO, ok now send it to the Vertex Shader.
And that's the start of the Pipeline, jsut the beginning.
Is this correct? (I haven't read what VAOs do yet, before I get to that I'd like to know if the way I deconstruct VBOs in my mind is the right way, or else I'm confused)
I think you are mixing up lots of different things and have several confusions, so I'm try to work through most of them in the order you brought them up:
when we declare a series of vertices, let's say 3 vertices that form a triangle primitive, we basically store those nowhere, they're simply declared in code.
No. If you store data "nowhere", then you don't have it. Also you are mixing up declaration, definiton and initialization of variables here. For vertex data (like all other forms of data), there are two basic strategies:
You store the data somewhere, typically in a file. Specifying it directly in source code just means that it is stored in some binary file, potentially the executable itself (or some shared library used by it)
You procedurally generate the data through some mathematical formula or more general by some algortihm
Methods 1. and 2 can of course be mixed, and usually, method 2 will need some parameters (which itself need to be stored somewhere, so the parameters are just case 1 again).
And, through the same VBO we send all that vertex info to the Vertex Shader (which is a bunch of code). Now, the VBO is located in the GPU, so we are basically storing all that info on the GPU's memory when we call the VBO.
OpenGL is actually just a specification which is completely agnostic about the existence of a GPU and the existence of VRAM. And as such, OpenGL uses the concept of buffer objects (BOs) as some continuous block of memory of a certain size which is completely managed by the GL implementation. You as the user can ask the GL to create or destroy such BOs, specify their size, and have complete control of the contents - you can put an MP3 file into a BO if you like (not that there would be a good use case for this).
The GL implementation on the other hand controls where this memory is actually allocated, and GL implementations for GPUs
which actually have dedicated video memory have the option to store a BO directly in VRAM. The hints like GL_STATIC_DRAW are there to help the GL implementation decide where to best put such a buffer (but that hint system is somewhat flawed, and better alternatives exist in modern GL, but I'm not going into that here). GL_STATIC_DRAW means you intent to specify the contents once and use the may times as the source of a drawing option - so the data won't change often (and certainly not on a per-frame basis or even more often), and it might be a very good idea to store it in VRAM if such a thing exists.
Then the Vertex Shader, which is part of the Pipeline Rendering process, "comes" to the GPU's memory, "looks" into the VBO and retrieves all that info.
I think one could put it that way, although some GPUs have a dedicated "vertex fetch" hardware stage which actually reads the vertex data which is then fed to the vertex shaders. But that's not a really important point - the vertex shader needs to access each vertex' data, and that means the GPU will read that memory (VRAM or system memory or whatever) at some point before or during the execution of a vertex shader.
In other words, the VBO stores the vertex data (triangle vertices)
Yes. A buffer object which is used as source for the vertex shader's per-vertex inputs ("vertex attributes") is called a vertex buffer object ("VBO"), so that just follows directly from the definition of the term.
and sends it to the Vertex Shader.
I wouldn't put it that way. A BO is just a block of memory, it doesn't actively do anything. It is just a passive element: it is being written to or being read from. That's all.
// here I declare the VBO
unsigned int VBO;
No, you are declaring (and defining) a variable in the context of your programming language, and this variable is later used to hold the name of a buffer object. And in the GL, object names are just positive integers (so 0 is reserved for the GL as "no such object" or "default object", depending on the object type).
// we have 1 VBO, so we generate an ID for it, and that ID is: GL_ARRAY_BUFFER
glGenBuffers(1, &VBO)
No. glGenBuffers(n,ptr) just generates names for n new buffer objects, so it will generate n previously unused buffer names (and mark them as used) and returns them by writing them to the array pointed to byptr. So in this case, it just creates one new buffer object name and stores it in your VBO variable.
GL_ARRAY_BUFFER has nothing to do with this.
// GL_ARRAY_BUFFER is the VBO's ID, which we are going to bind to the VBO itself
glBindBuffer(GL_ARRAY_BUFFER, VBO)
No, GL_ARRAY_BUFFER is not the VBO's ID, the value of yourVBO variable is the VBO's ID (name!).
GL_ARRAY_BUFFER is the binding target. OpenGL buffer objects can be used for different purposes, and using them as the source for vertex data is just one of them, and GL_ARRAY_BUFFER refers to that use case.
Note that classic OpenGL uses the concept of binding for two purposes:
bind-to-use: Whenever you issue a GL call which depends on some GL objects, the objects you want to work with have to be currently bound to some (specific, depending on the use case) binding target (not only buffer objects, but also textures and others).
bind-to_modify: Whenever you as the user want to modify the state of some object, you have to bind it first to some binding target, and all the object state modify functions don't directly take the name of the GL object to work on as parameter, but the binding target, and will affect the object which is currently bound at that target. (Modern GL also has direct state access which allows you to modify objects without having to bind them first, but I'm also not going into details about that here).
Binding a buffer object to some of the buffer object binding targets means that you can use that object for the purpose defined by the target. But note that a buffer object doesn't change because it is bound to a target. You can bind a buffer object to different targets even at the same time. A GL buffer object doesn't have a type. Calling a buffer a "VBO" usually just means that you intent to use it as GL_ARRAY_BUFFER, but the GL doesn't care. It does care about what is buffer is bound as GL_ARRAY_BUFFER at the time of the glVertexAttribPointer() call.
// bunch of info in here that basically says: I want to take the vertex data (the
// triangle that I declared as a float) and send it to the VBO's ID, which is
// GL_ARRAY_BUFFER, then I want to specify the size of the vertex
// data, the vertex data itself and the 'static draw' thingy
glBufferData(...).
Well, glBufferData just creates the actual data storage for a GL buffer object (that is, the real memory), meaning you specify the size of the buffer (and the usage hint I mentioned earlier where you tell the GL how you intend to use the memory), and it optionally allows you to initialize the buffer by copying data from your application's memory into the buffer object. It doesn't care about the actual data, and the types you use).
Since you use GL_ARRAY_BUFFER here as the target parameter, this operation will affect the BO which is currently bound as GL_ARRAY_BUFFER.
After doing all that, the VBO now contains all the vertex data within.
Basically, yes.
So we tell the VBO, ok now send it to the Vertex Shader.
No. The GL uses Vertex Array Objects (VAOs) which store for each vertex shader input attribute where to find the data (in which buffer object, at which offset inside the buffer object) and how to interpret this data (by specifying the data types).
Later during the the draw call, the GL will fetch the data from the relevant locations within the buffer objects, as you specified it in the VAO. If this memory access is triggered by the vertex shader itself, or if there is a dedicated vertex fetch stage which reads the data before and forwards it to the vertex shader - or if there is a GPU at all - is totally implementation-specific, and none of your concern.
And that's the start of the Pipeline, just the beginning.
Well, depends on how you look at things. In a traditional rasterizer-based rendering pipline, the "vertex fetch" is more or less the first stage, and vertex buffer objects will just hold the memory where to fetch the vertex data from (and VAOs telling it which buffer objects to use, and which actual locations, and how to interpret them).
It all boils down to this: when you work in "normal" programs, all what you have is the CPU, caches, registers, main memory, etc.
However, when you work with computer graphics (and other fields), you want to use a GPU because it is faster for that particular task. The GPU is an independent computer on its own, with its own processor, pipeline and main even memory.
This means your program needs to somehow transfer all the data to the other computer and tell the other computer what to do with it. This is no easy task, so OpenGL simplifies things for you. Thus they give you an abstraction (VBO) that represents a buffer of vertices in the GPU, among many other abstractions for other tasks. Then they give you functions to create that resource (glGenBuffers), fill it with data (glBufferData), "bind it" to work with it (glBindBuffer), etc.
Remember, it is all a simplification for your benefit. In truth, the details of how everything is performed underneath is way more complex. Having abstractions like VBOs for vertices or IBOs for indexes makes it easier to work with them.

glMultiDraw functions and gl_InstanceID

When I look at the documentation of glMultiDrawElementsIndirect (or in the Wiki) it says that a single call to glMultiDrawElementsIndirect is equivalent to repeatedly calling glDrawElementsIndirect (just with different parameters).
Does that mean that gl_InstanceID will reset for each of these "internal" calls? And if so, how am I able to tell all these calls apart in my vertex shader?
Background: I'm trying to draw all my different meshes all at once. But I need some way to know to which mesh the vertex, I'm processing in my vertex shader, belongs.
The documentation says "similarly to". "Equivalent" isn't the same thing. It also points to glDrawElementsInstancedBaseVertexBaseInstance, not glDrawElementsInstanced.
But yes, gl_InstanceId for any draw will start at zero, no matter what base instance you provide. That's how gl_InstanceId works, unfortunately.
Besides, that's not the question you want answered. You're not looking to ask which instance you're rendering, since each draw in the multi-draw can be rendering multiple instances. You're asking which draw in the multi-draw you are in. An instance ID isn't going to help.
And if so, how am I able to tell all these calls apart in my vertex shader?
Unless you have OpenGL 4.6 or ARB_shader_draw_parameters, you can't. Well, not directly.
That is, multidraw operations are expected to produce different results based on rendering from different parts of the current buffer objects, not based on computations in the shader. You're rendering with a different base vertex that selects different vertices from the arrays, or you're using different ranges of indices or whatever.
The typical pre-shader_draw_parameters solution would have been to use a unique base instance on each of the individual draws. Of course, since gl_InstanceId doesn't track the base instance (as previously stated), you would need to employ instanced arrays instead. So you'd get the mesh index from that.
Of course, 4.6/shader_draw_parameters gives you gl_DrawId, which just tells you what the index is within the multidraw command. It's also dynamically uniform, so you can use it to access arrays of opaque types in shaders.

Meaning of "Single Vertex Buffer"

I am trying to understand the meaning of a "performance tip" given in the GCW Zero OpenGL instructions:
always use vertex buffer objects (VBOs)
put vertices into one interleaved VBO, not multiple VBOs
Does this mean that I should put ALL MY OBJECTS into a single vertex buffer (and remember the start / finish index pertaining to each object). Or does it simply mean that each object should be in one vertex buffer (rather than a buffer for each attribute).
Is it normal to have multiple objects in the same vertex buffer?
Does this mean that I should put ALL MY OBJECTS into a single vertex
buffer (and remember the start / finish index pertaining to each
object)
Or does it simply mean that each object should be in one
vertex buffer (rather than a buffer for each attribute).
This "performance tip" says nothing about multiple objects. What it says is that you should put all the attributes into the same VBO, using interleaved attribute arrays. Which is likely to be the most cache efficient strategy, and a reasonable advice in the general case.
Putting multiple objects is also quite common, especially if they have only relatively few vertices. You can save a lot of state switches and ideally even draw calls that way. But it depends on the scene, of course. Combining things into the same VBO is most useful for static objects which are often drawn together.

OpenGL - Indexed Draws with glDrawElements

I have a couple questions about how OpenGL handles these drawing operations.
So lets say I pass OpenGL the pointer to my vertex array. Then I can call glDrawElements with an array of indexes. It will draw the requested shapes using those indexes in the vertex array correct?
After that glDrawElements call could I then do another glDawElements call with another set of indexes? Would it then draw the new index array using the original vertex array?
Does OpenGL keep my vertex data around for the next frame when I redo all of these calls? So the the next vertex pointer call would be a lot quicker?
Assuming the answer to the last three questions is yes, What if I want to do this on multiple vertex arrays every frame? I'm assuming doing this on any more than 1 vertex array would cause OpenGL to drop the last used array from graphics memory and start using the new one. But in my case the vertex arrays are never going to change. So what I want to know is does opengl keep my vertex arrays around in-case next time I send it vertex data it will be the same data? If not is there a way I can optimize this to allow something like this? Basically I want to draw procedurally between the vertexes using indicies without updating the vertex data, in order to reduce overhead and speed up complicated rendering that requires constant procedurally changing shapes that will always use the vertexes from the original vertex array. Is this possible or am I just fantasizing?
If I'm just fantasizing about my fourth question what are some good fast ways of drawing a whole lot of polygons each frame where only a few will change? Do I always have to pass in a totally new set of vertex data for even small changes? Does it already do this anyways when the vertex data doesn't change because I notice I cant really get around the vertex pointer call each frame.
Feel free to totally slam any logic errors I've made in my assertions. I'm trying to learn everything I can about how opengl works and it's entirely possible my current assumptions on how it works are all wrong.
1.So lets say I pass OpenGL the pointer to my vertex array. Then I can call glDrawElements with an array of indexes. It will draw the
requested shapes using those indexes in the vertex array correct?
Yes.
2.After that glDrawElements call could I then do another glDawElements
call with another set of indexes? Would it then draw the new index
array using the original vertex array?
Yes.
3.Does OpenGL keep my vertex data around for the next frame when I redo
all of these calls? So the the next vertex pointer call would be a lot
quicker?
Answering that is a bit more tricky than you might. The way you ask these questions makes me to assume that uou use client-side vertex arrays, that is, you have some arrays in your system memory and let your vertes pointers point directly to those. In that case, the answer is no. The GL cannot "cache" that data in any useful way. After the draw call is finished, it must assume that you might change the data, and it would have to compare every single bit to make sure you have not changed anything.
However, client side VAs are not the only way to have VAs in the GL - actually, they are completely outdated, deprecated since GL3.0 and been removed from modern versions of OpenGL. The modern way of doing thins is using Vertex Buffer Objects, which basically are buffers which are managed by the GL, but manipulated by the user. Buffer objects are just a chunk of memory, but you will need special GL calls to create them, read or write or change data and so on. And the buffer object might very well not be stored in system memory, but directly in VRAM, which is very useful for static data which is used over and over again. Have a look at the GL_ARB_vertex_buffer_object extension spec, which orignially introduced that feature in 2003 and became core in GL 1.5.
4.Assuming the answer to the last three questions is yes, What if I want
to do this on multiple vertex arrays every frame? I'm assuming doing
this on any more than 1 vertex array would cause OpenGL to drop the
last used array from graphics memory and start using the new one. But
in my case the vertex arrays are never going to change. So what I want
to know is does opengl keep my vertex arrays around in-case next time
I send it vertex data it will be the same data? If not is there a way
I can optimize this to allow something like this? Basically I want to
draw procedurally between the vertexes using indicies without updating
the vertex data, in order to reduce overhead and speed up complicated
rendering that requires constant procedurally changing shapes that
will always use the vertexes from the original vertex array. Is this
possible or am I just fantasizing?
VBOs are exactly what you are looking for, here.
5.If I'm just fantasizing about my fourth question what are some good
fast ways of drawing a whole lot of polygons each frame where only a
few will change? Do I always have to pass in a totally new set of
vertex data for even small changes? Does it already do this anyways
when the vertex data doesn't change because I notice I cant really get
around the vertex pointer call each frame.
You can also update just parts of a VBO. However, it might become inefficient if you have many small parts which are randomliy distributed in your buffer, it will be more efficient to update continous (sub-)regions. But that is a topic on it's own.
Yes
Yes
No. As soon as you create a Vertex Buffer Object (VBO) it will stay in the GPU memory. Otherwise vector data needs to be re-transferred (an old method of avoiding this was Display Lists). In both cases the performance of subsequent frames should stay similar (but much better with the VBO method): you can do the VBO creation and download before rendering the first frame.
The VBO was introduced to provide you exactly with this functionality. Just create several VBOs. Things get messy when you need more GPU memory than available though.
VBO is still the answer, and see Modifying only a specific element type of VBO buffer data?
It sounds like you should try something called Vertex Buffer Objects. It offers the same benefits as Vertex Arrays, but you can create multiple vertex buffers and store them in "named slots". This method has much better performance as data is stored directly in Graphic Card memory.
Here is a good tutorial in C++ to start with.

Should the same VAO be used with multiple programs?

Say we bind vertex attribute locations to the same values on two programs. Is it correct to use the same vertex array object to draw with these two programs?
Define "correct."
If two program objects use compatible attribute locations, then they use the same attribute locations. VAOs work off of attribute locations, so a VAO that works with one will work with another. So this will work.
In general, it is a matter of performance whether you actually take advantage of this. It's generally a good idea to avoid changing vertex array state, but it's not clear how important this is relative to other state changes. You're changing programs anyway, so not changing VAOs when you change programs will at worst be no slower and can lead to significant performance increases.
However, it is not clear how much work you should do to minimize vertex array state changes. If you can pack models into the same buffer objects with the same format, you can render all of them without VAO changing using functions like glDrawArrays or glDrawElementsBaseVertex.
I've tried using the same VAO with different shaders and I could see visual artifacts.
(The IDs of the attributes did match)
The solution was to use a new VAO for every single program.