-1

什么是更快的 - 让变化来插值纹理坐标(和一些其他逐渐变化的系数)或在片段着色器中手动计算它们?

有人会认为这个问题的答案是显而易见的,但后来我偶然发现有人提到(目前无法找到来源)每一个额外的变化都是有代价的,并导致性能下降。

更新: 我正在进行图像重采样,所以基本上对于每个目标像素,我需要从原始纹理中获取几个样本,然后进行插值。我可以在顶点着色器中预先计算这些样本的精确坐标并通过变量传递它们,或者我可以直接在片段着色器中计算它们。事实上,我还没有看到有人通过变量来做到这一点。我认为这背后应该有一个原因。

4

2 回答 2

2

根据至少一份指南,使用 varings 更快

注意动态纹理查找

动态纹理查找,也称为依赖纹理读取,发生在片段着色器计算纹理坐标而不是使用传递给着色器的未修改纹理坐标时。在支持 OpenGL ES 3.0 的硬件上支持相关纹理读取,无需性能成本;在其他设备上,依赖纹理读取会延迟纹素数据的加载,从而降低性能。当着色器没有依赖纹理读取时,图形硬件可能会在着色器执行之前预取纹素数据,从而隐藏访问内存的一些延迟。

清单 10-7 显示了一个计算新纹理坐标的片段着色器。这个例子中的计算可以很容易地在顶点着色器中执行,而不是。通过将计算移至顶点着色器并直接使用顶点着色器的计算纹理坐标,可以避免读取依赖纹理。

注意:它可能看起来并不明显,但纹理坐标上的任何计算都算作依赖纹理读取。例如,将多组纹理坐标打包到单个可变参数中并使用 swizzle 命令提取坐标仍然会导致依赖纹理读取。

清单 10-7 依赖纹理读取

varying vec2 vTexCoord;
uniform sampler2D textureSampler;

void main()
{
   vec2 modifiedTexCoord = vec2(1.0 - vTexCoord.x, 1.0 - vTexCoord.y);
   gl_FragColor = texture2D(textureSampler, modifiedTexCoord);
}

注意:这是假设,就像你提到的,我们正在谈论纹理坐标。用于在纹理中查找纹素的坐标。

老实说,我不认为这与文件所说的那样真实。我假设纹理的工作方式类似于普通内存,因为有一个纹理缓存,如果你的纹理(或纹理的一部分)不在缓存中,那么就会出现缓存未命中。同样,我假设缓存只是半自动拉入矩形区域(用于过滤),因此只要您大部分时间以正常方式穿过纹理,我认为无论纹理坐标如何计算,您都会获得最佳性能。但是,至少根据该文件,这是不正确的。

另一个是术语。我一直认为依赖纹理读取=通过查找其他纹理的结果来查找一个纹理。一个典型的例子是调色板纹理,您使用 8 位单通道纹理来索引 RGBA 调色板纹理。这是一个依赖纹理查找。但是根据上面的文档,依赖纹理查找的另一个定义显然是任何不直接使用未修改变量的纹理查找。

请注意,上面的指南适用于 PowerVR GPU(例如所有 iPhone/iPad)。其他 GPU 可能具有不同的性能特征。

于 2016-06-13T14:31:02.643 回答
0

我可能会看到的唯一用例是全屏四边形渲染(您可以gl_FragCoord使用视口大小获取并推断 uv 坐标),但在这种情况下,您只有一两个变量,所以没有我猜是性能上的差异,但如果你做了很多后期处理,可能值得比较两者。

在更一般的情况下,正如 Nicol Bolas 指出的那样,您可能仍然需要一些不同的数据来计算插值(例如系数),以及片段着色器中的更多数据(要线性插值您的 uv,您需要每个顶点的 uv你的三角形)。

于 2016-06-13T14:08:10.303 回答