Chapter 3: OpenTK.Math

To help you write cleaner code, OpenTK defines commonly used vectors, quaternions and matrices to extend the standard scalar types. They are generally nicer to handle than the arrays which the C API expects.

For example: OpenTK allows you to set the parameters of GL.Color() in various ways, the color cyan is used in this case.

GL.Color( 0.0f, 1.0f, 1.0f );
Vector3 MyColor = new Vector3( 0.0f, 1.0f, 1.0f );
GL.Color( MyColor );
// requires the System.Drawing library
GL.Color( Color.Cyan );

Function overloads like this can be found all over OpenTK.Graphics and OpenTK.Audio, where applicable.

Everything listed below is type-safe, code using these types will work across all supported platforms.



Row-Major Matrices

These are all value types (struct), not reference types. The implications of this can be read here.


For symmetry with established types, all OpenTK.Math types can be cast and allow serialization.

Vector2d TexCoord = new Vector2d( 0.2, 0.5 );
Vector2h HalfTexCoord = (Vector2h)TexCoord;
Vector3h Normal = (Vector3h)Vector3.UnitX;

Instance and Static Methods

The exact methods for each struct would be too numberous to list here, the function reference and inline documentation serve that purpose. It might not be obvious that some functionality is only available for instances of the structs, while others are static.

Vector3 Normal = Vector3.UnitX;
Vector4 TransformedVector = Vector4.Transform( Vector4.UnitX, Matrix4.Identity );


The new half-precision floating-point type in OpenTK.Math is specifically designed for computer graphics. It is commonly used to reduce the memory footprint of floating-point textures, which can become huge at high resolutions. It is also useful for Vertex attributes, because it can help your vertex struct to stay within the 16 or 32 Byte boundary, which processors like.

Internally the 16 Bit are represented similar to IEEE floating-point numbers:

  • 1 Sign Bit.
  • 5 Exponent Bits.
  • 10 Mantissa Bits. This is sometimes called the Significand, but called Mantissa in all OpenTK documentation.

It is important to understand that this type is a pure container to transfer data to or from the GPU, it does not support arithmetic operations. So if you want to use Half for Texture Coordinates or Normals, you have to perform any calculations with it in single- or double-precision first and then cast the final result to half-precision.

When using the Half type you should be aware of its poor precision:

  • Casting Math.PI to Half will result in 3.1406...
  • Numbers above 2048 and below -2048 will be rounded to the closest representable number.
  • The further away the value of the floating-point number gets from 1.0, the worse the Epsilon gets. Try to stay within [0.0 .. 1.0] range for best accuracy.