在GLSL中使用纹理时,最好在顶点着色器中计算最终的纹理坐标,然后使用varying s将其移交给片段着色器。在y坐标中进行简单翻转的示例:

// Vertex shader
attribute vec2 texture;
varying highp vec2 texCoord;
// ...
void main() {
    texCoord = vec2(texture.x, 1.0-texture.y);
    // ...
}

// Fragment shader
varying highp vec2 textureCoordinates;
uniform sampler2D tex;
// ...
void main() {
    highp vec4 texColor = texture2D(tex, texCoord);
    // ...
}


如果在y坐标中进行翻转,或者执行更简单的操作(如在纹理坐标中添加vec2(0.5))片段着色器的纹理访问速度要慢得多。为什么?


作为注释,例如使用它们的加权总和混合两个纹理在时间上要便宜得多,而且每个像素都需要完成,因此纹理坐标本身的计算似乎并不那么昂贵。

评论

我的猜测是,如果UV坐标是在VS中计算的,则纹理单元可以在PS启动时开始预取它们。如果它们是在PS中计算的,则纹理单元必须首先等待。

首先,这被称为“相关纹理读取”,以防它有助于搜索。

您是否有一些测量结果显示出性能差异?我实际上并不期望会有太大的区别。纹理获取延迟应淹没一些ALU操作。顺便说一句,从属纹理读取是存在两个(或更多)纹理读取的位置,第二个的坐标取决于第一个的输出。由于两次纹理读取之间要求严格的排序,因此速度较慢。

好吧,在片段着色器中完成的任何操作都将比在顶点着色器中进行更昂贵。每个三角形需要调用顶点着色器3次,但根据片段的屏幕大小,它可能需要更多次片段着色器的调用。

@NathanReed我认为您不必将“依赖纹理读取”限制为仅来自先前纹理访问的内容。我可能还会包括在碎片着色器中计算出的所有坐标,这与只能从顶点属性的线性(很好,带有透视图的双曲线)插值确定的坐标相反。

#1 楼

您所说的在移动开发社区中通常被称为“依赖纹理读取”。它是某些硬件的实现细节,因此,它是否真正影响性能取决于GPU。通常,您会在Apple硬件中看到PowerVR GPU带来的东西,因为Imagination和Apple文档中都明确提到了它。如果我没记错的话,问题基本上出在GPU中的硬件上,它将在片段着色器甚至开始运行之前就开始预取纹理,以便可以更好地隐藏延迟。我链接的文档提到它不再是Series6硬件上的问题,因此至少在较新的Apple硬件上,您不必担心。老实说,我不确定其他移动GPU,因为这不是我的专业领域。您应该尝试并查阅其文档以确保确定。

如果您决定对此问题进行一些Google搜索,请注意,您可能会发现一些较旧的材料在谈论依赖纹理的获取在较旧的台式机硬件上。在像素/片段着色器的早期很基本,术语“从属纹理获取”是指使用依赖于先前纹理获取的UV地址。经典示例是凹凸贴图环境地图渲染,您想在其中使用基于法线贴图的反射矢量来采样环境贴图。在这种较旧的硬件上,存在一些重大的性能影响,而且我认为某些非常老的GPU甚至不支持它。使用现代的GPU,硬件和着色器ISA变得更加通用,因此性能情况也更加复杂。

评论


$ \ begingroup $
顺便说一句:我在iPad 3上遇到了这种情况。所以也许这实际上是特定于硬件的。
$ \ endgroup $
– Nero
15年8月18日在17:18