Mat4
表示一个 4x4 列主序变换矩阵,适用于 3D 变换,并可直接上传到 GPU uniform buffer。
-- Construct an MVP matrix
local proj = Mat4.perspective(math.rad(60), 16 / 9, 0.1, 100)
local view = Mat4.fromTranslation(0, 0, -3) -- camera 3 units back
local model = Mat4.fromRotationY(angle)
local mvp = proj * view * model
-- Upload to a uniform buffer (64 bytes, column-major)
mvp:writeToBuffer(uboBytes, 0)
字段
m11
位于行 R、列 C 的元素(从 1 开始索引)。例如 m.m12 是第 1 行第 2 列的元素。
local m = Mat4.identity()
m.m11 = 2 -- scale x
m.m22 = 3 -- scale y
m.m14 = 50 -- translate x
m12
m13
m14
m21
m22
m23
m24
m31
m32
m33
m34
m41
m42
m43
m44
构造函数
identity
identity() -> Mat4
返回 4x4 单位矩阵。
values
values(c0x: number, c0y: number, c0z: number, c0w: number, c1x: number, c1y: number, c1z: number, c1w: number, c2x: number, c2y: number, c2z: number, c2w: number, c3x: number, c3y: number, c3z: number, c3w: number) -> Mat4
使用 16 个分量创建矩阵,分量按列主序提供(先是第 0 列:c0x、c0y、c0z、c0w、c1x,依此类推)。
fromTranslation
fromTranslation(x: number, y: number, z: number) -> Mat4
创建平移矩阵。
local t = Mat4.fromTranslation(10, 20, 30)
fromScale
fromScale(x: number, y: number?, z: number?) -> Mat4
创建缩放矩阵。如果省略 y 和 z,则对所有轴应用由 x 指定的统一缩放。
local s1 = Mat4.fromScale(2) -- uniform 2x
local s2 = Mat4.fromScale(1, 2, 1) -- 2x in Y only
fromRotationX
fromRotationX(radians: number) -> Mat4
创建绕 X 轴旋转的矩阵(弧度)。
fromRotationY
fromRotationY(radians: number) -> Mat4
创建绕 Y 轴旋转的矩阵(弧度)。
fromRotationZ
fromRotationZ(radians: number) -> Mat4
创建绕 Z 轴旋转的矩阵(弧度)。
perspective
perspective(fovY: number, aspect: number, near: number, far: number) -> Mat4
创建右手坐标系透视投影矩阵,将 z 映射到 [0, 1] 的 NDC 深度范围。fovY 使用弧度;near 和 far 为正距离。
local proj = Mat4.perspective(math.rad(60), 16 / 9, 0.1, 100)
perspectiveReverseZ
perspectiveReverseZ(fovY: number, aspect: number, near: number) -> Mat4
右手坐标系透视投影,使用 reverse-Z(near -> 1,far -> 0)和无限远平面。结合浮点深度缓冲区时,可在整个视锥体范围内获得近似均匀的 1/z 深度分布——这是任意场景能达到的最佳精度。深度缓冲区必须清除为 0(而不是 1),并且深度测试需要切换为 GREATER。
local proj = Mat4.perspectiveReverseZ(math.rad(60), 16 / 9, 0.1)
lookAt
lookAt(eye: Vector, center: Vector, up: Vector) -> Mat4
创建右手坐标系视图矩阵,从 eye 看向 center(GLM 约定)。up 不需要归一化。
local view = Mat4.lookAt(Vector.xyz(0, 2, 5), Vector.origin(), Vector.xyz(0, 1, 0))
ortho
ortho(left: number, right: number, bottom: number, top: number, near: number, far: number) -> Mat4
创建右手坐标系正交投影矩阵,将 z 映射到 [0, 1] 的 NDC 深度范围 (与 Mat4.perspective 匹配),例如用于阴影贴图级联或 2D 叠加层。
local proj = Mat4.ortho(-10, 10, -10, 10, 0.1, 100)
multiply
multiply(output: Mat4, a: Mat4, b: Mat4) -> Mat4
将 a * b 写入 output,复用其存储空间。返回 output。在紧密循环中使用它可以避免每次乘法都分配新的 Mat4。output 可以与 a 或 b 为同一对象。
local out = Mat4.identity()
for i = 1, 1000 do Mat4.multiply(out, view, model) end
multiplyAffine
multiplyAffine(output: Mat4, a: Mat4, b: Mat4) -> Mat4
类似于 Mat4.multiply,但假定两个输入都是仿射矩阵(底行 [0, 0, 0, 1]——任何平移/缩放/旋转矩阵的组合都满足条件)。它会跳过底行计算,每次乘法大约减少 25% 的 FLOP。结果始终为仿射矩阵。调用者必须确保两个输入都是仿射矩阵;传入非仿射输入会得到不正确的结果。
local world = Mat4.identity()
for _, bone in ipairs(bones) do
Mat4.multiplyAffine(world, parent, bone.local)
end
静态函数
invert
invert(output: Mat4, input: Mat4) -> boolean
将 input 的逆矩阵写入 output,成功时返回 true;如果 input 为奇异矩阵,则返回 false。
local inv = Mat4.identity()
local ok = Mat4.invert(inv, m)
invertAffine
invertAffine(output: Mat4, input: Mat4) -> boolean
将 input 的仿射逆矩阵写入 output。契约请参见 Mat4:invertAffine;它比 Mat4.invert 更快。
方法
invert
invert() -> Mat4?
线性列主序访问。索引 1..4 是第 0 列,5..8 是第 1 列,9..12 是第 2 列,13..16 是第 3 列(平移)。
local m = Mat4.identity()
m[13] = 50 -- translate x
m[14] = 100 -- translate y
m[15] = 25 -- translate z
返回矩阵的逆矩阵;如果矩阵为奇异矩阵,则返回 nil。
local m = Mat4.fromTranslation(50, 100, 25)
local inv = m:invert()
transpose
transpose() -> Mat4
返回矩阵的转置。
local m = Mat4.fromRotationY(math.rad(45))
local t = m:transpose()
transformPoint
transformPoint(x: number, y: number, z: number) -> Vector
使用矩阵变换给定的 3D 点(将 w 视为 1),并将结果作为 Vector 返回。如果结果的齐次 w 不是 1(例如经过透视矩阵之后),返回的点会进行透视除法。
local m = Mat4.fromTranslation(10, 20, 30)
local p = m:transformPoint(1, 2, 3)
print(p.x, p.y, p.z) -- 11, 22, 33
transformVec4
transformVec4(x: number, y: number, z: number, w: number) -> (number, number, number, number)
使用矩阵变换给定的齐次 4D 向量,并以多个返回值的形式返回四个分量,不进行透视除法。当调用者需要检查或保留齐次 w(例如裁剪空间坐标)时使用它。
local mvp = proj * view * model
local x, y, z, w = mvp:transformVec4(px, py, pz, 1)
writeToBuffer
writeToBuffer(buf: buffer, byteOffset: number) -> ()
将矩阵以 64 字节(列主序,16 个 float32 条目)写入给定 buffer 的 byteOffset 位置。从该偏移开始,buffer 必须至少有 64 字节可用。
local mvp = Mat4.identity()
local ubo = buffer.create(64)
mvp:writeToBuffer(ubo, 0)
__eq
__eq(rhs: Mat4) -> boolean
如果两个矩阵的全部 16 个分量都相等,则返回 true。
__mul
__mul(rhs: Mat4) -> Mat4
返回两个矩阵的矩阵乘积。适用于组合变换,例如 proj * view * model。会分配新的 Mat4;在紧密循环中,建议使用 Mat4.multiply(out, a, b) 来复用存储空间。
invertAffine
invertAffine() -> Mat4?
仿射矩阵的闭式逆(底行 [0, 0, 0, 1]——任何 fromTranslation/fromScale/fromRotationX/Y/Z 的组合都满足条件)。如果线性部分为奇异矩阵,则返回 nil。它比 :invert() 更快,并且避免完整的 4x4 余子式计算。
local m = Mat4.fromTranslation(3, -4, 5) * Mat4.fromRotationY(0.4)
local inv = m:invertAffine()