在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);
// ...
}
如果vec2(0.5)
在片段着色器中执行y坐标的翻转或什至更简单的操作(如添加到纹理坐标),则纹理访问会慢得多。为什么?
需要注意的是,例如,使用它们的加权总和来混合两个纹理在时间上要便宜得多,并且还需要针对每个像素完成,因此纹理坐标本身的计算似乎并不那么昂贵。
1
我的猜测是,如果UV坐标是用VS计算的,则纹理单元可以在PS启动时开始预取它们。如果它们是在PS中计算的,则纹理单元必须首先等待。
—
RichieSams 2015年
首先,这被称为“相关纹理读取”,以防它有助于您的搜索。
—
艾伦·沃尔夫
您是否有一些测量结果显示出性能差异?我实际上并不期望会有太大的区别。纹理获取延迟应该会淹没一些ALU操作。顺便说一句,从属纹理读取是存在两个(或更多)纹理读取的位置,第二个的坐标取决于第一个的输出。由于两个纹理读取之间要求严格的排序,因此速度较慢。
—
内森·里德
好吧,在片段着色器中进行的任何操作都将比在顶点着色器中进行的操作更为昂贵。每个三角形需要调用顶点着色器3次,但是取决于片段的屏幕大小,它可能需要更多数量级的片段着色器。
—
glampert
@NathanReed我认为您不必将“依赖纹理读取”限制为仅来自先前纹理访问的内容。我可能还会包括在碎片着色器中计算出的所有坐标,这与仅根据顶点属性的线性(很好,带有透视图的双曲线)插值可以确定的坐标相反。
—
西蒙F