Description

This sample demonstrates how instancing techniques can be used to speed up drawing operations for scenes that consist of many copies of the same object rendered with slight differences.

Screenshot

APIs Used

  • glDrawElementsInstanced (or glDrawElementsInstancedARB, or glDrawElementsInstancedNV)
  • glVertexAttribDivisor (or glVertexAttribDivisorARB, or glVertexAttribDivisorNV)
  • GL_ARB_instanced_arrays [optional]
  • GL_NV_draw_instanced [optional]

Shared User Interface

The Graphics samples all share a common app framework and certain user interface elements, centered around the "Tweakbar" panel on the left side of the screen which lets you interactively control certain variables in each sample.

To show and hide the Tweakbar, simply click or touch the triangular button positioned in the top-left of the view.

Technical Details

This sample demonstrates how instancing techniques can be used to speed up drawing operations for scenes that consist of many copies of the same object rendered with slight differences.

The key message here is if your scene is cpu/driver limited by the sheer volume of draw calls and/or uniform updates, using hardware instancing is the easiest way to overcome those performance bottlenecks.

Render Modes

There are two different visuals that can be rendered via the Render Mode UI, each with its own set of control variables per instance:

  1. Boxes

    Draws a 3D grid of textured and animated cubes. Each cube has the following unique per instance attributes:

    1. 3D Position
    2. Rotation around the Y axis
    3. Color shade into a palette of 6 shades
  2. Grass

    Draws a rectangular (2D) patch of grass blades. Each grass blade has the following unique per instance attributes:

    1. 2D Position
    2. Rotation around the Y axis
    3. Color index used to choose one of 6 color variations for the grass blades

Instancing Modes

The sample has three different, selectable Instancing Modes that show different techniques for rendering instances, each with different performance (from slowest to fastest):

  1. No Instancing

    Each instance of the object is drawn individually.

    1. Two calls to glUniform3fv to set the attributes for the current instance
    2. One call to glDrawElements to render the current instance
  2. Shader Instancing

    Objects are drawn in batches with each batch containing up to 100 instances.

    1. Two calls to glUniform3fv to set the attributes for the current batch of instances
    2. One call to glDrawElements to render the current batch of instance

    In order to support drawing 100 instances of the object the sample creates a vertex buffer object that contains the vertices of 100 copies of the object. The data for each vertex is extended to additionally contain an instance id. This id is then used to load per instance attributes from an array of uniform shaders variables to adjust position, rotation and color of each instance.

    Further on, in addition to the vertex buffer object, a buffer is created that contains the indices for the 100 copies of the original index buffer.

  3. Hardware Instancing

    Objects are drawn using just one call to glDrawElementsInstanced() (or if not available glDrawElementsInstancedARB() or glDrawElementsInstancedNV()).

    To setup this draw call additional per instance vertex attributes are setup by two calls to each glEnableVertexAttribArray, glVertexAttribPointer and glVertexAttribDivisorARB/NV. This setup does bring in per instance data as additional per vertex attributes to the vertex shader.