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)
- Using
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 glDraw*BaseInstance
.
Keep in mind that various instancing features have been added to OpenGL at different times:
- OpenGL 3.1
ARB_draw_instanced
and ARB_uniform_buffer_object
become core, allowing basic instanced rendering using gl_InstanceID
.
- OpenGL 3.3
ARB_instanced_arrays
becomes core, allowing for instanced vertex attributes through glVertexAttribDivisor
.
- 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 ARB_uniform_buffer_object
.
- OpenGL 4.5
ARB_direct_state_access
becomes core, including glVertexArrayBindingDivisor
, the DSA version of glVertexBindingDivisor
.
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.