No it is not.
The input to the shader pipeline expects a "stream" of vertices. So say you're using DRAW_TRIANGLES
(or whatever it is) what actually happens is this:
- Create 3 buffers (these are your
varying
s) of sufficient size
- Fetch vertex (attributes) and put them in the input to the vertex shader
- Run the vertex shader
- Transfer varyings output into the 1st buffer
- Fetch vertex and put them in the input to the vertex shader
- Run the vertex shader
- Transfer the varyings output to the 2nd buffer
- Fetch vertex and put them in the input to the vertex shader
- Run the vertex shader
- Transfer the varyings output to the 3rd buffer
- Interpolate the varyings buffers over the resulting triangle and run the fragment shader for each "fragment" (pixel/sub-sampled pixel basically)
I've put the important bit, "fetch vertex" in bold because this could mean anything. OpenGL doesn't specify how this must actually be done (because of course it belongs to the implementation) but this is where indexed arrays come into play.
Buffers, arrays and indexed arrays
Buffers:
The most primitive form of storage is a Buffer
- this doesn't know what it stores, it is simply a chunk of bytes.
Arrays:
Next we have arrays, arrays are not actually blocks of memory. They contain 4 bits of information:
- Which
Buffer
they are an array on. (a BufferId
or Buffer*
perhaps)
- What data type they're supposed to be (eg 3 floats, 2 ints, 16 floats (for a 4x4 matrix)...)
- An offset (call this
o
)
- A step (call this
s
)
When you ask for the i
th member of an array you actually get Buffer[si+o] - to - Buffer[si+o+sizeof(data type)]
back. So if its floats, 4 bytes, you get these 4 bytes: Buffer[si+o]
, Buffer[si+o+1]
, Buffer[si+o+2]
and Buffer[si+o+3]
back
Indexed arrays:
This is an array of some integer data type (so it's a buffer + the array structure on top that returns numbers).
Vertex streams
If you're using arrays, NOT indexed ones the fetch vertex step looks something like this:
For each attribute:
attribute.array[i]
i++;
Or
For each attribute:
attribute.buffer[attribute.array.step*i+attribute.array.offset]
i++;
With indexed arrays it does this:
For each attribute:
attribute.array[Index[i]]
i++;
Or
For each attribute:
attribute.buffer[attribute.array.step*Index[i]+attribute.array.offset]
i++;
In some sort of pseudo code.
As you can see indexes are not "complex" enough to do anything more than provide a lookup table mapping vertices to the data they're supposed to have.
In the industry
Suppose you have vertex positions and normals, technically you can have buffers like this:
Buffer 1: xyzxyzxyz.....
Buffer 2: uvwuvwuvw.....
However this is bad because it means the implementation will (at some level) have to read something from buffer 1, then jump to buffer 2 and read some more, then back to buffer 1 and so forth and so forth. This is bad.
What you should do is something like:
Buffer 1: xyzuvwxyzuvwxyzuvw.....
This would just be a bigger step on the arrays. The implementation will likely optimise things like this so it just has to read it right away (with minimal transposing)
Indexing is bad as it can result in rather random reads at least with arrays it is predictable, so it is possible to do some hardware magic that can speedily read from multiple buffers, indexes however are not a simple ax+b
formula, they can literally be random.
as such unless the cardinality (number) of indexes differs hugely from the length of the array implementations often unpack the indexed array.
That is to say if you have an index of 3 million but only 12 vertices, it'll use the index. If you have 15k index and 15k vertices it will not and it'll just unpack it.
Final note
The usefulness of indexed arrays is limited by the fact that MOST of the time vertices in the same position will have different surface normals, consider for example a cube. Take any corner, that vertex will have 3 distinct normals. I think this is what you're trying to do. You've realised that they have the same position, but your data
can still vary.
glEnableVertexAttribArray()
andglVertexAttribPointer()
to create vertex attribute arrays. I can access them from the vertex shader using things likelayout(location=1) in vec3 color
andlayout(location=2) in int attrib
\$\endgroup\$