【发布时间】:2018-11-30 20:21:57
【问题描述】:
我正在 three.js 中编写一个相当复杂的 webgl 应用程序,为了更好地控制我的网格材质,我通过着色器定义它们。
但是,我面临一个严重的问题,我找不到任何真正令人满意的答案。让我们假设以下强大的先决条件:
- 我的几何图形已编入索引,即顶点在面之间不重复,我不想更改此设置
- 几何图形存储在
THREE.BufferGeometry对象中,我不想再切换到THREE.Geometry - 我不想复制面和/或创建新的几何图形
- 我不想要任何会降低帧率的双向渲染
鉴于上述情况,假设我单击几何体的一个三角形(即射出一条射线并获得与射线相交的最近面),并且我希望用不同的颜色突出显示该三角形。
我已经通过为属于要突出显示的面的每个顶点分配一个自定义顶点属性,例如1.0,以一种非常有效的方式执行此操作。
在顶点着色器中,我用这样的顶点属性定义了一个变量,在片段着色器中,我只执行以下(伪代码):
vec4 frag_color=mix(default_color,highlight_color,(vert_attribute>1-eps));
eps 是一个很小的值(比如 1.0e-4)。
这个想法是每个片段都插入其对应的顶点属性,比如Vatt_1、Vatt_2和Vatt_3,如果所有三个属性都得到值1.0,那么它们的插值仍然接近1.0(不精确由于一些舍入误差,这就是我使用小公差 eps 的原因)并且测试是正确的。
如果测试是true 我有frag_color=highlight_color。
另一方面,如果至少有一个Vatt_i(i=1,2,3)不是1.0而是默认的0.0,则当前片段的插值是<1-eps,测试是false(给frag_color=default_color)。
这似乎工作得很好,但现在我遇到了以下看起来真正具有挑战性的问题(考虑到上面的约束 1 和 2):
我在片段着色器中没有任何简单的方法可以知道当前片段是否属于特定面(或停留在三个特定顶点内,这是相同的)。所以,如果我选择两个三角形T1 和T2,并且碰巧第三个三角形T3 有一个(或两个)与T1 共享的顶点和两个(或一个)与T2 共享的顶点,我得到T3 也被突出显示,因为它的三个顶点获得属性 1.0。
当然,从人类的角度来看,这不应该发生,因为 T3 的三个“高亮”顶点应该“逻辑上”指代两个不同的高亮面,但由于明显的原因,片段着色器亮点也T3。
我想这是一个相当普遍的问题,我阅读了很多论坛,但没有找到任何令人满意的可能解决方案。我知道“这就是它的工作原理”,并且片段着色器对背景三角形及其顶点一无所知,但在这里我正在寻找一些聪明的想法或技巧。
对于这个问题,有人有什么建议吗?很抱歉打扰,但只是为了防止一些可能的争论:我认为上面 1-4 的四点是很强的要求,否则我会有其他与整体性能相关的问题,我不想付出这个代价。
提前致谢
【问题讨论】:
-
只是一个快速的想法,您是否可以为每个选定的面分配不同的整数(例如所有其他设置为 0.5),然后使用
fract(vert_attribute) > 1e-5进行测试? 编辑: 好吧,算了吧。我错过了明显的一点,即您需要为同一个顶点设置不同的值:/ -
另外:非常感谢您的洞察力,我一直认为在使用索引几何时根本不可能发生这样的事情。
-
@MartinSchuhfuß,感谢您的建议,但我认为这行不通。片段着色器进行的插值将完全弄乱存储在分配给每个顶点的单个浮点属性中的任何逻辑。此外,如果您想选择共享一个顶点的两个面,该怎么办?您应该为该顶点分配什么值?面部ID的某种组合?还有更多的面孔?我想这几乎是不可行的。我尝试了一种不同的方法,它应该可行,但对我来说看起来太复杂了,比如用大炮射击苍蝇。
-
假设我们将一个统一的纹理传递给顶点着色器,在那里我们存储所有顶点及其顶点面,然后我们可以在一个 rgba 值数组中编码顶点面(设置
1.0如果一个人脸共享顶点,0.0如果不是),如果人脸 id 已经被巧妙地设置,一个“合理的”三角形网格应该需要一个相当小的向量,我会说 8 个 vec4(即 32 个浮点数),也许更少,这通常是MAX_VARYING_VECTORS允许的。因此,片段着色器将插入 3 个向量,例如 32 个浮点数,它们是0.0或1.0,并且只有一张脸会包含所有1.0。 -
也许你可以把脸转向另一边。也就是说,在面定义中交换2个顶点,这将使面法线指向相反的方向,您可以不同地渲染面