我正在绘制一个介于100到2500个三角形面之间的大中型物体,具体取决于用户之前选择的一些选项。对象本身是固定的 - 不移动,不经历任何变换,没有任何变化。到目前为止,你可以想到“我的应用程序加载OBJ文件,然后用户查看它们”,你就不会错了。
棘手的一点是,在任何时候,对象上的某些面部将被“选中”,而有些则不会。选定的面必须使用不同的纹理显示 - 相同的UV坐标,但像素颜色来自不同的位图。大约一半的面孔将在任何给定的时间被选中,哪些面孔将不断变化。
所以,显而易见的事情是,在片段着色器中,如果我正在处理选定的面,请在此位图上调用texture2D(),如果我在未选择的三角形中,请使用那个。只是,我没有看到从片段着色器中找出我所在的三角形的方法。我的问题是:我能知道吗?
我确实有另一种选择 - 使用自己的顶点副本设置每个面,将纹理位图的大小加倍,在每个面顶点上设置UV坐标以指向“选定”或“取消选择“位图的一部分 - 但是顶点的数量增加了6倍,我每一帧都将一整套新的UV数据传递给GPU,并且......是的。即使在小物体上也明显很慢。不好。
答案 0 :(得分:3)
片段着色器不知道它所在的三角形。但是,可以通过使用额外的顶点属性来获得所需的效果。
不幸的是,这通常意味着你必须以与进行硬折痕时相同的方式复制每个三角形的顶点数据 - 没有简单的方法可以做到不同,至少在它不得不工作时使用任何类型的选择 但是,使用单独的流,您实际上只需要每帧上传一个属性,其余的是常量。就此而言,它在带宽方面是完全可以接受的。
片段着色器然后静态地对两个纹理进行采样,并根据特殊顶点属性是1.0还是0.0来选择一个或另一个值(这比每次分支和采样不同的纹理更有效,这可能会同时采样纹理无论如何)。您可以使用mix
内在函数(通常导致单个本机1周期指令)或三元运算符。
对于一些不需要复制顶点数据的选择子集的一种工作替代方法是在1.0处切断的属性上使用阶梯函数 - 这个问题需要顶点重复进行插值。登记/> 如果任何单个顶点属性为零,则任何片段(除了具有“1.0”的顶点下的片段之外)的插值必须小于1.0。另一方面,除了“0.0”顶点之下或者恰好位于两个“0.0”顶点之间的线上之外的任何片段都将是非零的。这不适用于每个任意选择,但在许多情况下,使用诸如“选择任何非零值”(或反过来)之类的策略可能会起作用,而不会复制顶点数据。 / p>
让ARB_provoking_vertex可以缓解你的生活,但是唉......没有ES 2.0实现可能会提供这个。