在许多材料之间混合

我在网格中存储每个顶点的一个材质ID。 在网格的着色器中,我有一个纹理数组,其中包含材质ID可以引用的纹理。 使用三面体纹理select片段颜色。 与顶点颜色不同,这些材质ID不能混合

例如,如果污垢纹理的材质ID为5,草纹理的材质ID为1,则在材质ID为5的一个顶点和材质ID为1的顶点之间的碎片可能会具有介于2和4之间的材质ID ,这是不理想的。 这种方法的另一个缺陷是材料之间会有一个很难的转换,因为不使用着色器中的混合或lerp函数。

有没有办法在片段着色器中混合两个相邻顶点的纹理? 如果需要,我可以添加额外的顶点数据。

当到达片段着色器时,顶点值确实将被内插,所以例如具有两个连接的顶点,一个具有纹理槽id = 2,另一个具有id = 17,将给片段着色器2和17之间的一切(包括十进制值在之间)取决于像素的位置,导致大量的纹理插槽走在路上。

实际上,可以使用0 … 1样式来实际描述每个顶点中每个纹理槽的数量。 按照“并行”的方式进行,并按照固定的顺序进行。 一个顶点通常连接到另外6个顶点(但可以连接到更多),所以在这种情况下,最多6个纹理将随时参与混合。 但是,您会描述每个顶点中所有纹理的数量; 那些是0的,你可以简单地跳过片段着色器,也许最多可以做6次查找。

接下来的问题是可以在顶点数据中分配多less个“浮点”通道? 我想不是太多,但至less有一些,取决于你需要在顶点数据中烘烤什么。

话虽如此,我可以指出,你可能不需要1/256的“每个纹理的量”的精细分辨率? 如果你愿意有1/16的分辨率,你可以在一个8位“浮点数”中烘烤16个不同纹理的纹理数量,因为它可以保存256个不同的整数值。 在这种情况下,您可以描述最多16个纹理材质的混合,例如normal.w。 或者有8个频道,每个频道的分辨率为1/32。 Ofc你需要在着色器(和构建网格)时做一些math运算,但是这很有趣吗? 🙂

编辑:

关于上面的部分,我必须承认一个持续时间的脑力劳动并没有揭示任何好的解决scheme,以至于如何控制一个单一的浮点数的分裂,以便能够抓住它的比特序列的各个部分而GPU正在对其进行插值。 这将是一个问题,比特人,即。 一个单独的问题要求encryption和压缩专家。 你能插入一个32位的浮点值AAAA(4字节),这样它的位表示的单个字节保持可以沿着插值解码,并且全部在另一端分别成为BBBB?

一种可以做到的方法就是把你的材料分成几个层次。 举一个例子, RED3发动巫师3,为地形材料使用背景层和覆盖层 。

从上面链接的CD Projekt RED GDC谈话滑出

您可以将材料数据存储在控制贴图纹理中,如上面的例子或顶点数据。 无论哪种方式,您最终都会将素材的标识存储在每个插槽中,并在它们之间进行混合权重。 这样可以严格控制每点的材料数据总量和纹理采样操作的总数量:即使您的材料库很大,只有一个固定数量的材质可以用于单个三角形/片段。

如果将这些数据存储在顶点中,则意味着共享一个三角形的任何三个顶点需要在每个槽中的材料上达成一致。 如果一个顶点坐落在6个三角形的交界处,其中3个要求“积雪覆盖在岩石上”,另外3个要求“积雪覆盖”,那么您可以复制这个顶点来处理每个三角形 – 类似于我们如何创建硬边一个正常的突然变化,或紫外线接缝。 对于控件贴图,您可以对材质ID使用点过滤,以免插入。

这确实限制了你的材料的涂装。 在2层系统中,如果两个相邻的位置不同意材料应该在第1层上的位置,则第2层需要沿共享边缘完全不透明,以防止纹理接缝可见。 类似地,对于属于第2层的两个位置不同意 – 它必须在两者之间达到零不透明度。 在实践中,通常可以在几个三角形/单元格上展开材质变化来解决这个问题,或者在某种程度上贴一个支柱/草,以使缝不可见。 ;)