5. Drawing

In order to tell OpenGL to draw primitives for us, there's basically two ways to go:

1. Immediate Mode, as in specifying every single Vertex manually.
2. Vertex Buffers (or Vertex Arrays), drawing a whole Mesh with a single Command.

In order for all GL.Draw*-Functions to output geometric Primitives, EnableCap.VertexArray must be enabled first.

  1. Immediate Mode
    Hereby every single Vertex we wish to draw has to be issued manually.

    // GL.DrawArrays behaviour
    GL.Begin( BeginMode.Points );
    for ( uint i = 0; i < Vertices.Length; i++ )
    {
       GL.TexCoord2( Vertices[ i ].TexCoord );
       GL.Normal3( Vertices[ i ].Normal );
       GL.Vertex3( Vertices[ i ].Position );
    }
    GL.End( );
     
    // GL.DrawElements behaviour
    GL.Begin( BeginMode.Points );
    for ( uint i = 0; i < Indices.Length; i++ )
    {
       GL.TexCoord2( Vertices[ Indices[ i ] ].TexCoord );
       GL.Normal3( Vertices[ Indices[ i ] ].Normal );
       GL.Vertex3( Vertices[ Indices[ i ] ].Position );
    }
    GL.End( );
  2. GL.DrawArrays( BeginMode, int First, int Length )
    This Command is used together with Vertex Arrays or Vertex Buffer Objects, see setting Attribute Pointers. This line will automatically draw all Vertex contained in Vertices in order of appearance in the Array.

    GL.DrawArrays( BeginMode.Points, 0, Vertices.Length );
  3. GL.DrawElements( BeginMode, int Length, DrawElementsType, object )
    Like DrawArrays this Command is used together with Vertex Arrays or VBO. It uses an unsigned Array (byte, ushort, uint) to Index the Vertex Array. This is particularly useful for 3D Models where the Triangles describing the surface share Edges and Vertices.

    GL.DrawElements( BeginMode.TriangleStrip, Indices.Length, DrawElementsType.UnsignedInt, Indices );
  4. GL.DrawRangeElements( BeginMode, int Start, int End, int Count, DrawElementsType, object )
    This function behaves largely like GL.DrawElements, with the change that you may specify a starting index rather than starting at 0.
    Start and End are the smallest and largest Array-Index into Indices. Count is the number of Elements to render.

    // behaviour equal to GL.DrawElements
    GL.DrawRangeElements( BeginMode.TriangleStrip, 0, Indices.Length-1, Indices.Length, DrawElementsType.UnsignedInt, Indices );
  5. GL.DrawArraysInstanced( BeginMode, int First, int Length, int primcount )
    This function is only available on DX10 hardware and basically behaves like this:

    for (int gl_InstanceID=0; gl_InstanceID < primcount; gl_InstanceID++ )
       GL.DrawArrays( BeginMode, First, Length );

    gl_InstanceID is a uniform variable available to the Vertex Shader, which (in conjunction with GL.UniformMatrix) can be used to assign each Instance drawn it's own unique Orientation Matrix.

  6. GL.DrawElementsInstanced( BeginMode, int Length, DrawElementsType, object, int primcount )
    This function is only available on DX10 hardware and internally unrolls into:

    for (int gl_InstanceID=0; gl_InstanceID < primcount; gl_InstanceID++ )
       GL.DrawElements( BeginMode, Length, DrawElementsType, Object );

    gl_InstanceID is a uniform variable available to the Vertex Shader, which (in conjunction with GL.UniformMatrix) can be used to assign each Instance drawn it's own unique orientation Matrix.

Extension References
http://www.opengl.org/registry/specs/EXT/draw_range_elements.txt
http://www.opengl.org/registry/specs/EXT/draw_instanced.txt
http://www.opengl.org/registry/specs/EXT/multi_draw_arrays.txt