如何在使用三角带绘制的网格上实现类似于 Marching Squares 的算法?

3
我正在使用一系列三角带绘制网格。我正在使用这个来渲染一个高度场,并且完全在顶点着色器中生成顶点数据,而不使用任何输入缓冲区,只是使用顶点和实例索引。这一切都很好地工作,并且非常高效。
然而,现在我发现自己还需要在这个网格上实现边框线。显然,这里的解决方案将类似于 marching squares。基本上,我想要实现的是这样的:

Diagram of what I want

黑点代表网格中属于某个集合的顶点,我想用不同的颜色来填充红线内部和外部的区域。
表面上看,这似乎很容易:为集合中的顶点添加值1,而在外部的顶点则添加0,并根据插值后的值是大于还是小于0.5来进行不同的渲染。
然而,由于它是作为三角形带呈现的,所以这种方法并不完全奏效。实际上,由于这是作为三角形带呈现的,结果看起来像这样:

enter image description here

所以,一半的边缘是有效的,而另一半会形成丑陋的方形楼梯。
我已经试图思考几天是否有一些技巧可以用来不同地生成顶点值或进行更复杂的测试,以便更接近预期的形状,而不放弃漂亮而简单的三角形条带,并且不需要提前生成几何图形,但我想不到任何一个。
有人遇到过类似的问题吗?有没有一些聪明的解决方案我错过了?
我正在使用Metal进行此操作,但我不认为这取决于使用的具体API。

1
“我想要实现的是这样的效果”。有什么算法可以从一堆点中生成这样的东西?具体来说,末尾的长线条毫无意义。它中间没有点来支撑这样长的线条。 - Nicol Bolas
1
正如我在帖子中提到的那样,Marching Squares算法可以实现这一点。 - Dag Ågren
1
然后...使用那个算法。你是说你正在使用那个算法而没有得到正确的结果吗? - Nicol Bolas
2
问题是是否有一种方法可以在保留基于三角形带的当前渲染方法的同时模拟Marching Squares的结果,这对其他方面非常有用。 - Dag Ågren
3
@NicolBolas说:"我认为OP并不是试图画出线条。OP想要 '将区域内的线条与区域外的线条着不同的色'。因此,可以推测这些线条只是标明着色区域内部和外部的边界。" - Yakov Galka
显示剩余2条评论
1个回答

2
听起来你正在尝试独立于网格计算片段着色器中的颜色。如果是这样,你应该将颜色计算与网格分离。
假设你的占用率存储在纹理中,请使用textureGather获取四个附近的占用值;确定边界的方程式;然后使用纹理坐标的小数部分来确定其相对于边界的位置。(魔鬼在于细节——特别是模糊的棋盘格案例。)
一旦你实现了上述方法,很可能你甚至不再需要三角形带网格——只需用一个单独的大四边形填充整个绘图区域,并让片段着色器完成其余工作。

嗯,既然我在顶点着色器中已经读取了同样的纹理,我想我希望通过不在片段着色器中再次读取它来减轻内存带宽的负担,但你说得对,那也可以正常工作。我仍然需要三角形带出于其他原因,但也许我确实需要考虑只做这个。(此外,我的数据中不会有很多棋盘格情况,而且对于它们我做什么并不是非常重要,所以至少这不是我需要考虑的头疼问题。) - Dag Ågren
然而这给了我一个想法:我可以在顶点着色器中获取这些数据,并将其存储为一个平面值,然后在片段着色器中使用它。这样可以节省片段着色器的内存访问,但也能实现你建议的同样的功能!我想我会尝试这种方式! - Dag Ågren
@DagÅgren 我可能在这个问题上弄错了,但这并不一定会节省内存带宽。顶点着色器的值并不会神奇地出现在片段着色器中;据我所知,在GPU上实现的方式是,顶点着色器将其输出写入临时内存缓冲区,片段着色器调用从中读取。 - Yakov Galka
可以的。如果你正在绘制许多小三角形和被剪裁的三角形,那么在片段着色器中读取可能会更快,但至少这种方式很容易尝试两种方法并进行比较。 - Dag Ågren

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接