将3D点转换为屏幕的透视投影行为

时间:2018-12-08 16:43:47

标签: c++ 3d rendering perspectivecamera projection-matrix

我正在用c ++重新编码渲染管道,但使其工作起来有些麻烦。 我的意思是,它正在工作,但不符合我的预期。 为简单起见,我使用透视投影矩阵构建将3D点转换为2D点,如下所示:

我的draw_edge函数仅获取世界空间中的2个点,并进行调用以将这些点转换为屏幕坐标:

void Scene::draw_edge(const geometry::Point<float,4>& p1, const geometry::Point<float,4>& p2, gui::Color c) const
{

   geometry::LineSegment ls(p1.ReduceToPoint3DAsPoint(), p2.ReduceToPoint3DAsPoint());
   std::optional<geometry::LineSegment> cls = camera.VisiblePart(ls);

   if(cls != std::nullopt)
     {
        auto p1Persp = Perspective((*cls).GetBegin().ExtendedPoint4DAsPoint());
        auto p2Persp = Perspective((*cls).GetEnd().ExtendedPoint4DAsPoint());

        om::Vector<2,float> p1Projection2D;
        om::Vector<2,float> p2Projection2D;

        p1Projection2D[0] = p1Persp.At(0);
        p1Projection2D[1] = p1Persp.At(1);
        p2Projection2D[0] = p2Persp.At(0);
        p2Projection2D[1] = p2Persp.At(1);

        gui->render_line(p1Projection2D,p2Projection2D,c);
     }
}

此功能用于通过应用透视矩阵实际变换我的点,然后将我的坐标除以'w'。

geometry::Point<float,3> Scene::Perspective(const geometry::Point<float,4>& point) const
  {
    geometry::Transform perspectiveTransform = camera.GetPerspectiveProjection();
    geometry::Point<float,4> pointHomogenous = perspectiveTransform.TransformTo(point);
    om::Vector<3,float> normalized;
    for(int i = 0; i < 3; i++)
      {
    normalized[i] = pointHomogenous.At(i) / pointHomogenous.At(3);
      }

    return geometry::Point<float,3>(normalized);
  }

此功能用于构建我的透视投影矩阵

geometry::Transform Camera::GetPerspectiveProjection() const
  {
    float nearValue = position.Dist(frustum.nearPlane);
    float farValue = position.Dist(frustum.farPlane);
    float rightValue = nearValue / focaleDistance;
    float leftValue = -nearValue / focaleDistance;
    float topValue = (aspectRatio * nearValue) / focaleDistance;
    float bottomValue = -(aspectRatio * nearValue) / focaleDistance;

    auto perspective = geometry::Transform(nearValue, farValue, rightValue, leftValue, topValue, bottomValue);
    //auto perspectiveInverse = perspective.GetMatrix().Reverse();
    //perspective = geometry::Transform(perspectiveInverse);

    return perspective;
  }

正如您所看到的,我已经对倒置发表了评论,这就是这篇文章的重点,我稍后会再讨论。

最后,构建透视图矩阵的函数:

Transform(float near, float far, float right, float left, float top, float bottom)
{
  transform[0][0] = (2*near)/(right - left);
  transform[0][1] = 0.0f;
  transform[0][2] = (right + left)/(right - left);
  transform[0][3] = 0.0f;

  transform[1][0] = 0.0f;
  transform[1][1] = (2*near)/(top - bottom);
  transform[1][2] = (top + bottom)/(top - bottom);
  transform[1][3] = 0.0f;

  transform[2][0] = 0.0f;
  transform[2][1] = 0.0f;
  transform[2][2] = -((far + near)/(far - near));
  transform[2][3] = -((2*near*far)/(far - near));

  transform[3][0] = 0.0f;
  transform[3][1] = 0.0f;
  transform[3][2] = -1.0f;
  transform[3][3] = 0.0f;
}

因此,既然所有需要的代码都已公开,这就是我的问题。 当我使用透视投影的反转(通过取消注释两行)时,结果看起来正确如下:

inversed matrix

但是,如果我评论我的倒置,结果如下:

no inversed matrix

所以我的问题是我不明白为什么我需要使用逆矩阵来获得看起来正确的结果?我的意思是,我已经阅读了所有有关透视投影的文档,没有人说过对透视投影矩阵求逆。

感谢阅读,请随时询问更多信息

0 个答案:

没有答案