什么更快 - 片段着色器中的变化或手动插值?

What is faster - varying or manual interpolation in fragment shader?

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

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

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

我可能看到的唯一用例是全屏四边形渲染(你可以得到 gl_FragCoord 并使用视口大小推断 uv 坐标)但在这种情况下你只有一个或两个变量,所以我猜性能没有差异,但如果你做很多 post-processing.

可能值得比较两者

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

根据at least one guide using varings is faster

Be Aware of Dynamic Texture Lookups

Dynamic texture lookups, also known as dependent texture reads, occur when a fragment shader computes texture coordinates rather than using the unmodified texture coordinates passed into the shader. Dependent texture reads are supported at no performance cost on OpenGL ES 3.0–capable hardware; on other devices, dependent texture reads can delay loading of texel data, reducing performance. When a shader has no dependent texture reads, the graphics hardware may prefetch texel data before the shader executes, hiding some of the latency of accessing memory.

Listing 10-7 shows a fragment shader that calculates new texture coordinates. The calculation in this example can easily be performed in the vertex shader, instead. By moving the calculation to the vertex shader and directly using the vertex shader’s computed texture coordinates, you avoid the dependent texture read.

Note: It may not seem obvious, but any calculation on the texture coordinates counts as a dependent texture read. For example, packing multiple sets of texture coordinates into a single varying parameter and using a swizzle command to extract the coordinates still causes a dependent texture read.

Listing 10-7 Dependent Texture Read

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 的(例如 iPhones/iPads)。其他 GPU 可能具有不同的性能特征。