A common feature of shader languages like GLSL is components swizzling. This involves being able to select which components of a vector are used and in what order. For example, "variable.x", "variable.xxy", "variable.zxyy" are examples of swizzling.
This functionally turns out to be really complicated to implement in C++ using the exact GLSL conventions. GLM provides 2 implementions this feature.
The first implementation follows the GLSL convensions accurately. It uses macros to achieve this, which might generates name conflicts with system headers or third party libraries. Therefore, it is disabled by default. To enable this implementation, GLM_SWIZZLE must be defined before any inclusion of <glm/glm.hpp>.
#define GLM_SWIZZLE #include <glm/glm.hpp>
This implementation can be partially enabled by defining GLM_SWIZZLE_XYZW, GLM_SWIZZLE_RGBA or GLM_SWIZZLE_STQP. Each macro only enable a set of swizzling operators. For example we can only enable x,y,z,w and s,t,q,p operators using:
#define GLM_SWIZZLE_XYZW #define GLM_SWIZZLE_STQP #include <glm/glm.hpp>
A safer way to do swizzling is to use the <glm/gtc/swizzle.hpp> extension. This extension provides the GLSL functionality, but uses a different syntax for it. Moreover, the swizzle extension also provides dynamic swizzling.
Static swizzling is resovled at compile-time. The swizzle mask ".xzyy" is as fixed as the type of a particular variable. Dynamic swizzling is resolved at runtime via function calls. Dynamic swizzling is more flexible, since one can choose the swizzle mask at runtime, but it runs slower. This performance issue is enhanced when SIMD instructions are used.
#include <glm/glm.hpp> #include <glm/gtc/swizzle.hpp> void foo() { glm::vec4 ColorRGBA(1.0f, 0.5f, 0.0f, 1.0f); ... // Dynamic swizzling (at run time, more flexible) // l-value: glm::vec4 ColorBGRA1 = glm::swizzle(ColorRGBA, glm::B, glm::G, glm::R, glm::A); // r-value: glm::swizzle(ColorRGBA, glm::B, glm::G, glm::R, glm::A) = ColorRGBA; // Static swizzling (at build time, faster) // l-value: glm::vec4 ColorBGRA2 = glm::swizzle<glm::B, glm::G, glm::R, glm::A>(ColorRGBA); // r-value: glm::swizzle<glm::B, glm::G, glm::R, glm::A>(ColorRGBA) = ColorRGBA; }
GLM includes a notification system which can display some information at build time:
This system is disable by default. To enable this system, define GLM_MESSAGES before any inclusion of <glm/glm.hpp>.
#define GLM_MESSAGES #include <glm/glm.hpp>
GLM's functions are defined in headers, so they are defined with C++'s "inline" delcaration. This does not require the compiler to inline them, however. To force the compiler to inline the function, using whatever capabilities that the compiler provides to do so, GLM_FORCE_INLINE can be defined before any inclusion of <glm/glm.hpp>.
#define GLM_FORCE_INLINE #include <glm/glm.hpp>
GLM provides some SIMD optimizations based on compiler intrinsics. These optimizations will be automatically utilized based on the build environment. These optimizations are mainly available through the extensions GLM_GTX_simd_vec4: SIMD vec4 type and functions and GLM_GTX_simd_mat4: SIMD mat4 type and functions.
A programmer can restrict or force instruction sets used for these optimizations using GLM_FORCE_SSE2 or GLM_FORCE_AVX.
A programmer can discard the use of intrinsics by defining GLM_FORCE_PURE before any inclusion of <glm/glm.hpp>. If GLM_FORCE_PURE is defined, then including a SIMD extension will generate a build error.
#define GLM_FORCE_PURE #include <glm/glm.hpp>
Compilers have some language extensions that GLM will automatically take advantage of them when they are enabled. GLM_FORCE_CXX98 can switch off these extensions, forcing GLM to operate on pure C++98.
#define GLM_FORCE_CXX98 #include <glm/glm.hpp>