在实现画家算法时,对多边形进行排序的正确方法是啥?

Posted

技术标签:

【中文标题】在实现画家算法时,对多边形进行排序的正确方法是啥?【英文标题】:What's the right way to order polygons when implementing the painter's algorithm?在实现画家算法时,对多边形进行排序的正确方法是什么? 【发布时间】:2017-07-21 18:12:21 【问题描述】:

我正在写一个图形app,并被建议使用z-buffer 或painters algorithm 来处理visibility problem。

我在 html5 画布中编写此代码,因此使用 z 缓冲区似乎非常昂贵。例如,如果它是一个 500x500 的画布,并且只需要循环 10 个多边形,这将是在 CPU 中完成的每帧 2,500,000 次迭代。我不知道这是否是一个很大的数字,但对于这个应用来说,这似乎是错误的做法。

painters 算法似乎更合适。基本步骤是:

1. Sort polygons based on their "z".
2. Paint all polygons, but paint the ones farthest away first.

但我对如何找到他们的 z 感到困惑。假设我们自上而下查看以下多边形:

如果我只是找到最大 z(离屏幕最远),红色会被认为更远。所以它会先画红色,然后再用橙色覆盖红色,即使红色在橙色前面。

对这些多边形进行排序的正确方法是什么?或者更一般地说,在实现画家算法时,如何确定多边形的顺序?

编辑: this 是我害怕滚动我自己的 z-buffer 的原因(在这个五年前的 i7 上遍历每个像素并随机为其分配一个 ~10FPS 的颜色)。

【问题讨论】:

复杂度是一样的。要么对 10 个(剪裁的)三角形进行排序,然后使用 250 万个 2D 像素操作盲目地绘制它们,要么使用 z-buffer,每个像素只添加一个 z-操作。只有当您的 CG 算法确定某些三角形完全被其他三角形遮挡时,这些好处才会出现。 【参考方案1】:

三个三角形可以循环地相互覆盖,这意味着不存在通用的排序算法。 相反,该问题通常通过沿重叠边缘切割重叠三角形来解决,形成新的三角形/多边形,它们完全位于彼此的任一侧。

所讨论的两个多边形可以通过顶点与另一个多边形的平面方程的有符号距离进行OTOH排序。

【讨论】:

是所有多边形都放入一个大列表然后运行排序算法,还是您应该尝试根据多边形是否首先在 x 和 y 上重叠来对它们进行分组? 按边界框(对齐到 xyz 或未对齐)或球体分组通常用于加快排序。【参考方案2】:

Z-排序通常比Z-缓冲慢。你拥有的多边形越多越好,那就是使用 Z-buffer。您对迭代的假设是错误的。 Z 缓冲不是在每个多边形的基础上进行迭代,而是在每个像素的基础上进行迭代。

所以你得到多少多边形并不重要。重要的是以像素为单位渲染的区域(重叠区域在每个它所属的多边形中计算多次)。所以你不能指望500x500 屏幕和10 多边形会得到10*500*500 迭代。

我不使用 HTML5 画布 进行编码,但除非您有直接的像素访问和阴影后台缓冲区并自己栅格化多边形(或者像 GLSL 中的片段着色器一样访问它),否则您将获得很难实现 z-buffering,即使它只是一个简单的 if 条件。我认为它也可以通过模板或 alpha 遮罩来完成,但从未这样做过。

z-sorting通常用于这些情况:

    您没有足够的内存来存储 Z-buffer

    这也表明您的多边形复杂性和计数很低...

    您已经对多边形进行了排序(由于创建它们的过程)

    你需要正确的透明度

但是,如果您的多边形与它们与相机的距离相交,则另一个答案涵盖了它,您需要将它们切割得更多。这种操作通常非常昂贵,以至于 z-sorting 的任何好处都被所消耗的时间所抵消。这就是为什么即使对于 #3 也使用 z-buffering 并且排序是通过这样的面部剔除来伪造的:

OpenGL - How to create Order Independent transparency?

或者使用光线追踪的形式:

Curved Frosted Glass SSS Shader?

在某些情况下,Z 排序(对网格渲染顺序进行排序)和 Z 缓冲(按多边形顺序)结合使用。举个例子:

Is it possible to make realistic n-body solar system simulation in matter of size and mass?

【讨论】:

以上是关于在实现画家算法时,对多边形进行排序的正确方法是啥?的主要内容,如果未能解决你的问题,请参考以下文章

数组排序是啥?

使用 STL 容器进行中位数计算时,正确的方法是啥?

通过 JavaScript 对 HTML 表格进行排序的最有效方法是啥?

使用与数组相同的算法对 ArrayList 进行排序

Python编码实现冒泡排序

对用于 Objective-C 运行时的 SIMD 类型和函数进行编码的正确方法是啥?