Processing 如何在深度排序的半透明对象上避免这种损坏? 无效设置{ 尺寸600、480、P3D;可暗示的深度排序; } 抽真空 { 背景0; 平移宽度/2,高度/2;填充颜色255255,84; 冲程重量0; 翻译-40,0,1;sphere80; 平移2*40,0,0;球体80; //因腐败而失败:http://i.imgur.com/GW2h7Qv.png }

Processing 如何在深度排序的半透明对象上避免这种损坏? 无效设置{ 尺寸600、480、P3D;可暗示的深度排序; } 抽真空 { 背景0; 平移宽度/2,高度/2;填充颜色255255,84; 冲程重量0; 翻译-40,0,1;sphere80; 平移2*40,0,0;球体80; //因腐败而失败:http://i.imgur.com/GW2h7Qv.png },processing,Processing,注:sphereDetail无需应用。sphereDetail60导致失败并失去左重叠: 要理解为什么会发生这种情况,你必须了解引擎盖下发生了什么 以三角形思考 调用sphere函数时,处理实际上是绘制一组三角形。如果运行以下简单程序,您可以看到: 尺寸500500,P3D; 平移宽度/2,高度/2; 球体100; 在代码中,您已选择不绘制轮廓,但处理过程仍在绘制一组三角形以绘制球体。以下是它使用sphereDetail10绘制的内容: 关键是,你需要停止看到球体,看到组成这些球体的三角形 深度

注:sphereDetail无需应用。sphereDetail60导致失败并失去左重叠:


要理解为什么会发生这种情况,你必须了解引擎盖下发生了什么

以三角形思考 调用sphere函数时,处理实际上是绘制一组三角形。如果运行以下简单程序,您可以看到:

尺寸500500,P3D; 平移宽度/2,高度/2; 球体100; 在代码中,您已选择不绘制轮廓,但处理过程仍在绘制一组三角形以绘制球体。以下是它使用sphereDetail10绘制的内容:

关键是,你需要停止看到球体,看到组成这些球体的三角形

深度缓冲 因此,OpenGL和Processing使用深度缓冲来确定何时不绘制其他内容后面的内容

我只想复制一部分,这比我能做的要好得多:

考虑绘制两个三角形A和B的示例:

如果我们先画B,然后画A,深度缓冲区将看到新的 来自A的像素比之前由B绘制的像素更接近,因此 会把他们拉过头顶。如果我们按相反的顺序画A 然后是B,深度缓冲区将看到像素进入 从B开始的距离比A已经绘制的距离远,因此它将 丢弃它们。无论哪种情况,我们都会得到正确的结果:A在顶部, 后面藏着B

当你画一个不透明的球体时,你实际上是在画一堆不透明的三角形。处理将以球体到三角形算法生成的任意顺序绘制这些三角形。这适用于不透明对象,因为处理将检查Z缓冲区,然后跳过已绘制三角形后面的三角形。这基本上和OpenGL开箱即用一样聪明

透明度问题 再次引用:

但是如果这个几何体是alpha混合的,那么B部分可见呢 穿过半透明的三角形?如果我们画B,这仍然有效 首先,然后A在顶部,但如果我们画A,然后是B,则不会 在这种情况下,深度缓冲区将从B获得一个像素,请注意 它已经从图像中画出了一个更接近的像素,但它没有办法处理 在这种情况下。它的唯一选择是绘制B像素 将给出错误的结果,因为它将混合更多 远处的B在较近的A的顶部,而阿尔法混合不是 交换的,或者它可以完全丢弃B。不好

问题是,这不适用于透明三角形。请记住,处理是以算法生成的任何顺序绘制三角形,它使用Z缓冲区来决定何时跳过已绘制三角形后面的三角形。但我们不希望它跳过任何三角形!我们想画每个三角形,因为我们想通过前面的三角形看到后面的三角形

例如,如果我们在前面画一个透明的灰色球体,然后在它后面画一个红色球体,我们将看不到红色球体

尺寸500500,P3D; 平移宽度/2,高度/2; 仰泳; //前灰球 填充255,255,255,64; 球体100; //背红球 平移0,0,-500; 填充255,0,0,64; 球体100; 我之所以在这里使用整个球体是因为我很懒,但是想象一下,每个球体中的单个三角形都会发生这样的问题。这就是为什么你能在灰色球体中看到这些人工制品,同样的原因你不能在灰色球体后面看到红色球体。OpenGL先绘制灰色球体,然后跳过红色球体,因为它知道它位于前球体的后面。这是不透明对象的正确行为,但我们通过增加透明度使事情变得复杂

汇票事宜 相反,如果我们在绘制前灰色球体之前绘制后红色球体,那么我们可以通过灰色球体看到红色球体:

尺寸500500,P3D; 平移宽度/2,高度/2; 仰泳; //背红球 平移0,0,-500; 填充255,0,0,64; 球体100; //前灰球 翻译0,0,500; 填充255,255,255,64; 球体100; 请注意,由于三角形顺序问题,我们仍然可以在每个球体内看到瑕疵。这与我们在灰色球体之后绘制红色球体时看不到红色球体的原因相同

现在,要解决三角形的问题,绘制顺序很重要。就像在绘制红色球体后必须绘制前面的灰色球体一样,必须从后面到前面绘制三角形,这样OpenGL就不会跳过它确定的任何三角形 找到一个已经画好的三角形。这是一个巨大的颈部疼痛

救援行动 幸运的是,Processing为您提供了一个选项。这是可暗示的深度排序函数。启用此选项后,处理将根据三角形三个顶点的平均Z位置对每个三角形进行排序,然后按该顺序绘制它们。启用此选项后,我们可以在前面的灰色球体之后绘制后面的红色球体,处理将为我们排序三角形,并在到达OpenGL之前按正确的顺序绘制它们:

尺寸500500,P3D; 可提示的\u深度\u排序; 平移宽度/2,高度/2; 仰泳; //前灰球 填充255,255,255,64; 球体100; //背红球 平移0,0,-500; 填充255,0,0,64; 球体100; 请注意,我们可以看到后面的红色球体,即使我们在前面的灰色球体后面绘制它。处理是代表我们进行干预,并在OpenGL中实际绘制三角形之前对其进行排序。这也会修复每个球体内的瑕疵,因为三角形在每个球体中排序,而不仅仅是在球体之间

交叉口问题 请记住,三角形按其3个顶点的平均Z位置排序。这是相交三角形的问题。这是你们问题的症结所在

从中,假设有两个三角形A和B相交,如下所示:

无法对这些三角形进行排序,因为我们需要 将B的顶部画在A上,但将A的底部画在B上 唯一的解决方案是检测何时发生这种情况并分割三角形 它们相交的地方,但这将是昂贵得令人望而却步的

应该先画哪个三角形?没有一个单一的答案,但处理将尽最大努力,并根据3个顶点的平均Z位置对它们进行排序。这导致了你看到的人工制品

我们可以在一个简单的交互式草图中看到这一点:

无效设置{ 尺寸500500,P3D; 可提示的\u深度\u排序; 仰泳; } 抽真空{ 背景128; 平移宽度/2,高度/2; //灰球 填充255,255,255,64; 球体100; //红球 平移0,0,鼠标宽度/2; 填充255,0,0,64; 球体100; } 上下移动鼠标可前后移动红色球体。当它与灰色球体相交时,您会得到瑕疵,因为三角形相交

忽略鼠标周围的瑕疵,这是创建gif的结果

这就是你看到的人工制品的原因

可能的解决方案 你能做些什么来修复它?您有几个选择:

选项1:停止使用透明度。您的许多问题都是由使用透明度引起的,这使得事情变得非常复杂。最快最简单的方法就是停止使用透明度,因为OpenGL最适合不透明对象

选项2:停止使用相交的形状。您可以将相交球体视为OpenGL无法很好地处理的对象。你能简单地移动你的形状使它们不相交吗?如果您试图构建一个复杂的形状,可以使用三维模型,或者使用顶点函数自己构建它

选项3:提出你自己的排序算法。处理使用平均Z位置,当您具有相交形状时,不能保证该位置正确。您可以自己进行排序,而不是依赖于处理来对三角形进行排序。你将如何做到这一点超越了这个问题,这听起来非常烦人,但这就是3D渲染的本质

选项4:如果你真的,真的,真的需要有相交的透明形状,那么唯一正确的方法就是检测相交点,然后将它们分割成子形状,然后按正确的顺序绘制。这很烦人,但你正在走一条烦人的道路


您还可以调查着色器。我对着色器一无所知,但每当我看到3D渲染出现问题时,总会有人说答案是使用着色器。因此,这可能值得研究,也可能不值得研究,我真的不知道,尽管这是你自己的事情。

要理解为什么会发生这种情况,你必须了解引擎盖下发生了什么

以三角形思考 调用sphere函数时,处理实际上是绘制一组三角形。如果运行以下简单程序,您可以看到:

尺寸500500,P3D; 平移宽度/2,高度/2; 球体100; 在代码中,您已选择不绘制轮廓,但处理过程仍在绘制一组三角形以绘制球体。以下是它使用sphereDetail10绘制的内容:

关键是,你需要停止看到球体,看到组成这些球体的三角形

深度缓冲 因此,OpenGL和Processing使用深度缓冲来确定何时不绘制其他内容后面的内容

我只想复制一部分,这可以更好地解释t 我可以:

考虑绘制两个三角形A和B的示例:

如果我们先画B,然后画A,深度缓冲区将看到新的 来自A的像素比之前由B绘制的像素更接近,因此 会把他们拉过头顶。如果我们按相反的顺序画A 然后是B,深度缓冲区将看到像素进入 从B开始的距离比A已经绘制的距离远,因此它将 丢弃它们。无论哪种情况,我们都会得到正确的结果:A在顶部, 后面藏着B

当你画一个不透明的球体时,你实际上是在画一堆不透明的三角形。处理将以球体到三角形算法生成的任意顺序绘制这些三角形。这适用于不透明对象,因为处理将检查Z缓冲区,然后跳过已绘制三角形后面的三角形。这基本上和OpenGL开箱即用一样聪明

透明度问题 再次引用:

但是如果这个几何体是alpha混合的,那么B部分可见呢 穿过半透明的三角形?如果我们画B,这仍然有效 首先,然后A在顶部,但如果我们画A,然后是B,则不会 在这种情况下,深度缓冲区将从B获得一个像素,请注意 它已经从图像中画出了一个更接近的像素,但它没有办法处理 在这种情况下。它的唯一选择是绘制B像素 将给出错误的结果,因为它将混合更多 远处的B在较近的A的顶部,而阿尔法混合不是 交换的,或者它可以完全丢弃B。不好

问题是,这不适用于透明三角形。请记住,处理是以算法生成的任何顺序绘制三角形,它使用Z缓冲区来决定何时跳过已绘制三角形后面的三角形。但我们不希望它跳过任何三角形!我们想画每个三角形,因为我们想通过前面的三角形看到后面的三角形

例如,如果我们在前面画一个透明的灰色球体,然后在它后面画一个红色球体,我们将看不到红色球体

尺寸500500,P3D; 平移宽度/2,高度/2; 仰泳; //前灰球 填充255,255,255,64; 球体100; //背红球 平移0,0,-500; 填充255,0,0,64; 球体100; 我之所以在这里使用整个球体是因为我很懒,但是想象一下,每个球体中的单个三角形都会发生这样的问题。这就是为什么你能在灰色球体中看到这些人工制品,同样的原因你不能在灰色球体后面看到红色球体。OpenGL先绘制灰色球体,然后跳过红色球体,因为它知道它位于前球体的后面。这是不透明对象的正确行为,但我们通过增加透明度使事情变得复杂

汇票事宜 相反,如果我们在绘制前灰色球体之前绘制后红色球体,那么我们可以通过灰色球体看到红色球体:

尺寸500500,P3D; 平移宽度/2,高度/2; 仰泳; //背红球 平移0,0,-500; 填充255,0,0,64; 球体100; //前灰球 翻译0,0,500; 填充255,255,255,64; 球体100; 请注意,由于三角形顺序问题,我们仍然可以在每个球体内看到瑕疵。这与我们在灰色球体之后绘制红色球体时看不到红色球体的原因相同

现在,要解决三角形的问题,绘制顺序很重要。就像在绘制红色球体后必须绘制前面的灰色球体一样,必须从后面到前面绘制三角形,这样OpenGL就不会跳过它确定的位于已绘制三角形后面的任何三角形。这是一个巨大的颈部疼痛

救援行动 幸运的是,Processing为您提供了一个选项。这是可暗示的深度排序函数。启用此选项后,处理将根据三角形三个顶点的平均Z位置对每个三角形进行排序,然后按该顺序绘制它们。启用此选项后,我们可以在前面的灰色球体之后绘制后面的红色球体,处理将为我们排序三角形,并在到达OpenGL之前按正确的顺序绘制它们:

尺寸500500,P3D; 可提示的\u深度\u排序; 平移宽度/2,高度/2; 仰泳; //前灰球 填充255,255,255,64; 球体100; //背红球 平移0,0,-500; 填充255,0,0,64; 球体100; 请注意,我们可以看到后面的红色球体,即使我们在前面的灰色球体后面绘制它。处理是代表我们进行干预,并在OpenGL中实际绘制三角形之前对其进行排序。这也会修复每个球体内的瑕疵,因为三角形在每个球体中排序,而不仅仅是在球体之间

交叉口问题 请记住,三角形按其3个顶点的平均Z位置排序。这是相交三角形的问题。这是你们问题的症结所在

从, 假设有两个三角形A和B相交,如下所示:

无法对这些三角形进行排序,因为我们需要 将B的顶部画在A上,但将A的底部画在B上 唯一的解决方案是检测何时发生这种情况并分割三角形 它们相交的地方,但这将是昂贵得令人望而却步的

应该先画哪个三角形?没有一个单一的答案,但处理将尽最大努力,并根据3个顶点的平均Z位置对它们进行排序。这导致了你看到的人工制品

我们可以在一个简单的交互式草图中看到这一点:

无效设置{ 尺寸500500,P3D; 可提示的\u深度\u排序; 仰泳; } 抽真空{ 背景128; 平移宽度/2,高度/2; //灰球 填充255,255,255,64; 球体100; //红球 平移0,0,鼠标宽度/2; 填充255,0,0,64; 球体100; } 上下移动鼠标可前后移动红色球体。当它与灰色球体相交时,您会得到瑕疵,因为三角形相交

忽略鼠标周围的瑕疵,这是创建gif的结果

这就是你看到的人工制品的原因

可能的解决方案 你能做些什么来修复它?您有几个选择:

选项1:停止使用透明度。您的许多问题都是由使用透明度引起的,这使得事情变得非常复杂。最快最简单的方法就是停止使用透明度,因为OpenGL最适合不透明对象

选项2:停止使用相交的形状。您可以将相交球体视为OpenGL无法很好地处理的对象。你能简单地移动你的形状使它们不相交吗?如果您试图构建一个复杂的形状,可以使用三维模型,或者使用顶点函数自己构建它

选项3:提出你自己的排序算法。处理使用平均Z位置,当您具有相交形状时,不能保证该位置正确。您可以自己进行排序,而不是依赖于处理来对三角形进行排序。你将如何做到这一点超越了这个问题,这听起来非常烦人,但这就是3D渲染的本质

选项4:如果你真的,真的,真的需要有相交的透明形状,那么唯一正确的方法就是检测相交点,然后将它们分割成子形状,然后按正确的顺序绘制。这很烦人,但你正在走一条烦人的道路


您还可以调查着色器。我对着色器一无所知,但每当我看到3D渲染出现问题时,总会有人说答案是使用着色器。因此,这可能值得研究,也可能不值得研究,我真的不知道,尽管这是你自己的问题。

要理解为什么会发生这种情况,你必须了解引擎盖下发生了什么。在三角形中思考当我提高细节以减少三角化的伪影时会发生什么,请参见我的第二张图片。不准确度增加了,而不是减少了。@ChrisJJ这是一个单独的,可能相关的问题。我已经回答了你的第一个问题,不过我想你不喜欢这个答案。您的第二个问题值得研究-SpheredTail52在记住这个答案后似乎工作正常,但SpheredTail53存在您已经注意到的问题。请随意将其作为一个单独的问题发布,因为我认为这是另一个有趣的问题。但我的帖子确实回答了你的第一个问题,不管你喜不喜欢要理解为什么会发生这种情况,你必须理解引擎盖下发生了什么。在三角形中思考当我提高细节以减少三角化的伪影时会发生什么,请参见我的第二张图片。不准确度增加了,而不是减少了。@ChrisJJ这是一个单独的,可能相关的问题。我已经回答了你的第一个问题,不过我想你不喜欢这个答案。您的第二个问题值得研究-SpheredTail52在记住这个答案后似乎工作正常,但SpheredTail53存在您已经注意到的问题。请随意将其作为一个单独的问题发布,因为我认为这是另一个有趣的问题。但我的帖子确实回答了你的第一个问题,不管你喜不喜欢P