Frustum平面微积分

时间:2011-09-11 13:47:51

标签: 3d clipping

我正在从头开始编写一个简单的JavaScript 3D引擎,使用Canvas和类似基元的盒子(例如Minecraft)。我正在实施尽可能多的优化,到目前为止,我已经背面剔除和隐藏面部遮挡,但我无法弄清楚如何做截头剔除最佳方式。

我已经尝试过2D剔除,但这有一个我无法解决的具体问题:如果4点平面的单个顶点在相机后面,它仍然被绘制但完全失真(x和y坐标反转我认为) - 见图像。

我开始认为如果不使用更复杂的数学和渲染序列,这就没有真正的解决方案。

At first everything's ok

enter image description here

我试图限制2D屏幕内的顶点x和y坐标,只要4个顶点中至少有一个仍然在屏幕内(见下文),但这完全扭曲了正方形面(虽然我猜我可以使用更多花哨的数学和其他三角形。)

enter image description here

我在OpenGL方面有一些经验,它完全不同地渲染东西,所以这甚至不是问题。

我是否有机会在不拉扯头发的情况下修理它?


解决方案

最终解决方案是在进行2D投影然后进行屏幕剪裁之前,在3D 中测试8个顶点与近剪裁平面中的每一个。

这是第二个裁剪步骤,第一个是使用半径为sqrt(3/2)*boxSideLength的边界球测试框是否完全位于裁剪平面的后面。

其他三角形(在这种情况下实际上是点)过于复杂和数学密集,这个解决方案并不完美但很漂亮。

2 个答案:

答案 0 :(得分:4)

您无法将相机后面的3d点投影到2d屏幕空间并让它有任何意义。所以你需要定义至少一个近平面来剪辑。将点从世界空间转换为相机空间后,但在投影到屏幕空间之前,您需要进行一些剪裁。您需要定义一个近平面,例如z = 1或接近但在摄像机前面的东西,并将定义一个空间,其中点可以投影到屏幕空间中。

您有三个选项,第一个是多边形中的任何点落在近平面后面,然后不绘制整个多边形。这很简单但通常是不可接受的。将每个点与近平面进行比较(如果polygon.points[i].z < near.z)。但这会使多边形消失,并在屏幕边缘看似随机地重新出现。

您的第二个选择是将多边形剪切到近平面。对于三角形,如果所有三个点都在近平面后面,则不绘制。如果后面有两个点,则将两个线段剪切到近平面并绘制三角形。如果一个点在近平面后面,则剪切并制作两个新三角形并绘制。如果没有人在近平面后面那么只是画画。如果我不是通过手机发布这个,我会详细介绍,但希望这是有道理的。

最后,您可以进行完整的fustrum裁剪,而不是仅仅剪裁到您的近平面,剪辑可见平截头体的所有6个边。

对于这些方法中的每一种都有优化算法,但我将从基础开始并继续前进。每一步基本上都是最后一步的延伸,所以我先从第一步开始然后变得更复杂,直到你得到你正在寻找的视觉和性能水平。

答案 1 :(得分:1)

Look up clippingCohen-Sutherland是一种相当容易使用的方法。链接的维基百科页面甚至还有一些用于实现它的C / C ++代码。

如果你介绍像gouraud阴影和纹理映射之类的东西,你会发现剪切后,w除法会使事物非常扭曲(即纹理和颜色插值看起来不对)。因此,我经常更喜欢在3D中做像Cohen-Sutherland这样的事情。