“假3D”棱镜的壁的渲染顺序

时间:2018-11-09 01:09:11

标签: algorithm 3d geometry 2d rendering

我正在使用Python和pygame开发“假3D”游戏。 gfx仅由使用不同大小和颜色的2D图元创建的棱镜组成:

enter image description here

游戏gfx的工作原理:

enter image description here

问题出现在第4点,当我想按正确的顺序在渲染队列中对墙进行排序(确定哪一个是最接近的墙并且必须首先渲染,哪个是第二个,最后一个是最后一个)时等)。

目前,要对墙壁进行分类,我会移除所有不可见的墙壁,并测量wall和{{1}}之间的最短距离。它起作用...但是仅当场景中存在一个多边形时。示例(2个多边形):

enter image description here

我可以处理这种特定类型的问题,但是我不知道将来是否还会有其他问题。我的问题:是否有任何算法(可以起作用...)可以按正确的顺序对墙壁进行排序,并且我可以在脸上露出微笑来渲染它们?

1 个答案:

答案 0 :(得分:1)

我猜我们可以公平地假设多边形不相交。在这种情况下,我们不需要拆分任何内容。但是,找到正确的顺序在计算上仍然很繁重。尽管可能可以提出一种增量方法,该方法只能逐帧更新必要的内容。

这就是问题。在您的2多边形示例中,将顺序基于直线的两个最接近的点显然不起作用,因为它们的视图方向不同。但是,如果选择具有相同视图方向的点(在它们重叠的区域中),您将清楚地看到A在B的前面。因此,我们需要做什么:

首先找到所有可见的墙。我们将为这些墙创建可见性图。因此,创建一个图形,其中每面墙都由一个节点表示。最后,您将对该图进行拓扑排序以获取绘制顺序。现在,我们如何找到边缘,即有关另一堵墙前面是哪堵墙的信息?为此,首先找到重叠的墙对(挤压墙)。您可能想要使用AABB树之类的加速数据结构来加快速度。

这时,我们需要对视图方向进行一维参数化。方向和x轴之间的角度可能效果很好(a = atan2(lineY - playerY, lineX - playerX)),尽管它具有您需要处理的烦人的周期性。现在,我们将只考虑两壁的原始多边形边缘(不考虑挤压壁)。找到两条线的一维间隔(例如,线1在10°至35°之间,线2在20°至135°之间)。如果这两个间隔不重叠,则可以跳过此对,因为它们的相对顺序无关紧要。如果是这样,则找到重叠间隔中的任何点(例如25°),找到对应的视图方向(x = playerX + cos(25°), y = playerY + sin(25°))和对应于该方向的线上的点(例如,通过计算与视图射线)。然后,只需计算沿该射线的两条线的距离即可。选择重叠间隔中的哪一点都没有关系,因为直线是线性的,原始多边形不相交。如果到线1的距离小于到线2的距离,则在可见性图表上添加从线1到线2的有向边(这意味着线1在线2的前面),否则添加反向边。

最后,计算图的拓扑顺序,您便拥有绘制顺序。

选项2

这里是上述方法的替代方法,对于动态渲染而言可能更有效。这个想法基于this publication

首先对场景进行三角剖分,即用三角形填充空隙(此操作只需执行一次)。然后,我们的可见性图将存储三角形(而不是边缘)。对于从内部看到的每个三角形边缘,将三角形的边缘添加到入射到该边缘的相邻三角形。最后,再次计算拓扑排序并按此顺序绘制墙壁(跳过空三角形)。

动态情况下的效率来自以下事实:您只需要对图形进行少量更新即可。对于每个边缘,您都想确定是从正面还是背面看到它们。因此,仅当视点越过边缘指定的无限线时,边缘的方向才会反转。如果找到所有这些边缘(自上一帧以来改变了方向),则可以更新图形并进行相应的排序。