【问题标题】:OpenGl view matrix - wrong "camera" orientation and positionOpenGL视图矩阵 - 错误的“相机”方向和位置
【发布时间】:2015-05-15 21:36:35
【问题描述】:

症状是,“相机的位置”似乎围绕 x 轴镜像(负 z 而不是正 z),并且“相机的方向”与预期相反。
在其他换句话说,我必须将相机旋转 180 度并向前移动才能看到任何效果图。
在我见过的所有 OpenGL 相机教程中,相机位置总是有一个正 z 坐标。也许代码中只有一个符号错误,但我没有看到。我还发布了相应的着色器代码。
我的对象在世界坐标 z=0.1 处渲染。

相机实例的初始化显示在以下几行中

m_viewMatrix = math::Matrix4D::lookAt(m_cameraPosition, m_cameraPosition + m_cameraForward, m_cameraUp);

在哪里

m_cameraForward(math::Vector3D(0.0f, 0.0f, -1.0f)),
m_cameraRight(math::Vector3D (1.0f, 0.0f, 0.0f)),
m_cameraUp(math::Vector3D(0.0f, 1.0f, 0.0f)),
m_cameraPosition(math::Vector3D(0.0f, 0.0f, 20.0f))

结果是黑屏。当我将相机位置更改为 m_cameraPosition(math::Vector3D(0.0f, 0.0f, -20.0f) 一切正常。

函数lookAt由以下几行给出:

Matrix4D Matrix4D::lookAt(
        const Vector3D& f_cameraPosition_r,
        const Vector3D& f_targetPosition_r,
        const Vector3D& f_upDirection_r)

    {
        const math::Vector3D l_forwardDirection = (f_targetPosition_r - f_cameraPosition_r).normalized();

        const math::Vector3D l_rightDirection = f_upDirection_r.cross(l_forwardDirection).normalized();
        const math::Vector3D l_upDirection = l_forwardDirection.cross(l_rightDirection); // is normalized
        return math::Matrix4D(
            l_rightDirection.x, l_rightDirection.y, l_rightDirection.z, l_rightDirection.dot(f_cameraPosition_r*(-1.0f)),
            l_upDirection.x, l_upDirection.y, l_upDirection.z, l_upDirection.dot(f_cameraPosition_r*(-1.0f)),
            l_forwardDirection.x, l_forwardDirection.y, l_forwardDirection.z, l_forwardDirection.dot(f_cameraPosition_r*(-1.0f)),
            0.0f, 0.0f, 0.0f, 1.0f
            );
    }

matrix4d 的内存布局是列主要的,正如 OpenGL 所期望的那样。 dot 和 cross 等所有其他函数都经过单元测试。

顶点着色器:

#version 430

in layout (location = 0) vec3 position;
in layout (location = 1) vec4 color;
in layout (location = 2) vec3 normal;

uniform mat4 pr_matrix; // projection matrix
uniform mat4 vw_matrix = mat4(1.0); // view matrix <------
uniform mat4 ml_matrix = mat4(1.0); // model matrix

out vec4 colorOut;

void main()
{
    gl_Position = pr_matrix * vw_matrix * ml_matrix * vec4(position,1.0);
    colorOut = color;
}

片段着色器:

#version 430

out vec4 color;
in vec4 colorOut;

void main()
{
    color = colorOut;
}

编辑(添加透视矩阵):

Matrix4D Matrix4D::perspectiveProjection(
        const float f_viewportWidth_f,
        const float f_viewportHeight_f,
        const float f_nearPlaneDistance_f,
        const float f_farPlaneDistance_f,
        const float f_radFieldOfViewY_f)
    {
        const float l_aspectRatio_f = f_viewportWidth_f / f_viewportHeight_f;
        const float l_tanHalfFovy_f = tan(f_radFieldOfViewY_f * 0.5);
        const float l_frustumLength = f_farPlaneDistance_f - f_nearPlaneDistance_f;
        const float l_scaleX = 1.0f / (l_aspectRatio_f * l_tanHalfFovy_f);
        const float l_scaleY = 1.0f / l_tanHalfFovy_f;
        const float l_scaleZ = - (f_farPlaneDistance_f + f_nearPlaneDistance_f) / l_frustumLength;
        const float l_value32 = -(2.0f*f_farPlaneDistance_f*f_nearPlaneDistance_f) / l_frustumLength;

        return Matrix4D(
            l_scaleX,   +0.0f,      +0.0f,      +0.0f,
            +0.0f,      l_scaleY,   +0.0f,      +0.0f,
            +0.0f,      +0.0f,      l_scaleZ,   l_value32,
            +0.0f,      +0.0f,      -1.0f,      +0.0f);

【问题讨论】:

  • 我们也可以看看你的投影矩阵吗?眼睛空间有一些约定,你可以随意定义它们,但你必须对它们保持一致。在经典 GL 中,眼睛空间是用左手定义的,相机朝向 -z 方向。投影矩阵将其考虑在内并翻转到右手坐标空间。在一般情况下,投影矩阵还决定观察方向(甚至位置,如果你想以这种方式看东西,虽然没有人定义相机不在原点的眼睛空间,但它会起作用)。
  • 感谢您的回复。我添加了透视矩阵(在我的示例中使用)。视野以弧度表示

标签: opengl 3d camera


【解决方案1】:

您的投影矩阵遵循“经典”OpenGL 约定:在眼睛空间(矩阵的最后一行)中的观察方向是 (0,0,-1)。

但是,您的视图矩阵不遵循该约定:您必须将 否定 正向放入矩阵中(也用于计算那里的平移 z 分量)。在其当前形式中,视图矩阵只是旋转,以便将正向映射到 +z。

否定这一点当然意味着您将对世界空间使用右手坐标系(这是经典 GL 所做的)。如果您不希望这样,您也可以将投影矩阵更改为实际查看 +z。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-04-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-23
    • 1970-01-01
    相关资源
    最近更新 更多