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.
Related
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.
In my shader I have an ssbo containing an array of structs.
layout(std430, binding = 14) readonly buffer Block {
Uniform uniform[];
};
Now I want to use glDrawArraysIndirect and I need to pass the index for the ssbo with each draw command.
I am using opengl version 4.5 and extension ARB_shader_draw parameters is not supported.
The additional problems are that I am using a triple buffer, so I need to add the offset to the current part of the buffer to the index and the draw commands will not necessarily be in the same order as the structs in the buffer are.
If there is no way to get around draw commands being in a different order I could reorder them, but I would avoid that if possible.
If there was an easy way to get around ARB_shader_draw_parameters's functionality... the functionality wouldn't need to exist.
The closest approximation to ARB_shader_draw_parameters is to use the base instance index in the draw indirect command. Each draw you generate would assign itself a base instance, and that index represents the index used to index into the array.
Of course, ARB_shader_draw_parameters also provides access to the gl_BaseInstanceARB value, which is the base instance field from the draw command. It provides this because gl_InstanceID is not affected by the base instance. Only the value fetched from vertex shader instanced arrays is affected by the base instance.
So in order to use the base instance, you have to have an instance array which is just a linearly increasing series of integers. That value would be the base instance index you need.
And since you're not able to use gl_DrawIDARB, such a base instance value would not be guaranteed to dynamically uniform. So you cannot use the index, or any expressions derived from it, to do the following, among other things:
Index into an array of samplers or other opaque types.
Index into an array of interface blocks (not arrays within a block. An array of blocks themselves)
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 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.
If I have two different primitive types which are drawn dynamically according to user input, should I use 2 separate VBOs or is there a way of using one and of somehow identifying where the different primitive vertices begin and end?
The primitive types are triangle strips and points
Either method works. If using a VBO the data parameter of the gl…Pointer functions is interpreted as a numeric byte offset into the VBO. It's perfectly possible to put seveal batches of vertex attributes into a single VBO and point OpenGL to the sections within the VBO by their offsets.
So before each glDraw… call use the right gl…Pointer calls to set the right offsets. Or even better yet (if supported, i.e. you've got a new enough OpenGL version): Use Vertex Array Objects to encapsulate whole set of gl…Pointer settings into one abstract object that can be bound by a single OpenGL call.