【问题标题】:glLookAt moves camera position when lookAt is moved - role of projection matrix?当lookAt移动时glLookAt移动相机位置 - 投影矩阵的作用?
【发布时间】:2017-12-08 15:06:11
【问题描述】:

简短版:我正在使用带有透视投影矩阵的 glLookAt 视图矩阵,我想知道为什么 camLookAt 向量(我正在查看的点)的变化会导致改变相机的位置。

长版:我正在使用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)    

所以他们显然不在彼此后面。

投影矩阵有问题吗?

【问题讨论】:

    标签: opengl sharpgl


    【解决方案1】:

    但是,情况并非如此,(...) 两个变换点的 (X,Y) 分量不匹配。

    具有不同 x/y 坐标的两个点并不意味着它们不在彼此后面。显然,它们有不同的深度。相机位于该坐标系中的原点。如果你计算从相机到点的方向(即normalize(p - 0)),我们得到:

    direction1 = {0.707107, 0, -0.707107}
    direction2 = {0.707107, 0, -0.707107}
    

    所以,从相机到两个点的方向是相同的,因此它们彼此落后。

    你还没有展示你是如何进行投影的。但是这些点必须投影到同一位置。不过,透视投影有一点需要注意。投影点将有一个不是1w-组件。您需要将点除以这个w-component(透视除法)才能找到实际的投影点。然后,x/y 坐标实际上应该匹配。

    【讨论】:

    • 谢谢,所以这确实是一个投影问题。我的帖子底部描述了我是如何进行投影的。不确定,但我认为没有必要在着色器中除以w。我认为 OpenGL 会在着色器完成后自动执行此操作,对吗?
    • 是的,没错。 OpenGL 负责透视分割。您是否正确上传了矩阵(即按列优先顺序)?
    • 好吧,我在 SharpGL 中将它作为 matrix.to_array() 传递。这就是示例中的操作方式。我想如果我以错误的顺序通过它,场景看起来不会像 3D 场景。但是场景看起来不错,我可以用相机四处移动,并且对象按预期渲染。唯一的问题是,当我移动camLookAt 而保持camPosition 固定时,相机的位置似乎略有变化。
    • 看起来相机的位置有点“落后”camPosition。如果我将camLookAt 向左移动,那么相机似乎向右移动了一点。
    • 谢谢 Nico,我找到了。 GLMNet 的perspective 返回一个矩阵,其(3, 3) 条目为1.0。但是,其他透视实现会在(3, 3) 处创建一个带有0.0 条目的矩阵。我改变了它,现在一切正常。似乎是 GLMNet 错误。
    猜你喜欢
    • 2015-04-11
    • 2018-10-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-26
    • 1970-01-01
    相关资源
    最近更新 更多