为什么要将纹理从顶点着色器传递到片段着色器?只需在两个着色器中声明相同的采样器?
顶点着色器
...
uniform sampler2D foo;
....
片段着色器
...
uniform sampler2D foo;
...
否则答案是否定的,你不能在着色器之间传递纹理。您可以传递一些值来选择采样器结果
顶点着色器
varying float textureSelector;
...
textureSelector = ???
片段着色器
vec4 color1 = texture2D(foo, ...);
vec4 color2 = texture2D(bar, ...);
vec4 color = mix(color1, color2, textureSelector);
注意:根据 Nicol 的 cmets 更新,根据规范,如果在内部条件代码中使用纹理会中断。来自the spec, Appendix A.6
纹理访问
在非统一条件块的主体内访问 mip 映射纹理会给出未定义的值。非统一条件块是在编译时无法确定执行的块
换句话说,这样的代码可能不起作用
varying float textureSelector;
uniform sampler2D foo;
uniform sampler2D bar;
...
if (textureSelector > ???) {
... use foo ...
} else {
... use bar ...
}
所以我想最好在着色器的非条件部分对所有纹理进行采样,然后使用上述 mix 之类的数学运算,或者在从纹理中获取值后使用条件。访问 N 个纹理但只选择 1 个的示例。
#define NUM_TEXTURES 6
uniform sampler2D u_textures[NUM_TEXTURES];
varying float textureSelector; // 0 to NUM_TEXTURES - 1
void main() {
vec4 color = vec4(0);
for (int i = 0; i < NUM_TEXTURES; ++i) {
float id = float(i);
float mult = step(id - .5, textureSelector) * step(textureSelector, id + .5);
vec4 texColor = texture2D(u_textures[i], someTexCoord);
color = mix(color, texColor, mult);
}
... use color ...
}
当然,对于大多数用例,您可能应该使用纹理图集并使用纹理坐标来选择其中的一部分。使用多个纹理的正常原因是法线贴图、不透明度贴图、反射率贴图、环境光遮蔽、照明和/或平滑混合(如泥土/草/雪),在这种情况下您不需要条件。要重新迭代,在着色器中从多个纹理中进行选择并不常见。