Problems understanding how to use indexing
-
Although you can have separate buffers for each attribute you can't have a separate index for each attribute. So if you have 3 vertices with vertex coord and a color you can lay them anyway you want, but you will only have one index buffer. The index in each buffer will need to match. Here are some examples (not all possibilities), assuming I(index in the index buffer), V(vertex coordinate) and C(vertex color):
@
//1. best performance:
index buffer: III
array buffer: VCVCVC//2. a little worse performance, but might be worth considering
//if you want to keep attributes separated
//you can map only part of the buffer and update coords and colors independently
index buffer: III
array buffer: VVVCCC//3. worst performance, I would recommend that only if there's
//absolutely no other way
index buffer: III
array buffer1: VVV
array buffer2: CCC
@
But there is no this:
@
index buffer for array buffer 1: III
array buffer 1: VVV
index buffer for array buffer 2: III
array buffer 2: CCC
@
[EDIT]: Well there kinda is this, but it requires UBOs and a higher OpenGL version, above what Qt classes wrap around.In pure OpenGL these methods would look something like this. I hope you can translate that into the Qt wrappers:
@
GLsizei vSize = //size of single vertex coord e.g. 3 * sizeof(float)
GLsizei cSize = //size of single color e.g. 3 * sizeof(float)//1.
GLsizei vcSize = vSize + cSize;
glEnableVertexAttrib(coordLocation);
glEnableVertexAttrib(colorLocation);
glBindBuffer(GL_ARRAY_BUFFER, vcvcvcBuffer);
glVertexAttribPointer(coordLocation, 3, GL_FLOAT, GL_FALSE, vcSize, 0);
glVertexAttribPointer(colorLocation, 3, GL_FLOAT, GL_FALSE, vcSize, vSize);//2.
GLsizei vvvSize = vSize * vertexCount;
glEnableVertexAttrib(coordLocation);
glEnableVertexAttrib(colorLocation);
glBindBuffer(GL_ARRAY_BUFFER, vvvcccBuffer);
glVertexAttribPointer(coordLocation, 3, GL_FLOAT, GL_FALSE, 0, 0);
glVertexAttribPointer(colorLocation, 3, GL_FLOAT, GL_FALSE, 0, vvvSize);//3.
glEnableVertexAttrib(coordLocation);
glEnableVertexAttrib(colorLocation);
glBindBuffer(GL_ARRAY_BUFFER, vvvBuffer);
glVertexAttribPointer(coordLocation, 3, GL_FLOAT, GL_FALSE, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, buffColor);
glVertexAttribPointer(colorLocation, 3, GL_FLOAT, GL_FALSE, 0, 0);
@Mind that there might be typos. I'm writing from memory.
-
Thanks a lot, I'll be using the first method you describe. This means that for each vertex I have a fixed color. It's not really a big deal for my project but I'm a little puzzled that I can't use different colors for the same coordinate. That means that drawing a rectangle like this is impossible (with indexing, that is):
-
bq. That means that drawing a rectangle like this is impossible (with indexing, that is)
Not at all! You just need to specify each vertex-color pair separately, so you'll have a total of 6 indices and some duplicated vertex coord data. It dismisses any benefits of indexing but it's possible.
Indexing is used to reduce data duplication, and when I say data I mean the whole vertex data, not single attributes of it. As such, the above rectangle is a pathological case for indexing, because there is no data duplication at all (at the vertex level, not single attribute level) and indexing is actually worse than non-indexed version, because you pay the extra for storing indices.
When choosing your storage layout you always need to consider your data - is it unique per vertex (as a whole or at attribute level), will it be updated dynamically and if so - how often, which attributes will be updated and will it happen at the same rate for all of them, will it be downloaded back to CPU side etc. All theses questions lead to very different data structures and drawing patterns. After that comes actual profiling of your implementation and the optimized end result is often quite different from what intuition would suggest when first tackling the problem.
-
I agree, indexing is not necessary at all for a rectangle as I posted, but consider drawing something like this:
!http://oi58.tinypic.com/2598gaf.jpg(Image)!
The middle coordinate is surely to be duplicated, but the color value must be different each time.
But if I have understood it correctly, indices cannot contain more than one value per instance. So a index cannot point to two separate VBOs? I think I'll have to study OpenGL a bit more to understand how indexing works
-
Yes, the type of data like in your picture is not gonna be well suited for indexing.
Indexing is best for continuous data like texturing large triangle mesh with a single texture as many vertices have identical data - vertex coord, texture coord, normal, bitangent etc.
bq. So an index cannot point to two separate VBOs
It can. See my example 3 and comment about performance. It's just gonna be the same single index in both VBOs (counting from offset specified with glVertexAttribPointer). What you can't have is a distinct index for each attribute.
So for example if you have VBO1: v0, v1, v2 and VBO2: c0, c1,c2
there's gonna be a single index buffer: 0,1,2 which will process data like this: (v0,c0), (v1,c1), (v2,c2).You can't have two index buffers like 0,1,2 and 2,2,2 that would produce vertex data like this: (v0,c2), (v1,c2), (v2,c2)
I'll repeat that you can achieve this with UBOs, but that's another topic.
-
I think I understand, but maybe we can move on to a specific example?
I'm now drawing the triangles with their corresponding colors using indexing, I'm reading a disparity map and a colored image to visualize disparity maps in 3D; "this":http://oi57.tinypic.com/30uy9u9.jpg is what it looks like.
Now I'd like to draw black lines on top of each triangle. How would you suggest I do this? Can I somehow override the color data of the buffer? Or do I have to set some uniform value in the shader so that everything I draw next will be black?
Please look at this pastebin: http://pastebin.com/eySDk8Vy
-
There are couple of ways to do it.
If what you have works and is good enough then it's ok. No need to complicate things. You just need to blend the second pass properly so that you won't be seeing Z-fighting artifacts.
One other simple solution would be to just use another shader that doesn't take any color inputs at all and just paints everything black and draw your lines with that (again, minding the blending).
If you want to get fancy you can even do everything in one pass with a shader that calculates fragment position inside the triangle and paints the ones near edge black. Some examples are "here":http://strattonbrazil.blogspot.com/2011/09/single-pass-wireframe-rendering_11.html and "here":http://codeflow.org/entries/2012/aug/02/easy-wireframe-display-with-barycentric-coordinates/
-
Yes it seems to be working pretty well, added a uniform vec3 variable called "position_offset" to avoid Z-fighting artifacts (now I even learned a new expression). I'm pretty happy with the result:
!http://oi60.tinypic.com/vo06s9.jpg(Image)!
I really appreciate all the help you've given me, thanks a million :) We'll be sure to add you to the credits section of our bachelor thesis
-
Looks good.
The offsetting is a little hard to handle if there's a large depth difference in the scene as too much offset will result in visual disparity near the camera and too little will not fix the z problems far away.
Another way to deal with this is to render the color and the outlines into separate textures without any offset (using FBOs) and then just blend them together in a final pass.