GLM is a header only library, there is nothing to build to use it which increases its cross platform capabilities.
To use GLM, a programmer only has to include <glm/glm.hpp>. This provides all the GLSL features implemented by GLM.
GLM makes heavy usages of C++ templates. This design may significantly increase the compile time for files that use GLM. Precompiled headers are recommended to avoid this issue.
#include <glm/glm.hpp> int foo() { glm::vec4 Position = glm::vec4(glm::vec3(0.0), 1.0); glm::mat4 Model = glm::mat4(1.0); Model[4] = glm::vec4(1.0, 1.0, 0.0, 1.0); glm::vec4 Transformed = Model * Position; return 0; }
GLM is arranged in 2 distinct segments. These are the GLM features based on the GLSL specification and a set of extensions. Some extensions are stable and backward compatible (GTC Extensions (Stable) GTC VIRTREV Extensions VIRTREV) but some are experimental (GTX Extensions (Experimental) GTX) which means that they are not guarantee to be backward compatible from version to version.
The GLM represents only what GLSL's core provides in terms of types and functions (to the best of GLM's ability to replicate them). All that is needed to use the core is to include <glm/glm.hpp>
.
GTC extensions are functions and types that add onto the core. These are considered reasonably stable, with their APIs not changing much between versions. Each core extension is included with a separated header file include. All of the core extensions are in the "glm/gtc" directory.
GTX extensions are functions and types that add onto the core. Unlike GTC extensions, their APIs are not considered particularly stable, which is why they are marked "experimental". Like GTC extensions, each experimental extension is included with a separate header file.
All the extensions can be included at once by default by including <glm/ext.hpp>
but this is not recommanded as it will reduce compilation speed for many unused features.
All of GLM is defined as direct children of the glm namespace, including extensions.
To use a particular extension, simply include the extension header file. All extension features are added to the glm namespace automatically.
#include <glm/glm.hpp> #include <glm/gtc/matrix_transform.hpp> int foo() { glm::vec4 Position = glm::vec4(glm::vec3(0.0f), 1.0f); glm::mat4 Model = glm::translate( glm::mat4(1.0f), glm::vec3(1.0f)); glm::vec4 Transformed = Model * Position; return 0; }
When <glm/glm.hpp> is included, GLM provides all the GLSL features it implements in C++.
When an extension is included, all the dependent extensions will be included as well. All the extensions depend on GLM core. (<glm/glm.hpp>)
There is no dependence with external libraries or external headers like gl.h, gl3.h, glu.h or windows.h. However, if <boost/static_assert.hpp> is included, Boost static assert will be used throughout GLM code to provide compiled time errors.
It is often useful to get a vector type as an array of its base type. For example, the OpenGL function glUniform3fv()
takes an array instead of 3 individual values. If the vector and matrix types were simple arrays, then one could pass them to the function like so: glUniform3fv(loc, 1, glm::vec3(0))
. However, this is not the case; the vector and matrix types are C++ classes, not arrays.
Instead, GLM provides a mechanism to get the content of a vector or matrix as an array pointer. The GLM_GTC_type_ptr: Memory layout access. extension provides this ability.
#include <glm/glm.hpp> #include <glm/gtc/type_ptr.hpp> void BindUniforms(GLuint uniVec, GLuint uniMat) { glm::vec4 v(0.0f); glm::mat4 m(1.0f); ... glUniform3fv(uniVec, 1, glm::value_ptr(v)); glUniformMatrix4fv(uniMat, 1, GL_FALSE, glm::value_ptr(m)); }
Notice that all matrix types are column-major rather than row-major. Hence the need to pass GL_FALSE to glUniformMatrix4fv.
Alternatively, the first element of the type can be dereferenced.
#include <glm/glm.hpp> void BindUniforms(GLuint uniVec, GLuint uniMat) { glm::vec4 v(0.0f); glm::mat4 m(1.0f); ... glUniform3fv(uniVec, 1, glm::value_ptr(&v[0])); glUniformMatrix4fv(uniMat, 1, GL_FALSE, &m[0][0]); }
This method requires dereferencing the very first basic type of the object, not merely the first element. The [] operator on the matrix type returns a column vector; one must then access the first element of that column vector to get a pointer to the basic type.