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

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

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

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

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

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

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

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

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

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

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

对不起,如果我在原始问题中没有说清楚.

最佳答案 如果你“对计算机图形不好”,如果多边形可以是透明的,那么在CPU(软件渲染)上进行操作将非常困难.

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

Cpu解决方案:

Soltuion#1(极其困难):

(我忘了这个算法的名字).

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

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

这可能非常难以正确.我认为这种方法在“Francis S. Hill”的“计算机图形使用OpenGL第二版”中进行了讨论 – 在其中一个练习中.

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

解决方案#2(更简单):

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

解决方案#3(计算成本高):
只需使用ray-tracing.你将获得完美的渲染效果(没有深度剥离和cpu解决方案#2的限制),但它的计算成本很高,因此你需要经常优化渲染程序.

底线:

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

–edit-1–

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

#2所需的知识是“纹理3d三角形渲染”(算法).这是一个相当复杂的话题.

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

–edit-2–

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

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

–edit-3–

I should note that the overall number of quads per subscene is around 30 (average). Definitely won’t go above 100.

如果你将分割多边形,它可以很容易地超过100.

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

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

这是应该工作的粗略算法大纲:

>准备场景中所有三角形的列表.
>删除背面三角形.
>找到在3d空间中相互交叉的所有三角形,并使用交叉线将它们分开.
>计算所有三角形的所有顶点的屏幕空间坐标.
>按画家算法的深度排序.
>为新基元准备额外列表.
>查找在2D(投影后)屏幕空间中重叠的三角形.
>对于所有重叠三角形,请检查其渲染顺序.基本上,将在另一个三角形“下方”呈现的三角形应该没有位于另一个三角形之上的部分.
8.1.为此,使用相机原点和三角形边缘将原始三角形分成几个子区域,然后检查区域是否符合已建立的排序顺序(为画家算法准备).通过使用由相机原点和三角形边创建的6个剪裁平面来分割现有的三​​角形来创建区域.
8.2.如果所有区域都符合渲染顺序,则保留三角形.如果没有,请从列表中删除三角形,并将它们添加到“新原语”列表中.
>如果新基元列表中有任何基元,请将列表与三角形列表合并,然后转到#5.

通过查看该算法,您可以轻松理解为什么现在每个人都使用Z缓冲区.

想一想,这对于专攻CG的大学来说是一次很好的训练.那种可能让你的学生讨厌你的运动.

点赞