跳到主要内容

四维矩阵(Mat4)

表示 4×4 列主序变换矩阵(column-major transformation matrix),适用于 3D 变换并可直接上传至 GPU uniform buffer。

-- 构建 MVP 矩阵
local proj = Mat4.perspective(math.rad(60), 16 / 9, 0.1, 100)
local view = Mat4.fromTranslation(0, 0, -3) -- 摄像机后退 3 单位
local model = Mat4.fromRotationY(angle)
local mvp = proj * view * model

-- 上传至 uniform buffer(64 字节,列主序)
mvp:writeToBuffer(uboBytes, 0)

字段(Fields)

m11

行列索引从 1 开始,mRC 表示第 R 行第 C 列的元素。例如 m.m12 是 第 1 行第 2 列的值。

local m = Mat4.identity()
m.m11 = 2 -- 缩放 x
m.m22 = 3 -- 缩放 y
m.m14 = 50 -- 平移 x

m12

m13

m14

m21

m22

m23

m24

m31

m32

m33

m34

m41

m42

m43

m44

构造函数(Constructors)

identity

identity() -> Mat4

返回 4×4 单位矩阵。

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

创建缩放矩阵。如果省略 yz,将对所有轴应用 x 的统一缩放。

local s1 = Mat4.fromScale(2)        -- 统一 2x 缩放
local s2 = Mat4.fromScale(1, 2, 1) -- 仅在 Y 轴 2x 缩放

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 为弧度制;nearfar 为正数距离。

local proj = Mat4.perspective(math.rad(60), 16 / 9, 0.1, 100)

perspectiveReverseZ

perspectiveReverseZ(fovY: number, aspect: number, near: number) -> Mat4

右手系透视投影,使用反向 Z(reverse-Z:near → 1, far → 0)和无限远平面。 配合 float 深度缓冲区,可在整个视锥体内实现近乎均匀的 1/z 深度分布—— 这是任意场景能达到的最佳精度。深度缓冲区必须清零为 0(而非 1), 深度测试需翻转为 GREATER。

local proj = Mat4.perspectiveReverseZ(math.rad(60), 16 / 9, 0.1)

multiply

multiply(output: Mat4, a: Mat4, b: Mat4) -> Mat4

a * b 写入 output,复用其存储空间。返回 output。 在紧凑循环中使用此方法可避免每次乘法都分配新的 Mat4output 可与 ab 别名(alias)。

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 类似,但假设两个输入均为仿射矩阵(affine matrix, 即底行为 [0, 0, 0, 1]——任何由平移/缩放/旋转矩阵复合而成的矩阵均符合条件)。 跳过底行计算,每次乘法减少约 25% 的浮点运算。结果始终为仿射。 调用者必须确保两个输入为仿射矩阵;传入非仿射输入将得到错误结果。

local world = Mat4.identity()
for _, bone in ipairs(bones) do
Mat4.multiplyAffine(world, parent, bone.local)
end

静态函数(Static Functions)

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 更快。

方法(Methods)

invert

invert() -> Mat4?

支持列主序线性索引访问。索引 1..4 为第 0 列,5..8 为第 1 列, 9..12 为第 2 列,13..16 为第 3 列(平移分量)。

local m = Mat4.identity()
m[13] = 50 -- 平移 x
m[14] = 100 -- 平移 y
m[15] = 25 -- 平移 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 非单位值(例如经过透视矩阵后),返回的点会进行透视除法。

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 条目)写入给定缓冲区的 byteOffset 偏移处。缓冲区从偏移位置起至少需要有 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?

仿射矩阵的闭式逆(closed-form inverse)。适用于底行为 [0, 0, 0, 1] 的矩阵—— 任何由 fromTranslation/fromScale/fromRotationX/Y/Z 复合而成的矩阵均符合条件。 如果线性部分奇异则返回 nil。比 :invert() 更快,无需进行完整的 4×4 余子式计算。

local m = Mat4.fromTranslation(3, -4, 5) * Mat4.fromRotationY(0.4)
local inv = m:invertAffine()