1

我正在绘制一个具有 100 到 2500 个三角形面的中型到大型对象,具体取决于用户之前选择的一些选项。物体本身是固定的——不会移动,不会发生任何变化,什么都没有。到目前为止,您可以将事情想象为“我的应用程序加载 OBJ 文件,然后用户查看它们”,您不会错太多。

棘手的一点是,在任何时候,对象上的一些面都会被“选中”,而另一些则不会。所选面必须以不同的纹理显示——相同的 UV 坐标,但像素颜色来自不同的位图。在任何给定时间将选择大约一半的面,哪些面会不断变化。

因此,显而易见的事情是,在片段着色器中,如果我正在处理选定的面,请在此位图上调用 texture2D(),如果我在未选择的三角形中,请使用那个。只是,我看不到从片段着色器中找出我所在的三角形的方法。这是我的问题:我能知道吗?

我确实有一个替代方案——用自己的顶点副本设置每个面,将纹理位图的大小加倍,在每个面的顶点上设置 UV 坐标以指向“选定”或“取消选定”部分位图——但是顶点的数量增加了 6 倍,而且我每帧都将一个全新的 UV 数组传递给 GPU,而且……是的。明显慢,即使在小物体上也是如此。不好。

4

1 回答 1

3

片段着色器不知道它在哪个三角形中。但是,可以通过使用额外的顶点属性来获得您想要的效果。

不幸的是,这通常意味着您必须以与进行硬折痕时相同的方式复制每个三角形的顶点数据——没有简单的方法可以做到这一点,至少在它必须与任何类型一起工作时不是这样。的选择。
但是,使用单独的流,您实际上只需要每帧上传一个属性,其余的都是不变的。就带宽而言,这是完全可以接受的。

然后,片段着色器将对两个纹理进行静态采样,并根据特殊顶点属性是 1.0 还是 0.0 来选择一个值或另一个值(这比每次分支和采样不同的纹理更有效,这可能无论如何都会对两个纹理进行采样) . 您可以mix为此使用内在函数(这通常会导致单个本机 1 周期指令)或三元运算符。

对于某些不需要您复制顶点数据的选择子集,一种可行的替代方法是在 1.0 处截断的属性上使用阶跃函数——需要顶点复制的问题是插值。
如果任何单个顶点属性为零,则任何片段(除了恰好在具有“1.0”的顶点下的片段之外)的插值将必然小于 1.0。另一方面,除“0.0”顶点下或恰好在两个“0.0”顶点之间的线上的片段以外的任何片段都将是非零的。这不适用于每个任意选择,但在许多情况下,使用诸如“选择任何非零值”(或相反的方式)之类的策略可能会起作用,而不会复制顶点数据。

Having ARB_provoking_vertex would ease your life, but alas... no ES 2.0 implementation will likely provide that.

于 2012-10-06T16:54:16.600 回答