透视投影 - 如何投影相机后方的点?

9

我正在使用Java编写自己的软件光栅化器,但遇到了一些问题...请看一下样例图像:

图像

这个样例只是在平面上绘制了一个简单的方格网。一切都很正常,直到我把相机移动到足够近的位置,使得某些点移动到它后面。之后,它们就不再被正确地投影了,就像你所看到的那样(垂直线 - 应该在相机后面的点被投影在屏幕顶部)。

我的变换矩阵和向量与DirectX使用的相同(透视投影使用PerspectiveFovLH,相机使用LookAtLH)。

我正在使用以下变换方法来投影3D点:

  1. 3D vector to be transformed is created.
  2. Vector is multiplied by ViewProjection matrix.
  3. After that, point is transformed to screen using following method:

    // 'vector' is input vector in projection space
    // projection to screen
    double vX = vector.x / vector.z;        
    double vY = vector.y / vector.z;
    
    //translate
    //surfaceW is width and surfaceH is height of the rendering window.
    vX = (( vX + 1.0f) / 2.0f) * surfaceW;
    vY = ((-vY + 1.0f) / 2.0f) * surfaceH;
    
    return new Vector3(vX, vY, vector.z);
    
正如我之前所说的,直到点移动到相机后面才会出现问题。事实上,我可以通过测试其最终变换后的Z值来确定点是否在相机后面,但由于我正在绘制线条和其他基于线条的对象,因此不能跳过该点。
然后,我尝试根据MSDN上的《Direct3D变换管道》文章设置我的转换管道。
不幸的是,我也没有成功(结果相同),因此任何帮助都将不胜感激,因为我有些卡在这里了。
谢谢。
最好的问候, Alex

你是否正确设置了相机的前剪裁平面?并在渲染时考虑到它? - ChrisF
我的 zNear 平面设置为 1,zFar 平面设置为 1000 单位。我尝试更改这些值,但问题仍然存在。有什么建议吗? - Alex
我已经有一段时间没有做这样的事情了,但是在投影线之前,您需要执行与前裁剪平面的交集。 - ChrisF
1个回答

10

你需要在三维空间中将该线与前裁剪平面相交,并截断该线段,以便只绘制可见的线段:

             |
             |
             |
x------------+-----------o
             |
             |
             |   * - camera
             |
             |
             |
       clipping plane
你有一条线段 xo ,其中 x 在剪裁平面的前面, o 在其后面。将该线段与剪裁平面相交,生成点 + 。你知道哪个点 x 和 o 是可见的,所以从 x 到 + 绘制一条线段。 < p>这样,您就不会投影出在相机后面的点。

2
谢谢。在透视变换之后,在剪辑空间中进行,透视除法之前(使用齐次坐标和w),这样做可以吗? - Alex
@Alex 是的。我相当确定您可以在裁剪空间或甚至NDC中完成这个操作。 - Samie Bencherif

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接