遮挡剔除3D变换的2D矩形?

时间:2013-05-16 08:19:40

标签: c graphics 3d geometry

所以,首先,我不擅长计算机图形。我正在尝试实现一个GUI工具包,其中一个功能是能够将3D转换应用于2D“图层”。 (一个图层只有一个Z坐标,作为预变换,它是一个二维轴对齐的矩形)

现在,这非常简单,直到你进行3D变换将图层推回去,需要将图层分割成多个多边形才能正确渲染,如图所示。而且因为我们可以拥有透明度,所以图层可能不会被完全遮挡,同时仍需要分割。

所以这里是一个描述问题和期望结果的插图。在这种情况下,蓝色图层(称为 B )位于红色图层的顶部( R ),同时具有相同的Z位置(但 B < / strong>在 R 之后添加。在这种情况下,如果我们旋转 B ,其前两个点将获得低于0的Z指数,而底部点将获得高于0的指数(锚点是唯一的点/线)保留为0)。

example

有人可以建议在CPU上执行此操作的好方法吗?我一直在努力寻找适合这种情况的合适的算法实现(在C ++或C中)。

编辑: 为了澄清自己,在管道的这个阶段,还没有渲染。我们只需要为每个图层生成一组多边形,然后表示图层的变换和遮挡几何。然后,如果需要,在需要时进行渲染(软件或硬件),但情况并非总是如此(例如,在进行命中测试时)。

编辑2: 我将二进制空间分区作为实现此目的的选项,但我只能找到一个实现(在GL2PS中) ,我不知道该怎么用。我对BSP的工作方式有一个模糊的理解,但我不确定如何将它们用于遮挡剔除。

编辑3: 我不打算在此阶段进行色彩和透明度混合。只是纯几何。透明度可以由渲染器处理,透支也可以。在这种情况下,蓝色多边形可以仅在红色多边形下绘制,但是对于更复杂的情况,可能需要深度排序或甚至分割多边形(如下所示的可怕情况的示例)。虽然视口是固定的,因为所有图层都可以在3D中变换,因此可以创建如下所示的形状。

所以我真正想要的是一种算法,它将几何分层 B 分成两个蓝色形状,其中一个将被绘制在“上方”和一个其中将在 R 下面绘制。 “下面”部分会被透支,是的,但这不是一个重大问题。所以 B 只需要分成两个多边形,这样当按顺序绘制这些多边形时,它似乎会切断 R 。无需担心混合。

circular

编辑4: 出于此目的,我们无法渲染任何内容。这一切都必须完全以几何形式完成(生成 2D 多边形)。这就是我最初的目标。

编辑5: 我应该注意每个子场景的四边形总数约为30(平均值)。绝对不会超过100.除非图层是3D变换的(这是出现此问题的地方),它们只是在绘制之前按Z位置排序的基数。具有相同Z位置的图层按照添加顺序(先进先出)绘制。

很抱歉,如果我在原始问题中没有说清楚。

2 个答案:

答案 0 :(得分:2)

如果你不熟悉计算机图形和#34;如果多边形可以透明,那么在CPU(软件渲染)上进行操作将非常困难。

最简单的方法是使用Depth Peeling technique的GPU渲染(OpenGL / Direct3D)。

Cpu解决方案

Soltuion#1(非常困难)

(我忘记了这个算法的名称)。

您需要将多边形B拆分为两个,例如,使用多边形A作为剪裁平面,然后使用painter算法渲染结果。 要做到这一点,您需要更改渲染例程,以便它们不再使用四边形,而是使用纹理多边形,此外您还必须编写/调试剪切例程,以便分割三角形在场景中他们不再打破paitner的算法。

大问题:如果你有很多多边形,这个解决方案可能会将场景分成无数个三角形。另外,自己编写纹理渲染代码并不是很有趣,因此建议使用OpenGL / Direct3D。

这可能非常难以做到。我认为这种方法在&#34;计算机图形学使用OpenGL第二版&#34; by#34; Francis S. Hill&#34; - 在他们的一个练习中的某个地方。

另请查看Hidden Surface Removal上的维基百科文章。

解决方案#2(更简单)

您需要实现多层z-buffer,最多可存储N个透明像素及其深度。

解决方案#3(计算成本高昂): 只需使用ray-tracing即可。您将获得完美的渲染结果(没有深度剥离和CPU解决方案#2的限制),但它的计算成本很高,因此您需要大量优化渲染例程。

底线:

如果您正在执行软件渲染,请使用解决方案#2或#3。如果您在硬件上渲染,请使用类似于深度剥离的技术,或在硬件上实现光线跟踪。

<强> - 编辑 - 1 -

实施#1和#2所需的知识是"line-plane intersection"。如果您了解如何使用平面将线条(在3d空间中)分割为两个,则可以轻松实现光线跟踪或剪切。

#2的所需知识是&#34;纹理3d三角渲染&#34; (算法)。这是一个相当复杂的话题。

为了实现GPU解决方案,您需要能够找到几个处理着色器的OpenGL教程。

<强> - 编辑 - 2 -

透明度是相关的,因为为了获得正确的透明度,您需要使用画家的算法从后到前(从最远到最近)绘制多边形。正确排序多边形是impossible in certain situation,因此必须将它们拆分,或者您应该使用列出的技术之一,否则在某些情况下会出现伪像/错误渲染的图像。

如果没有透明度,您可以使用硬件OpenGL实现标准zbuffer或绘图,这是一项非常简单的任务。

<强> - 编辑 - 3 -

  

我应该注意,每个子场景的四边形总数大约是30(平均值)。绝对不会超过100。

如果要分割多边形,它可以很容易地超过100。

有可能以这样的方式定位多边形,即每个多边形将分割所有其他多边形。

现在,2 ^ 29是536870912,但是,不可能用一个平面分割一个表面,使得在每个分割数量的多边形将加倍。如果将一个多边形分割为29个时间,则在最佳情况下您将获得30个多边形,如果分割平面不平行,则在最坏的情况下可能会有数千个多边形。

这应该有用的粗略算法大纲

  1. 准备场景中所有三角形的列表。
  2. 移除背面三角形。
  3. 查找在3d空间中相互交叉的所有三角形,并使用交叉线对它们进行拆分。line of intersection
  4. 计算所有三角形的所有顶点的屏幕空间坐标。
  5. 按画家算法的深度排序。
  6. 为新基元准备额外列表。
  7. 查找在2D(投影后)屏幕空间中重叠的三角形。
  8. 对于所有重叠三角形,请检查其渲染顺序。基本上是一个将要渲染的三角形&#34;低于&#34;另一个三角形应该没有位于另一个三角形之上的部分 8.1。为此,使用相机原点和三角形边缘将原始三角形分成几个子区域,然后检查区域是否符合既定的排序顺序(为画家的算法做好准备)。通过使用由相机原点和三角形边创建的6个剪裁平面来分割现有的三​​角形来创建区域。 enter image description here
    8.2。如果所有区域都符合渲染顺序,则保留三角形。如果他们不这样做,请从列表中删除三角形,并将它们添加到&#34;新原语&#34;列表。
  9. 如果新基元列表中有任何基元,请将列表与三角形列表合并,然后转到#5。
  10. 通过查看该算法,您可以轻松理解为什么现在每个人都使用Z缓冲区。

    来考虑一下,这对于专攻CG的大学来说是一次很好的训练。这种运动可能会让你的学生讨厌你。

答案 1 :(得分:0)

我要说出来给出更简单的解决方案,这可能不适合你的问题。为什么不直接更改您的图稿以防止出现此问题。

在问题1中,只需在Maya或其他任何事先划分多边形。对于3线问题,再次在交叉点划分多边形以防止战斗。预先计算的解决方案总是比在飞行时更快 - 特别是在有限的硬件上。从专业经验来看,我可以说它也有规模,它可以扩展。它只需要从艺术方面和技术评论中进行一些调整,以确保“非法”创建任何内容。你可能最终得到更多的聚合物这样做而不是动态渲染,但至少你不需要对可能无法完成任务的CPU进行大量的数学计算。

如果您无法控制图稿管道,这将无法正常工作,因为编写某种转换器所需的时间比启动并运行BSP细分例程要长。不过,KISS通常是最好的解决方案。