3
\$\begingroup\$

I'm using glDrawArraysInstanced to draw multiple instances of a tree at different positions to generate a forest.

Is there a way to draw selected instances? For example: I got 100 trees with different attributes. Due to culling I only want to draw instance 3, 65, 89 and 95.

\$\endgroup\$

2 Answers 2

4
\$\begingroup\$

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.

\$\endgroup\$
2
\$\begingroup\$

I know this question was asked prior, but with OpenGL 4.6 you can now call glDrawArraysInstancedBaseInstance to do exactly what was asked.

Another option is with OpenGL 4.2 the ARB_base_instance extension was added for this as well.

So to draw tree 3, 65, 89 and 95 you could make 4 draw calls of size 1 instance and put the offsets for each

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .