代码之家  ›  专栏  ›  技术社区  ›  duhaime

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

  •  0
  • duhaime  · 技术社区  · 7 年前

    是否可以在WebGL中将纹理从顶点传递到片段着色器如果是这样,一个人怎么能达到这种行为呢?

    我试图将Sampler2D传递给frag着色器,但得到一个错误:

    采样器2ds必须均匀

    我很感激其他人在这个问题上的帮助!

    1 回复  |  直到 7 年前
        1
  •  2
  •   gman    7 年前

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

    顶点着色引擎

    ...
    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的注释更新,如果在条件代码内部使用,则根据spec纹理break进行更新从 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 ...
    }
    

    当然,对于大多数用例,您可能应该使用纹理图集并使用纹理坐标来选择其中的一部分使用多个纹理的正常原因是:法线贴图、不透明度贴图、反射率贴图、环境光遮挡、照明或平滑混合(如污垢/草地/雪),在这种情况下,不需要条件要重新迭代,从材质球中的多个纹理中进行选择并不常见。