3d 平截体平面演算

3d 平截体平面演算,3d,clipping,3d,Clipping,我正在从头开始编写一个简单的JavaScript 3D引擎,使用画布和盒状原语(就像Minecraft一样)。我正在实施尽可能多的优化,到目前为止,我有背面剔除和隐藏面遮挡,但我不知道如何以最佳方式进行平截体剔除 我尝试过2D消隐,但有一个特定的问题我无法解决:如果一个4点平面的一个顶点在相机后面,它仍然被绘制,但完全扭曲(我认为x和y坐标是相反的)-参见图片 我开始认为,如果不使用更复杂的数学和渲染序列,就没有真正的解决方案 我试图限制2D屏幕内的顶点x和y坐标,只要4个顶点中至少有一个仍

我正在从头开始编写一个简单的JavaScript 3D引擎,使用画布和盒状原语(就像Minecraft一样)。我正在实施尽可能多的优化,到目前为止,我有背面剔除和隐藏面遮挡,但我不知道如何以最佳方式进行平截体剔除

我尝试过2D消隐,但有一个特定的问题我无法解决:如果一个4点平面的一个顶点在相机后面,它仍然被绘制,但完全扭曲(我认为x和y坐标是相反的)-参见图片

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

我试图限制2D屏幕内的顶点x和y坐标,只要4个顶点中至少有一个仍在屏幕内(见下文),但这会完全扭曲方形面(尽管我想我可以使用更奇特的数学和额外的三角形)

我有一些OpenGL的经验,它呈现的东西完全不同,所以这甚至不是一个问题

我有没有机会不拉扯头发就把它修好


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

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

额外的三角形(在本例中实际上是点)过于复杂和数学密集,这个解决方案并不完美,但相当漂亮。

。这是一种相当容易使用的方法。链接的维基百科页面甚至有一些C/C++代码来实现它


如果你引入像古劳德着色和纹理贴图这样的东西,你会发现剪切后的w分割仍然会明显扭曲东西(即纹理和颜色插值看起来是错误的)。因此,我通常最好在3D中使用科恩·萨瑟兰(Cohen Sutherland)这样的方法。

你不能将相机后面的3D点投影到2d屏幕空间中,让它有任何意义。因此,您需要至少定义一个要剪裁到的近平面。将点从世界空间转换为摄影机空间后,但在投影到屏幕空间之前,需要进行一些剪裁。您需要定义一个近平面,类似于
z=1
或靠近但在摄影机前面的某个平面,并将定义一个可以将点投影到屏幕空间的空间

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

第二个选项是将多边形剪裁到近平面。对于三角形,如果所有三个点都在近平面后面,则不绘制。如果两点在后面,则将两条线段剪裁到近平面并绘制三角形。如果一个点位于近平面的后面,则剪裁并制作两个新三角形并绘制。如果没有人在近平面后面,那么就画。如果我不是在手机上发这封信,我会更详细地说,但希望这是有意义的

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


这些方法中的每一种都有优化算法,但我将从基础开始,然后继续工作。每一步基本上都是最后一步的延伸,所以我会从第一步开始,然后变得更复杂,直到你得到你想要的视觉和性能水平

目前已经实现了近平面和远平面剪裁(因为有可用的数据),否则我会进行二维剪裁(到屏幕),这使得数学计算比计算每个平面的法线和测试点要简单得多。所以我唯一错过的第二步是生成额外的三角形。。。我会调查的。