glLookAt 移动 lookAt 时移动相机位置 - 投影矩阵的作用?
glLookAt moves camera position when lookAt is moved - role of projection matrix?
简短版本: 我正在使用带有透视投影矩阵的 glLookAt 视图矩阵,我想知道为什么 camLookAt 向量发生变化(我' m looking at) 导致相机位置发生变化。
长版本: 我正在使用描述的代码 here 来实现我自己的著名 glLookAt 函数:
var z = glm.normalize(camPosition - camLookAt);
var y = up;
var x = glm.normalize(glm.cross(y, z));
y = glm.cross(z, x);
var result = new mat4(1.0f);
result[0, 0] = x.x;
result[1, 0] = x.y;
result[2, 0] = x.z;
result[3, 0] = -Dot(x, camPosition);
result[0, 1] = y.x;
result[1, 1] = y.y;
result[2, 1] = y.z;
result[3, 1] = -Dot(y, camPosition);
result[0, 2] = z.x;
result[1, 2] = z.y;
result[2, 2] = z.z;
result[3, 2] = -Dot(z, camPosition);
result[0, 3] = 0;
result[1, 3] = 0;
result[2, 3] = 0;
result[3, 3] = 1.0f;
return result;
这似乎工作得很好,除了一件奇怪的事情:当我让凸轮的位置固定,但改变 camLookAt
变量时,似乎相机移动的不仅仅是它的角度,还有它的位置.
为了演示,我做了一个显式计算:
- 获得世界积分
(0, 0, 0)
和(1, 0, 0)
。
- 从
camPosition = (-3, 0, 0)
和 camLookAt = (0, 0, 0)
与 up = (0, 0, 1)
来看它们。所以我们正在查看原点,在正 x 轴的方向上。这是我得到的矩阵:
0, -1, 0, 0
0, 0, 1, 0
-1, 0, 0, -3
0, 0, 0, 1
- 由于两个点都位于 x 轴上,因此它们应该出现在我们相机的同一位置。一个点应该恰好在另一个点之后。这很好用,第一个点映射到
(0, 0, -3)
,第二个点映射到 (0, 0, -4)
。
- 现在将
camLookAt
更改为(0, 3, 0)
,即将相机向左旋转45度。这是我得到的矩阵:
0.71, -0.71, 0.00, 2.12
0.00, 0.00, 1.00, 0.00
-0.71、-0.71、0.00、-2.12
0.00, 0.00, 0.00, 1.00
- 由于我们没有移动相机的位置,所以点应该仍然在彼此后面。但是,情况并非如此,这两个点分别转换为
(2.1213, 0, -2.1213)
和 (2.8284, 0, -2.8284)
。所以两个变换点的(X,Y)分量不匹配。
到目前为止,我们只使用了欧几里德变换,所以还没有透视。但是,我使用的是像这样的透视投影矩阵
const float radians = (60.0f / 360.0f) * (float)Math.PI * 2.0f;
projectionMatrix = glm.perspective(radians, width / height, 0.01f, 1000f);
即使在应用此投影矩阵之后,这两个点也不会落在相同的 (X, Y) 坐标上,即落在屏幕上的同一像素上。
我错过了什么?这是 glLookAt 的预期行为,还是我使用/实施错误?
编辑: 投影矩阵应用于顶点着色器,就像这样:
void main(void) {
gl_Position = projectionMatrix * viewMatrix * modelMatrix * vec4(in_Position, 1.0);
}
EIDT 2: 这是我当前场景的录音,作为澄清。唯一随时间变化的是 camLookAt
向量。相机应该保持在相同的位置,但不知何故它似乎在移动:
编辑 3: 按照@NicoSchertler 的建议,我只是在 CPU 上进行了所有计算。 viewMatrix 乘法在上面完成,结果分别为 (2.1213, 0, -2.1213)
和 (2.8284, 0, -2.8284)
。现在我应用投影矩阵(参见上面我如何获得投影矩阵):
1.30, .00, .00, .00
.00, 1.73, .00, .00
.00, .00, -1.00, -.02
.00, .00, -1.00, 1.00
我得到以下向量
(2.75, 0.00, 2.10, 3.12)
(3.67, 0.00, 2.81, 3.83)
然后我将它们除以它们的 w
值,得到
(0.88, 0.00, 0.67, 1.00)
(0.96, 0.00, 0.73, 1.00)
所以他们显然不在彼此后面。
投影矩阵有问题吗?
However, this isn't the case, (...) the (X,Y) components of the two transformed points do not match.
坐标x/y不同的两个点并不代表它们不在彼此的后面。显然,它们具有不同的深度。相机位于该坐标系中的原点。如果你计算从相机到点的方向(即 normalize(p - 0)
),我们得到:
direction1 = {0.707107, 0, -0.707107}
direction2 = {0.707107, 0, -0.707107}
所以,从相机到两点的方向是相同的,因此它们在彼此的后面。
你还没有展示你是如何进行投影的。但这些点必须投射到同一位置。不过,透视投影有一点警告。投影点将有一个 w
分量,而不是 1
。您需要将点除以此 w
分量(透视划分)以找到实际投影点。然后,x/y 坐标应该实际匹配。
简短版本: 我正在使用带有透视投影矩阵的 glLookAt 视图矩阵,我想知道为什么 camLookAt 向量发生变化(我' m looking at) 导致相机位置发生变化。
长版本: 我正在使用描述的代码 here 来实现我自己的著名 glLookAt 函数:
var z = glm.normalize(camPosition - camLookAt);
var y = up;
var x = glm.normalize(glm.cross(y, z));
y = glm.cross(z, x);
var result = new mat4(1.0f);
result[0, 0] = x.x;
result[1, 0] = x.y;
result[2, 0] = x.z;
result[3, 0] = -Dot(x, camPosition);
result[0, 1] = y.x;
result[1, 1] = y.y;
result[2, 1] = y.z;
result[3, 1] = -Dot(y, camPosition);
result[0, 2] = z.x;
result[1, 2] = z.y;
result[2, 2] = z.z;
result[3, 2] = -Dot(z, camPosition);
result[0, 3] = 0;
result[1, 3] = 0;
result[2, 3] = 0;
result[3, 3] = 1.0f;
return result;
这似乎工作得很好,除了一件奇怪的事情:当我让凸轮的位置固定,但改变 camLookAt
变量时,似乎相机移动的不仅仅是它的角度,还有它的位置.
为了演示,我做了一个显式计算:
- 获得世界积分
(0, 0, 0)
和(1, 0, 0)
。 - 从
camPosition = (-3, 0, 0)
和camLookAt = (0, 0, 0)
与up = (0, 0, 1)
来看它们。所以我们正在查看原点,在正 x 轴的方向上。这是我得到的矩阵:
0, -1, 0, 0 0, 0, 1, 0 -1, 0, 0, -3 0, 0, 0, 1
- 由于两个点都位于 x 轴上,因此它们应该出现在我们相机的同一位置。一个点应该恰好在另一个点之后。这很好用,第一个点映射到
(0, 0, -3)
,第二个点映射到(0, 0, -4)
。 - 现在将
camLookAt
更改为(0, 3, 0)
,即将相机向左旋转45度。这是我得到的矩阵:
0.71, -0.71, 0.00, 2.12 0.00, 0.00, 1.00, 0.00 -0.71、-0.71、0.00、-2.12 0.00, 0.00, 0.00, 1.00
- 由于我们没有移动相机的位置,所以点应该仍然在彼此后面。但是,情况并非如此,这两个点分别转换为
(2.1213, 0, -2.1213)
和(2.8284, 0, -2.8284)
。所以两个变换点的(X,Y)分量不匹配。
到目前为止,我们只使用了欧几里德变换,所以还没有透视。但是,我使用的是像这样的透视投影矩阵
const float radians = (60.0f / 360.0f) * (float)Math.PI * 2.0f;
projectionMatrix = glm.perspective(radians, width / height, 0.01f, 1000f);
即使在应用此投影矩阵之后,这两个点也不会落在相同的 (X, Y) 坐标上,即落在屏幕上的同一像素上。
我错过了什么?这是 glLookAt 的预期行为,还是我使用/实施错误?
编辑: 投影矩阵应用于顶点着色器,就像这样:
void main(void) {
gl_Position = projectionMatrix * viewMatrix * modelMatrix * vec4(in_Position, 1.0);
}
EIDT 2: 这是我当前场景的录音,作为澄清。唯一随时间变化的是 camLookAt
向量。相机应该保持在相同的位置,但不知何故它似乎在移动:
编辑 3: 按照@NicoSchertler 的建议,我只是在 CPU 上进行了所有计算。 viewMatrix 乘法在上面完成,结果分别为 (2.1213, 0, -2.1213)
和 (2.8284, 0, -2.8284)
。现在我应用投影矩阵(参见上面我如何获得投影矩阵):
1.30, .00, .00, .00 .00, 1.73, .00, .00 .00, .00, -1.00, -.02 .00, .00, -1.00, 1.00
我得到以下向量
(2.75, 0.00, 2.10, 3.12)
(3.67, 0.00, 2.81, 3.83)
然后我将它们除以它们的 w
值,得到
(0.88, 0.00, 0.67, 1.00)
(0.96, 0.00, 0.73, 1.00)
所以他们显然不在彼此后面。
投影矩阵有问题吗?
However, this isn't the case, (...) the (X,Y) components of the two transformed points do not match.
坐标x/y不同的两个点并不代表它们不在彼此的后面。显然,它们具有不同的深度。相机位于该坐标系中的原点。如果你计算从相机到点的方向(即 normalize(p - 0)
),我们得到:
direction1 = {0.707107, 0, -0.707107}
direction2 = {0.707107, 0, -0.707107}
所以,从相机到两点的方向是相同的,因此它们在彼此的后面。
你还没有展示你是如何进行投影的。但这些点必须投射到同一位置。不过,透视投影有一点警告。投影点将有一个 w
分量,而不是 1
。您需要将点除以此 w
分量(透视划分)以找到实际投影点。然后,x/y 坐标应该实际匹配。