Possible to store different vertex attributes and indices in same VBO? - c++

(Speaking of OpenGL 3.3) Is there a way to store different vertex attributes in the same VBO? I don't mean interleaved with "stride", I mean for example positions at the beginning of the VBO and texture coordinates at the end of the VBO.
If yes, then is it also true for indices? Can I store vertex indices and vertex attributes in the same VBO and bind it for DrawElements type of draw calls?
Thanks!

Yes, no need for interleaved data.
The last parameter of the gl-command glVertexAttribPointer() "Specifies a offset of the first component of the first generic vertex attribute in the array in the data store of the buffer currently bound to the GL_ARRAY_BUFFER target. The initial value is 0."
Just compute that offset on your own and pass it to the command.
Can I store vertex indices and vertex attributes in the same VBO and
bind it for DrawElements type of draw calls?
If you use different glVertexAttribPointer or different glDrawxx there's no problem.
What you can't do is reading vertices and indices at the same if they have different type (float vs integer) and stride.

Related

Disambiguate "vertex" in "vertex shader"

https://www.khronos.org/opengl/wiki/Vertex_Shader says that "The vertex shader will be executed roughly once for every vertex in the stream."
If we are rendering a cube, vertex could refer to the 8 vertexes of the entire shape (meaning One). Or, it could refer to the 24 vertexes of the 6 squares with 4 corners each (meaning Two).
As I understand it, if a cube is being rendered, the 8 corners of the cube have to be converted into the coordinate system of the viewer. But also there are texture coordinates that have to be calculated based on the individual textures associate with each face of the cube.
So if "vertex" is intended by meaning One, then why are textures being supplied to a shader which is a per face concept? Or if "vertexes" are being fed to the shader by meaning two, does that mean that the coordinate transforms and projections are all being done redundantly? Or is something else going on? These guides seem to have an allergy to actually saying what is going on.
The page on Vertex Specification could be a bit more clear on this, but a vertex is just a single index in the set of vertex arrays as requested by a rendering operation.
That is, you render some number of vertices from your vertex arrays. You could be specifying these vertices as a range of indices from a given start index to an end index (glDrawArrays), or you could specify a set of indices in order to use (glDrawElements). Regardless of how you do it, you get one vertex for each datum specified by your rendering command. If you render 10 indices with indexed rendering, you get 10 vertices.
Each vertex is composed of data fetched from the active vertex arrays in the currently bound VAO. Given the index for that vertex, a value is fetched from each active array at that index. Each individual array feeds a vertex attribute, which is passed to the vertex shader.
A vertex shader operates on the attributes of a vertex (passed as in qualified variables).
The relationship between a "vertex" and your geometry's vertices is entirely up to you. Vertices usually include positions as part of their vertex attributes, but they usually also include other stuff. The only limitation is that the value fetched for each attribute of a particular vertex always uses the same vertex index.
How you live within those rules is up to you and your data.

Can I set VAO before VBO in OpenGL?

I have a Sphere class that generate the VBO for creating given input radius and some more parameters.
Each Sphere VBO share the same memory layout (let's say vertex indice 0 = vertices, 1 = colors).
I may getting wrong, but if a understand correctly, state is what VAO store. But I don't know if VAO reminds which VBO was bound or use the currently bound VBO. But I think it use the VBO bound when modifying it (so it imply that reconfiguring the VAO for each Sphere render)
Question #1
Is it possible to store on VAO for all of the spheres? Sharing one VAO for multiple VBO.
Question #2
Can we set up the VAO independently from the VBO ? I wanna say, before even creating the VBO and without VBO bound, for example in a static function before even creating Spheres.
Question #3
This question may have non sens and be case-specific, but should I use one VAO and one VBO for each Sphere or share one VAO for all the Spheres (if it's possible) ?
Using the separate attribute format API, it is easy to set up a VAO independently from any particular set of source buffer objects. The vertex format information (component type, count, etc) can all be established via glVertexAttribFormat without a buffer object. You can even set up the relationship between attribute indices and buffer binding points, so that you can read interleaved attributes from a single buffer binding. All without ever binding a buffer object.
Now at the end of the data, you will have to attach buffer objects to the VAO when it comes time to render (via glBindVertexBuffer(s)). And the VAO will store the buffers it was last set with. But you should essentially ignore this. Treat a VAO as if it were just the vertex format state, with buffer binding being something that you do right before you render with it.
And yes, having one VAO and multiple potential buffers that get read with that vertex format (or better yet, just one buffer with multiple mesh data in it that all share the same vertex format, with mesh selection being done via the baseVertex parameter of glDrawElementsBaseVertex) is the right way to go.
All that being said, you also should remember that all spheres are the same mesh. They may appear in different locations with different sizes, but that's just a matter of providing a different transform of a unit sphere. The only reason to use more than one sphere mesh is if you need different resolutions of spheres (more polygons vs. fewer).

OpenGL How Many VAOs

I am writing an OpenGL3+ application and have some confusion about the use of VAOs. Right now I just have one VAO, a normalised quad set around the origin. This single VAO contains 3 VBOs; one for positions, one for surface normals, and one GL_ELEMENT_ARRAY_BUFFER for indexing (so I can store just 4 vertices, rather than 6).
I have set up some helper methods to draw objects to the scene, such as drawCube() which takes position and rotation values and follows the procedure;
Bind the quad VAO.
Per cube face:
Create a model matrix that represents this face.
Upload the model matrix to the uniform mat4 model vertex shader variable.
Call glDrawElements() to draw the quad into the position for this face.
I have just set about the task of adding per-cube colors and realised that I can't add my color VBO to the single VAO as it will change with each cube, and this doesn't feel right.
I have just read the question; OpenGL VAO best practices, which tells me that my approach is wrong, and that I should use more VAOs to save the work of setting the whole scene up every time.
How many VAOs should be used? Clearly my approach of having 1 is not optimal, should there be a VAO for every static surface in the scene? What about ones that move?
I am writing to a uniform variable for each vertex, is that correct? I read that uniform shader variables should not change mid-frame, if I am able to write different values to my uniform variable, how do uniforms differ from simple in variables in a vertex shader?
Clearly my approach of having 1 is not optimal, should there be a VAO for every static surface in the scene?
Absolutely not. Switching VAOs is costly. If you allocate one VAO per object in your scene, you need to switch the VAO before rendering such objects. Scale that up to a few hundred or thousand objects currently visible and you get just as much VAO changes. The questions is, if you have multiple objects which share a common memory layout, i.e. sizes/types/normalization/strides of elements are the same, why would you want to define multiple VAOs that all store the same information? You control the offset where you want to start pulling vertex attributes from directly with a corresponding draw call.
For non-indexed geometry this is trivial, since you provide a first (or an array of offsets in the multi-draw case) argument to gl[Multi]DrawArrays*() which defines the offset into the associated ARRAY_BUFFER's data store.
For indexed geometry, and if you store indices for multiple objects in a single ELEMENT_ARRAY_BUFFER, you can use gl[Multi]DrawElementsBaseVertex to provide a constant offset for indices or manually offset your indices by adding a constant offset before uploading them to the buffer object.
Being able to provide offsets into a buffer store also implies that you can store multiple distinct objects in a single ARRAY_BUFFER and corresponding indices in a single ELEMENT_ARRAY_BUFFER. However, how large buffer objects should be depends on your hardware and vendors differ in their recommendations.
I am writing to a uniform variable for each vertex, is that correct? I read that uniform shader variables should not change mid-frame, if I am able to write different values to my uniform variable, how do uniforms differ from simple in variables in a vertex shader?
First of all, a uniforms and shader input/output variables declared as in/out differ in various instances:
input/output variables define an interface between shader stages, i.e. output variables in one shader stage are backed by a corresponding and equally named input variable in the following stage. A uniform is available in all stages if declared with the same name and is constant until changed by the application.
input variables inside a vertex shader are filled from an ARRAY_BUFFER. Uniforms inside a uniform block are backed a UNIFORM_BUFFER.
input variables can also be written directly using the glVertexAttrib*() family of functions. single uniforms are written using the glUniform*() family of functions.
the values of uniforms are program state. the values of input variables are not.
The semantic difference should also be obvious: uniforms, as their name suggests, are usually constant among a set of primitives, whereas input variables usually change per vertex or fragment (due to interpolation).
EDIT: To clarify and to factor in Nicol Bolas' remark: Uniforms cannot be changed by the application for a set of vertices submitted by a single draw call, neither can vertex attributes by calling glVertexAttrib*(). Vertex shader inputs backed by a buffer objects will change either once per vertex or at some specific rate set by glVertexAttribDivisor.
EDIT2: To clarify how a VAO can theoretically store multiple layouts, you can simply define multiple arrays with different indices but equal semantics. For instance,
glVertexAttribPointer(0, 4, ....);
and
glVertexAttribPointer(1, 3, ....);
could define two arrays with indices 0 and 1, component sized 3 and 4 and both refer to position attributes of vertices. However, depending on what you want to render, you can bind a hypothetical vertex shader input
// if you have GL_ARB_explicit_attrib_location or GL3.3 available, use explicit
// locations
/*layout(location = 0)*/ in vec4 Position;
or
/*layout(location = 1)*/ in vec3 Position;
to either index 0 or 1 explicitly or glBindAttribLocation() and still use the same VAO. AFAIK, the spec says nothing about what happens if an attribute is enabled but not sourced by the current shader but I suspect implementation to simply ignore the attribute in that case.
Whether you source the data for said attributes from the same or a different buffer object is another question but of course possible.
Personally I tend to use one VBO and VAO per layout, i.e. if my data is made up of an equal number of attributes with the same properties, I put them into a single VBO and a single VAO.
In general: You can experiment with this stuff a lot. Do it!

OpenGL - glVertexAttribPointer with multiple VBOs and VAOs using the same shader

I have multiple VBOs and matching VAOs set up in my rendering engine. I am a bit confused about using glVertexAttribPointer. I have set it and it renders fine but I am curious if I am using one shader (a basic diffuse) with all of these different objects, do I set glVertexAttribPointer each time I create a VAO. I guess what's throwing me is I am trying to figure out if my setting an attribute pointer, is that set in the shader or the vertex array object. I assume it's the vertex array object but am hoping for some clarification.
Vertex attribute pointers are per vertex array object (VAO). The OpenGL 4.3 specification on page 318 in the description of glGetVertexAttribPointerv specifies: The value returned is queried from the currently bound vertex array object.

OpenGL - Associate Texture Coordinates Array With Index Array Rather Than Vertex Array?

Whenever we use an index array to render textured polygons with glDraw*Elements*, we can provide an array of vertices and an array of texture coordinates. Then each index in the index array refers to a vertex at some position in the vertex array and the corresponding texture coordinate at the same position in the texture array. Now, if for instance several separate primitives (like QUADS) share one vertex, but require different texture coordinates for that vertex, we have to duplicate that vertex in our array as many times as we have different texture coordinates for it. Therefore, it would be much more convenient if the texture coordinate array could be associated with the positions in the index array. That way no vertex duplication would be necessary to associate one specific vertex with different texture coordinates.
Is this possible? If yes, what syntax to use?
No. Not in a simple way.
You could use buffer textures and shader logic to implement it. But there is no simple API to make attributes index the way you want. All attributes are sampled from the same index (except when instanced array divisors are used, but that won't help you either).
Note that doing this will be a memory/performance tradeoff. Using buffer textures to access vertex data will take up less memory, but it will be significantly slower and more limiting than just using regular attributes. You won't have access to normalized vertex attributes, so compressing the vertex data will require explicit shader logic. And accessing buffer textures is just slower overall.
You should only do this if memory is at a premium.
Now, if for instance several separate primitives (like QUADS) share one vertex, but require different texture coordinates for that vertex, we have to duplicate that vertex in our array as many times as we have different texture coordinates for it.
If the texture coordinates differ on primitives sharing a vertex position, then the vertices at a whole are not shared! A vertex is a single vector consisting of
position
normal
texture coordinate(s)
other attributes
You alter any of these, you end up with a different vertex. Because of that vertex sharing does not the way you thought.
You can duplicate the vertices so that 1 has 1 texture coord & the other has the other. The only downfall of that is if you need to morph the surface - you may move 1 vertex but not both. Of course it is possible to do it "imperatively" - ie when you just run thru a loop & use different texture coord as you go - but that would not be VBO & much slower