gpt4 book ai didi

javascript - 学习 WebGL 背后的数学原理

转载 作者:行者123 更新时间:2023-11-30 12:59:47 25 4
gpt4 key购买 nike

就像我这个受虐狂一样,我正在努力学习创建模型 View 和透视矩阵背后的所有矩阵数学,以便我可以编写自己的函数来生成它们而无需使用 JS 库。

我理解矩阵的概念,但不知道如何实际生成它们。我一直在仔细研究 glMatrix 库,我有以下问题:

1) 以下 mat4.perspecive 方法中发生了什么?

/**
* Generates a perspective projection matrix with the given bounds
*
* @param {mat4} out mat4 frustum matrix will be written into
* @param {number} fovy Vertical field of view in radians
* @param {number} aspect Aspect ratio. typically viewport width/height
* @param {number} near Near bound of the frustum
* @param {number} far Far bound of the frustum
* @returns {mat4} out
*/
mat4.perspective = function (out, fovy, aspect, near, far) {
var f = 1.0 / Math.tan(fovy / 2),
nf = 1 / (near - far);
out[0] = f / aspect;
out[1] = 0;
out[2] = 0;
out[3] = 0;
out[4] = 0;
out[5] = f;
out[6] = 0;
out[7] = 0;
out[8] = 0;
out[9] = 0;
out[10] = (far + near) * nf;
out[11] = -1;
out[12] = 0;
out[13] = 0;
out[14] = (2 * far * near) * nf;
out[15] = 0;
return out;
};

具体来说,我得到了 Math.tan(fovy/2) 正在计算的内容,但为什么要取反?同样,为什么取近边界和远边界之差的倒数?另外,为什么 out[11] 设置为 -1 以及 out[14] 中存储的值是什么?

2) 库中的以下mat4.lookAt 方法也让我感到困惑:

/**
* Generates a look-at matrix with the given eye position, focal point,
* and up axis
*
* @param {mat4} out mat4 frustum matrix will be written into
* @param {vec3} eye Position of the viewer
* @param {vec3} center Point the viewer is looking at
* @param {vec3} up vec3 pointing up
* @returns {mat4} out
*/
mat4.lookAt = function (out, eye, center, up) {
var x0, x1, x2, y0, y1, y2, z0, z1, z2, len,
eyex = eye[0],
eyey = eye[1],
eyez = eye[2],
upx = up[0],
upy = up[1],
upz = up[2],
centerx = center[0],
centery = center[1],
centerz = center[2];

if (Math.abs(eyex - centerx) < GLMAT_EPSILON &&
Math.abs(eyey - centery) < GLMAT_EPSILON &&
Math.abs(eyez - centerz) < GLMAT_EPSILON) {
return mat4.identity(out);
}

z0 = eyex - centerx;
z1 = eyey - centery;
z2 = eyez - centerz;

len = 1 / Math.sqrt(z0 * z0 + z1 * z1 + z2 * z2);
z0 *= len;
z1 *= len;
z2 *= len;

x0 = upy * z2 - upz * z1;
x1 = upz * z0 - upx * z2;
x2 = upx * z1 - upy * z0;
len = Math.sqrt(x0 * x0 + x1 * x1 + x2 * x2);
if (!len) {
x0 = 0;
x1 = 0;
x2 = 0;
} else {
len = 1 / len;
x0 *= len;
x1 *= len;
x2 *= len;
}

y0 = z1 * x2 - z2 * x1;
y1 = z2 * x0 - z0 * x2;
y2 = z0 * x1 - z1 * x0;

len = Math.sqrt(y0 * y0 + y1 * y1 + y2 * y2);
if (!len) {
y0 = 0;
y1 = 0;
y2 = 0;
} else {
len = 1 / len;
y0 *= len;
y1 *= len;
y2 *= len;
}

out[0] = x0;
out[1] = y0;
out[2] = z0;
out[3] = 0;
out[4] = x1;
out[5] = y1;
out[6] = z1;
out[7] = 0;
out[8] = x2;
out[9] = y2;
out[10] = z2;
out[11] = 0;
out[12] = -(x0 * eyex + x1 * eyey + x2 * eyez);
out[13] = -(y0 * eyex + y1 * eyey + y2 * eyez);
out[14] = -(z0 * eyex + z1 * eyey + z2 * eyez);
out[15] = 1;

return out;
};

类似mat4.perspecive方法,为什么计算的是向量长度的倒数?另外,为什么该值然后乘以 z0z1z2 值? x0-x2 变量和 y0-y2 变量也是一样的。为什么?最后,out[12]-out[14]设置的值是什么意思?

3) 最后,我有几个关于 mat4.translate 方法的问题。具体来说,我买了书Professional WebGL Programming: Developing 3D Graphics for the Web ,它表示以下 4x4 矩阵用于平移顶点:

1 0 0 x
0 1 0 y
0 0 1 z
0 0 0 1

但是,当我查看 glMatrix 库中的以下 mat4.translate 方法时,我看到 out[12]-out[15] 是通过一些复杂的方程式设置的。为什么要设置这些值?

/**
* Translate a mat4 by the given vector
*
* @param {mat4} out the receiving matrix
* @param {mat4} a the matrix to translate
* @param {vec3} v vector to translate by
* @returns {mat4} out
*/
mat4.translate = function (out, a, v) {
var x = v[0], y = v[1], z = v[2],
a00, a01, a02, a03,
a10, a11, a12, a13,
a20, a21, a22, a23;

if (a === out) {
out[12] = a[0] * x + a[4] * y + a[8] * z + a[12];
out[13] = a[1] * x + a[5] * y + a[9] * z + a[13];
out[14] = a[2] * x + a[6] * y + a[10] * z + a[14];
out[15] = a[3] * x + a[7] * y + a[11] * z + a[15];
} else {
a00 = a[0]; a01 = a[1]; a02 = a[2]; a03 = a[3];
a10 = a[4]; a11 = a[5]; a12 = a[6]; a13 = a[7];
a20 = a[8]; a21 = a[9]; a22 = a[10]; a23 = a[11];

out[0] = a00; out[1] = a01; out[2] = a02; out[3] = a03;
out[4] = a10; out[5] = a11; out[6] = a12; out[7] = a13;
out[8] = a20; out[9] = a21; out[10] = a22; out[11] = a23;

out[12] = a00 * x + a10 * y + a20 * z + a[12];
out[13] = a01 * x + a11 * y + a21 * z + a[13];
out[14] = a02 * x + a12 * y + a22 * z + a[14];
out[15] = a03 * x + a13 * y + a23 * z + a[15];
}

return out;
};

感谢大家抽出宝贵时间,对于所有问题,我们深表歉意。我来自 JS 背景,而不是 OpenGL/3D 编程背景,所以我很难理解所有矩阵背后的数学原理。

如果有任何很好的资源可以解释用于这些方程式/方法的数学,那也很好。谢谢。

最佳答案

Specifically, I get what Math.tan(fovy / 2) is calculating, but why take the inverse of it?

因为焦距d来自公式

Math.tan(fovy / 2) = y / d

得到你需要乘以的焦距

1 / Math.tan(fovy / 2)

why take the inverse of the difference between the near boundary and the far boundary? Also, why is out[11] set to -1 and what is the value stored in out[14] for?

您可以使用焦距 d< 将 (x,y,z) 投影到 (x*d/z, y*d/z)/。这已经足够了,但 OpenGL 需要对 (x,y,z) 进行线性变换,例如投影在 [-1,1] 中给出坐标。这种归一化坐标简化了裁剪并保留了用于移除隐藏表面的 z 信息。

out[11] 设置为 -1,因为除非应用反射,否则没有提供归一化坐标的线性变换。这个 -1 导致系统的惯用手性与归一化坐标切换。

out[14] 与 out[10] 一起使用,在投影后将 z 从 [-n -f] 转换为 [-1 1]。

Similar to the mat4.perspecive method, why is the inverse of the length of the vector being calculated? Also, why is that value then multiplied by the z0, z1 and z2 values? The same thing is being done for the x0-x2 variables and the y0-y2 variables. Why?

归一化向量 x、y 和 z

what is the meaning of the values set for out[12]-out[14]?

相机由矢量基和位置组成。out[12]-out[14] 应用反向翻译来设置相机位置。

However, when I look at the following mat4.translate method in the glMatrix library, I see that out[12]-out[15] are set via some complex equations. Why are these values set at all?

方程式看起来很复杂,因为它是平移矩阵和现有矩阵 a 的乘积。

Professional WebGL Programming: Developing 3D Graphics for the Web

我不知道这本书,它可能会解释一些数学,但如果您需要详细解释,您应该考虑 Eric Lengyel 的 book这解释并推导了 3d 光栅图形中使用的重要数学。

关于javascript - 学习 WebGL 背后的数学原理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17643720/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com