在计算机图形学领域,投影矩阵是将三维空间中的物体转换到二维屏幕上的关键工具。它能帮助我们模拟真实世界的视觉效果,让用户在平面显示器上看到立体的图形场景。下面我们将深入探讨投影矩阵的原理与实现。
一、投影矩阵基础概念
在三维空间里,每个点都有三个坐标(x,y,z),而我们的屏幕是二维的,只有两个坐标(x,y)。投影矩阵的作用,就是把三维空间中物体上每个点的坐标,经过一系列计算,转化为二维屏幕上对应的坐标,这样我们就能在屏幕上看到三维物体的样子了。这个转换过程包含了缩放、平移、旋转等多种操作,通过矩阵乘法来实现。
二、正交投影矩阵
正交投影是一种比较简单的投影方式,它不会产生近大远小的效果,常用于工程制图、建筑设计等需要精确展示物体尺寸和形状的场景。在正交投影中,所有平行线在投影后仍然保持平行。
正交投影矩阵的创建,需要确定几个关键参数:
- 左平面(left) :三维空间中最左侧的平面位置。
- 右平面(right) :三维空间中最右侧的平面位置。
- 下平面(bottom) :三维空间中最下方的平面位置。
- 上平面(top) :三维空间中最上方的平面位置。
- 近平面(near) :距离观察者最近的平面位置。
- 远平面(far) :距离观察者最远的平面位置。
用 JavaScript 实现创建正交投影矩阵的代码如下:
function ortho(left, right, bottom, top, near, far) {
return [
2 / (right - left), 0, 0, 0,
0, 2 / (top - bottom), 0, 0,
0, 0, -2 / (far - near), 0,
-(right + left) / (right - left), -(top + bottom) / (top - bottom), -(far + near) / (far - near), 1
];
}
在这段代码中,函数 ortho 根据传入的六个参数,按照正交投影矩阵的计算规则,构建并返回一个 4x4 的矩阵数组。矩阵中的每个元素对应着特定的计算,用来实现将三维坐标转换为二维坐标的缩放和平移操作。
三、透视投影矩阵
透视投影更符合我们人眼观察物体的方式,会产生近大远小的效果,在游戏、影视特效等领域广泛应用。在透视投影中,平行线在远处会汇聚到一个消失点。
创建透视投影矩阵,同样需要几个关键参数:
- 视角(fovy) :垂直方向上的视角角度,通常以弧度为单位。
- 宽高比(aspect) :渲染窗口的宽度与高度的比值。
- 近平面(near) :距离观察者最近的平面位置。
- 远平面(far) :距离观察者最远的平面位置。
下面是用 JavaScript 实现创建透视投影矩阵的代码:
function perspective(fovy, aspect, near, far) {
const yMax = near * Math.tan(fovy / 2);
const yMin = -yMax;
const xMin = yMin * aspect;
const xMax = yMax * aspect;
return [
2 * near / (xMax - xMin), 0, 0, 0,
0, 2 * near / (yMax - yMin), 0, 0,
(xMax + xMin) / (xMax - xMin), (yMax + yMin) / (yMax - yMin), -(far + near) / (far - near), -1,
0, 0, -2 * far * near / (far - near), 0
];
}
在 perspective 函数中,首先根据视角和近平面距离计算出垂直方向的边界值 yMax 和 yMin,再根据宽高比算出水平方向的边界值 xMin 和 xMax。然后按照透视投影矩阵的计算公式,构建并返回一个 4x4 的矩阵数组。这个矩阵能模拟出近大远小的视觉效果,将三维空间中的物体投影到二维屏幕上。
四、使用投影矩阵进行坐标转换
有了投影矩阵后,我们需要将三维空间中的点坐标与投影矩阵相乘,得到投影后的二维坐标。在 JavaScript 中,可以通过矩阵乘法函数来实现这一过程。以下是一个简单的矩阵向量乘法示例代码:
function multiplyMatrixVector(matrix, vector) {
const x = matrix[0] * vector[0] + matrix[1] * vector[1] + matrix[2] * vector[2] + matrix[3] * vector[3];
const y = matrix[4] * vector[0] + matrix[5] * vector[1] + matrix[6] * vector[2] + matrix[7] * vector[3];
const z = matrix[8] * vector[0] + matrix[9] * vector[1] + matrix[10] * vector[2] + matrix[11] * vector[3];
const w = matrix[12] * vector[0] + matrix[13] * vector[1] + matrix[14] * vector[2] + matrix[15] * vector[3];
return [x / w, y / w, z / w];
}
假设我们有一个三维点坐标 [1, 1, 1],想要用前面创建的正交投影矩阵进行转换,可以这样操作:
const orthoMatrix = ortho(-1, 1, -1, 1, 0.1, 100);
const point = [1, 1, 1, 1]; // 齐次坐标表示的三维点
const projectedPoint = multiplyMatrixVector(orthoMatrix, point);
console.log(projectedPoint);
通过上述代码,我们就能将三维空间中的点经过投影矩阵转换,得到其在二维屏幕上对应的坐标。
计算机图形学中的投影矩阵是实现三维到二维转换的核心,正交投影和透视投影各有其应用场景。通过 JavaScript 代码实现投影矩阵的创建和坐标转换,能帮助我们更深入地理解其工作原理。希望本文能让你对投影矩阵有更清晰的认识,并在实际项目中灵活运用。