You can use the ability of more advanced hardware to allow the use of multiple indices. This requires explicit shader code. It also requires that the shader know and understand the format of the data, so that it can process it correctly. Some of this description can be handled through uniforms, but be aware that in-shader logic will be done for every vertex. So building a shader specifically around a format would probably be more efficient.
The biggest problem you have is that each vertex's data in the array is oddly formatted. You can have mis-aligned shorts and so forth. So processing it requires extra care. To handle the 7-byte vertices as shown above, you would need to do this:
uniform usamplerBuffer vertexData; //Format is unsigned bytes.
uniform samplerBuffer positionArray;
uniform samplerBuffer normalArray;
uniform samplerBuffer texCoordArray;
uint ExtractShortFromVertex(in uint firstIndex)
{
uint highByte = texelFetch(vertexData, firstIndex);
uint lowByte = texelFetch(vertexData, firstIndex + 1);
return (highByte << 8) | lowByte;
}
void main()
{
uint baseIndex = gl_VertexID * 7;
uint matrixIndex = texelFetch(vertexData, baseIndex);
uint positionIndex = ExtractShortFromVertex(baseIndex + 1);
uint normalIndex = ExtractShortFromVertex(baseIndex + 3);
uint texCoordIndex = ExtractShortFromVertex(baseIndex + 5);
vec4 position = texelFetch(positionArray, positionIndex);
vec4 normal = texelFetch(normalArray, normalIndex);
vec4 texCoord = texelFetch(texCoordArray, texCoordIndex);
//Do your stuff
}
Obviously, if you have direct data in there, you're going to need specialized logic to extract it.
vertexData
is a buffer object (accessed as a buffer texture) which stores the GX data as you presented it. Of course, it should point only to the actual per-vertex data, not to the 90 0003
prefix. That you will still have to handle manually. So the CPU will still need fast access to the data, so that when it calls glDrawArrays
, it can pass the right primitive and draw count.
Note that the format for vertexData
is GL_R8UI
, since we need byte-wise access.
Dealing with "direct data" is more troublesome, since that requires converting a sequence of bytes into a complex type like a float or somesuch. But modern GLSL does have a number of functions that ought to be able to get that done.
It might be possible to use Compute Shaders to process certain aspects of each rendering command. The goal here would be to turn them into indirect rendering commands.
The problem is that, while indirect commands can have different vertex counts, what they cannot do is change uniform data, programs, or the primitive type. So there would be no way to build a sequence of indirect commands where the format changes between different commands. Not without the CPU knowing about it and issuing different draw call parameters based on it.
At which point, you may as well let the CPU just process the commands itself.