当前位置: 首页 > 知识库问答 >
问题:

OpenGl视图矩阵-错误的"相机"方向和位置

贲宜春
2023-03-14

症状是,“摄像头位置”似乎围绕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(数学::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
            );
    }

正如OpenGl所预期的那样,matrix4d的内存布局是以列为主的。所有其他功能,如点和交叉都经过单元测试。

顶点着色器:

#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);

共有1个答案

曾丰茂
2023-03-14

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

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

否定这一点当然意味着你将在世界空间中使用右手坐标系(这就是经典GL所做的)。如果你不想这样,你也可以改变投影矩阵,让它看起来像z。

 类似资料:
  • 本章节主要给大家引入视图矩阵和投影矩阵两个新的概念,如果你没有图形学基础,对这两个概念暂时还没有认知,也没有关系。通过前面的学习相信你对平移、旋转等矩阵有了一定的认知,至于投影和视图矩阵和平移、旋转等模型矩阵一样也会对WebGL顶点进行坐标变换,至于如何变换下面会逐步讲解。 在学习本章节之前,如果你对Three.js已经有了一定的了解,可以尝试从WebGL视图矩阵和投影矩阵的角度去深入理解Thre

  • 我试图从opengl FrameBuffer中保存的深度数据渲染三维点云。基本上,我从不同的n个视点(已经知道)对以(0,0,0)为中心的渲染模型取了不同的深度样本。我成功地保存了深度图,但现在我想从这些深度图中提取x,y,z。为此,我从图像向世界反投影点。为了得到世界坐标,我使用以下方程P=K_inv[Rt]_inv*P。来计算世界坐标。 为了计算图像的本质矩阵,我使用了来自opengl相机矩阵

  • 问题内容: 我试图在OpenGL中使用gluUnProject,首先我需要获取projectoin,model_view和viewort矩阵。根据我在网上找到的例子 但是我收到错误消息“ ValueError:glGetFloatv需要1个参数(pname),收到2:(GL_PROJECTION_MATRIX,[])” 那么,我应该使用什么来获取这些矩阵? 问题答案: 也许: 之后在变量中应该是投

  • 我正在开发一些游戏,以便学习OpenGL。 我正在尝试实现一种方法来拾取对象(例如,镐、枪等)。 这个想法是,即使在相机移动或旋转之后,这个物体也会固定在相机前面。 当我向前、向后、向左、向右、向上或向下移动时,我可以通过在相机正前方设置对象的位置来使对象跟随我。 然而...当相机旋转/倾斜(向上、向下、向左、向右看...)问题就开始了。 在这种情况下,一切都很好(向上、向下、向左、向右、向右倾斜

  • 当通过命令行启动我的程序时,出现这样的问题:OpenCV错误:图像步骤错误(矩阵不连续,因此它的行数不能改变)un CV::MAT::Reshape,文件C:\builds\2_4_packslave-win64-vc12-shared\OpenCV\modules\core\src\matrix.cpp,第802行。