如何用 GLM 做 C++ 图形数学:vec、mat 与四元数完整上手指南

发布时间:2026/11/4 1:57:58
如何用 GLM 做 C++ 图形数学:vec、mat 与四元数完整上手指南

如何用 GLM 做 C++ 图形数学:vec、mat 与四元数完整上手指南

【免费下载链接】glmOpenGL Mathematics (GLM)项目地址: https://gitcode.com/gh_mirrors/gl/glm

GLM(OpenGL Mathematics)是一个 header only 的 C++ 图形数学库,把 GLSL 规范里的向量、矩阵、四元数函数用相同的命名搬到了 C++ 一侧。如果你要写渲染器、3D 工具或物理模拟,又不想自己推导矩阵乘法和归一化,它是直接可用的现成方案。

一句话定位

GLM 的定位是“用 GLSL 的写法,在 C++ 里用”:会读着色器的人可以直接上主机端写数学代码。与通用线性代数库不同,它不追求 SVD、稀疏矩阵这类通用能力,而是专注于 GLSL 规范定义的那套类型和函数,再叠加一层扩展体系——矩阵变换、四元数、数据打包、噪声、随机数等。

五分钟用 GLM 图形数学跑起来 🧰

引入方式很轻:CMake 里find_package(glm CONFIG REQUIRED)之后链接glm::glm-header-only(纯头文件)或glm::glm(库模式);用 vcpkg 的话直接vcpkg install glm。源码可以从 https://gitcode.com/gh_mirrors/gl/glm 克隆下来自己构建。

装好之后,一个函数就能拿到第一张 MVP 相机矩阵,只需包含glm/ext/matrix_clip_space.hpp和glm/ext/matrix_transform.hpp:

glm::mat4 view(float dist, float yaw, float pitch) { glm::mat4 P = glm::perspective(glm::pi<float>() * 0.25f, 4.0f / 3.0f, 0.1f, 100.0f); glm::mat4 V = glm::translate(glm::mat4(1.0f), {0.0f, 0.0f, -dist}); V = glm::rotate(glm::rotate(V, pitch, {1.0f, 0.0f, 0.0f}), yaw, {0.0f, 1.0f, 0.0f}); return P * V; }

glm::perspective、glm::rotate这些函数名和 GLSL 里的写法一一对应,头文件拆分在 glm/ext/ 目录下,用到哪个包含哪个。

能力拆解:三个常见场景 🧮

用 GLM 矩阵函数搭建 MVP 相机链路

自己写渲染器时,4x4 矩阵乘法、列主序布局、透视投影公式都得手工实现,还得对照 OpenGL 的 clip space 约定验证。GLM 把这些拆成独立的 clip space 与 transform 扩展头文件,直接包含即用。上面的例子是完整相机矩阵;如果需要无限远平面处理,扩展里还提供了infinitePerspectiveRH和infinitePerspectiveLH两个函数。

用四元数做平滑旋转与合成

旋转插值如果自己做,得处理球面线性插值、轴角表示,还要防万向锁。用 GLM 的话,glm::angleAxis从轴角建一个旋转,glm::slerp在两个四元数之间平滑过渡,需要拼进 MVP 链路时再用 glm::mat4_cast 转成矩阵:

#include <glm/gtc/quaternion.hpp> glm::quat q = glm::angleAxis(glm::radians(45.0f), {0.0f, 1.0f, 0.0f}); glm::mat4 M = glm::mat4_cast(q); glm::quat mid = glm::slerp(q, glm::quat(1.0f, 0.0f, 0.0f, 0.0f), 0.5f);

1.0.2 版本还补充了 packed/aligned 两种 quat 类型,前者省内存,后者给 SIMD 场景用,可按内存布局需求挑选。

用结构化绑定拆开 vec3 的分量

把向量分量逐个传给函数时,以前得手写.x、.y、.z。1.0.2 新增的GLM_GTX_structured_bindings扩展让 C++17 结构化绑定直接作用于 vec、mat、quat 类型:

#define GLM_ENABLE_EXPERIMENTAL #include <glm/gtx/structured_bindings.hpp> glm::vec3 p{1.0f, 2.0f, 3.0f}; auto [x, y, z] = p;

GTX 系列属于实验性扩展,使用前必须定义GLM_ENABLE_EXPERIMENTAL,接口将来可能变动。同一系列里的glm/gtx/iteration.hpp还能让向量参与 range-for 遍历。

工程化细节 ⚙️

  • 编译器要求:需要 C++17 编译器;官方支持列表为 GCC 8+、Clang 6+、Apple Clang 6.0+、Visual C++ 2019+、CUDA 9.0+(实验性),更老的 C++ 标准可以用 1.0 分支。
  • 构建安装:cmake -DGLM_BUILD_TESTS=OFF -B build .后执行cmake --build build -- install;加-DBUILD_SHARED_LIBS=ON产出动态库。
  • 不想装包也可以用 CMake 的 FetchContent 拉取源码随工程一起构建。
  • 单元测试默认不构建,需要显式加-DGLM_BUILD_TESTS=ON。
  • SIMD intrinsics 默认关闭,定义GLM_FORCE_INTRINSICS开启;默认配置下函数保持 constexpr 友好。
  • 跨版本迁移:1.0.2 修复过四元数 rotate 的方向问题,1.0.3 又把该修复回退,跨这两个版本升级时要核对旋转方向的用例;1.0.3 还修正了 vec4 到 vec3 的转换,依赖旧行为的代码注意检查。

选型参考 ⚖️

  • 对比Eigen:Eigen 是更重的通用线性代数库,覆盖稀疏矩阵、各类分解。如果你的核心需求是与 GLSL 命名一一对应、主机端和着色器写同一套 vec/mat 操作,GLM 更直接。
  • 对比CML:CML 同样面向游戏和图形场景,GLM 的扩展体系、编译器覆盖(含 NEON 路径)和测试规模更完整,单测分布在 test/ 下的 core、ext、gtc、gtx 四个子目录。
  • 不必选它的场景:通用数值计算、稀疏线性代数这类需求,或者团队已有引擎内建数学库且不需要 GLSL 风格命名。

收尾 📮

如果你在写 C++ 图形或模拟代码、希望主机端数学和着色器同名同构,GLM 就是现成答案。完整的手册见仓库内的 manual.md,API 参考文档在doc/api/目录。

【免费下载链接】glmOpenGL Mathematics (GLM)项目地址: https://gitcode.com/gh_mirrors/gl/glm

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考