There are two main ways to get instance data into a shader program:
- Setting the instance divisor for one or more vertex attributes (instead of advancing every vertex, it will advance every N instances)
gl_InstanceID or an instanced attribute to select part of an array of instance data stored in a uniform buffer, shader storage buffer, etc.
gl_InstanceID always starts at
0. Even if you use
glDraw*BaseInstance, the base instance offset only applies to instanced attributes.
Therefore, the only way I can see to do what you want is to store all your instance data in an array of structs in a buffer accessed through the vertex shader, and a list of instance IDs in another buffer, which is bound to an instanced vertex attribute.
If the specific instances you want to draw is dynamically changing, updating the instance ID buffer will likely cause more of a performance hit than instancing gains you over multiple draw calls (and if you're only drawing 4 instances, you might not get any gains anyway - instanced rendering works best with dozens to hundreds of instances). On the other hand if you have multiple sets of instances that might need to be drawn, but the specific instances are known beforehand, you can put multiple lists of instance IDs in the same buffer and select the first ID using
Keep in mind that various instancing features have been added to OpenGL at different times:
- OpenGL 3.1
ARB_uniform_buffer_object become core, allowing basic instanced rendering using
- OpenGL 3.3
ARB_instanced_arrays becomes core, allowing for instanced vertex attributes through
- OpenGL 4.2
ARB_base_instance makes instanced attributes more flexible.
ARB_transform_feedback_instanced allows for instanced drawing from transform feedback buffers.
- OpenGL 4.3
ARB_vertex_attrib_binding becomes core, adding
glVertexBindingDivisor, which works like
glVertexAttribDivisor but operates on any attributes that use a particular buffer binding index rather than just one attribute index. Also,
ARB_shader_storage_buffer_object, while not directly related to instancing, solves some issues with
- OpenGL 4.5
ARB_direct_state_access becomes core, including
glVertexArrayBindingDivisor, the DSA version of
On an side note, consider using
glDrawElements* instead of
glDrawArrays* if you're concerned about performance. In addition to usually reducing the size of your vertex data, it enables the GPU to use the Post Transform Cache.