WebGL:将纹理从顶点着色器传递到片段着色器

WebGL: Pass texture from vertex shader to fragment shader

是否可以将纹理从顶点传递到 WebGL 中的片段着色器?如果是这样,如何实现这一行为?

我试图将 Sampler2D 传递给碎片着色器,但出现错误:

sampler2Ds must be uniform

如果其他人可以就此问题提供任何帮助,我将不胜感激!

为什么要将纹理从顶点着色器传递到片段着色器?只需在两个着色器中声明相同的采样器?

顶点着色器

...
uniform sampler2D foo;
....

片段着色器

...
uniform sampler2D foo;
...

否则答案是否定的,你不能在着色器之间传递纹理。您可以将一些值传递给 select 采样器结果

顶点着色器

varying float textureSelector;
...
textureSelector = ???

片段着色器

vec4 color1 = texture2D(foo, ...);
vec4 color2 = texture2D(bar, ...);
vec4 color = mix(color1, color2, textureSelector);

注意:根据 Nicol 的评论更新,根据规范,如果在内部条件代码中使用,纹理会中断。来自 the spec, Appendix A.6

Texture Accesses

Accessing mip-mapped textures within the body of a non-uniform conditional block gives an undefined value. A non-uniform conditional block is a block whose execution cannot be determined at compile time

换句话说,这样的代码可能行不通

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 ...
}

当然,对于大多数用例,您可能应该使用纹理图集并将纹理坐标用于其中的 select 部分。使用多个纹理的正常原因是法线贴图、不透明度贴图、反射率贴图、环境遮挡、照明和/或像 dirt/grass/snow 这样的平滑混合,在这些情况下你不需要条件。重申一下,在着色器中从多个纹理 select 并不常见。