So I have one huge VBO where all my models are stored, and a bunch of draw calls ready to submit to glMultiDrawArraysIndirect.
I also have a uniform block full of matrices so ship A goes to position A, ship B goes to position B, etc.
My question is - how does one make glsl aware which draw call is which? I tried changing the baseInstance variable but that doesn't seem to affect gl_InstanceID, which also starts at 0 for every draw call. After reading further on the khronos page, it seems like this variable won't affect anything.
So what is the proper way to include matrices so each draw call draws things at different positions?
If you have GL 4.6/ARB_shader_draw_parameters, then you have access to gl_DrawID, which is exactly what it sounds like: the zero-based index of the draw in any multi-draw command. It's also guaranteed to be dynamically uniform, so you can use it to access texture arrays (that is, sampler2D texarray[5];, not sampler2DArray texarray;) and other things that require dynamically uniform values.
If you don't... then your best bet is to create an instance array that contains indices, starting with 0. Your VS will have an input corresponding to this value. gl_InstanceID is not affected by the base instance, but the value fetched from an instance array is affected by it. So it will give you a proper index, at the cost of having a seemingly pointless value lying around.
Also, such a value will not be dynamically uniform. But that's usually not a big deal. It's only a problem if you want to access texture arrays.
Related
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.
I'm drawing a bunch of primitives (in my case lines) using the glMultiDrawArrays command. Each of these arrays (lines) have some additional attribute(s) specific to that array.
I would essentially like to pass these "array attributes" as separate uniforms specific to each array.
The two ways I can think of now is:
Draw each array (line) in separate draw calls and specify the attribute as a uniform.
Pass these attributes as vertex attributes. This would require me to store as many copies of the same value as I have vertices (I can have up to a 100k in the arrays). Not an option if I do have to store them!
Is there a smarter way of doing this in OpenGL?
Say I have n number of primitives to draw.
The glMultiDrawArrays command already requires me to pass along two arrays of size n. One array (lineStartIndex) of start indices and one array (lineCount) storing how many vertices each array contains .
To me it seems as it should be possible to specify vertex array attributes in a similar manner. E.g. a arrayAttributes vector of size n that could also be passed along with the draw call.
So instead of vertexAttribArray I'd like something like vertexArrayAttribArray ;)
Btw, I am only using one VAO and one VBO.
To me it seems as it should be possible to specify vertex array attributes in a similar manner.
Why? Vertex attributes are for things that change per-vertex; why would you expect to be able to use them for things that don't change per-vertex?
Well, you can (as I will explain), but I don't know why you think it should be possible.
The instancing and base instance feature can be (ab)used to provide a uniform-like value to a shader in a draw call.
You need to set up the attribute you want to provide "per-line" as an instanced array attribute. So you would use glVertexAttribDivisor with a value of 1 for that attribute.
Then, for each line, you would call glDrawArraysInstancedBaseInstance. Each call represents a single line, so you would provide an instance count of 1. But the base instance represents the index in the attribute array for that line's "per-line" value.
Yes, you're not using multi-draw. But OpenGL's draw call overhead is minimal; it's combining draw calls with state changes that get you. And you're not changing state between calls, so there's no problem.
However, if you're concerned about this minor overhead, and have access to multi-draw indirect functionality, you can always use that. Each line is a separate draw in the multi-draw call.
Of course, base instance requires GL 4.2 or ARB_base_instance. If you don't have access to hardware of this nature, then you're going to have to stick with the uniform variable method.
I'm working with OpenGL and am not totally happy with the standard method of passing values PER TRIANGLE (or in my case, quads) that need to make it to the fragment shader, i.e., assign them to each vertex of the primitive and pass them through the vertex shader to presumably be unnecessarily interpolated (unless using the "flat" directive) in the fragment shader (so in other words, non-varying per fragment).
Is there some way to store a value PER triangle (or quad) that needs to be accessed in the fragment shader in such a way that you don't need redundant copies of it per vertex? Is so, is this way better than the likely overhead of 3x (or 4x) the data moving code CPU side?
I am aware of using geometry shaders to spread the values out to new vertices, but I heard geometry shaders are terribly slow on non up to date hardware. Is this the case?
OpenGL fragment language supports the gl_PrimitiveID input variable, which will be the index of the primitive for the currently processed fragment (starting at 0 for each draw call). This can be used as an index into some data store which holds per-primitive data.
Depending on the amount of data that you will need per primitive, and the number of primitives in total, different options are available. For a small number of primitives, you could just set up a uniform array and index into that.
For a reasonably high number of primitives, I would suggest using a texture buffer object (TBO). This is basically an ordinary buffer object, which can be accessed read-only at random locations via the texelFetch GLSL operation. Note that TBOs are not really textures, they only reuse the existing texture object interface. Internally, it is still a data fetch from a buffer object, and it is very efficient with none of the overhead of the texture pipeline.
The only issue with this approach is that you cannot easily mix different data types. You have to define a base data type for your TBO, and every fetch will get you the data in that format. If you just need some floats/vectors per primitive, this is not a problem at all. If you e.g. need some ints and some floats per primitive, you could either use different TBOs, one for each type, or with modern GLSL (>=3.30), you could use an integer type for the TBO and reinterpret the integer bits as floating point with intBitsToFloat(), so you can get around that limitation, too.
You can use one element in the vertex array for rendering multiple vertices. It's called instanced vertex attributes.
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.
So, let say that I have two vertex buffers. One that describes the actual shape I want to draw, and the other one is able to influence the first one.
So, what I actually want to be able to do is something like this:
uniform VBO second_one;
void main()
{
for (int i = 0; i < size_of_array(second_one); ++i)
Do things with second_one[i] to alter the values
create the output informations
}
Things I might want to do can be gravity, that that each point in second_one tries to drag a bit the point closer to it and so on and then after the point is adjusted, apply the matrices to have its actual location.
I would be really surprise that it's possible, or something close to it. But the whole point is to be able to use a second VBO, or the make it as a uniform of type vec3 let say so I can access it.
For what you're wanting, you have three options.
An array of uniforms. GLSL lets you do uniform vec3 stuff[50];. And arrays in GLSL have a .length() method, so you can find out how big they are. Of course, there are limits to the number of uniforms you use, but you shouldn't need more than 20-30 of these. Anything more than that and you'll really feel the performance drain.
Uniform buffer objects. These can store a bit more data than non-block uniforms, but they still have limits. And the storage comes from a buffer object. But accesses to them are, depending on hardware, slightly slower than accesses to direct uniforms.
Buffer textures. This is a way to attach a buffer object to a texture. With this, you can access vast amounts of memory from within a shader. But be warned: they're not fast to access. If you can make due with one of the above methods, do so.
Note that #2 and #3 will only be found on hardware capable of supporting GL 3.x and above. So DX10-class hardware.