如何将纹理数组绑定到WebGL着色器统一?

vir*_*obi 7 textures webgl

我需要处理许多只共享少量纹理的对象.手动定义和加载纹理(如SO上的另一篇文章中所述)感觉不对......更是如此,因为switch (index) {case:...}WebGL中没有任何语句.

所以我想传递纹理以用作顶点属性的顶点,并使用此数字作为fragement着色器中某些"纹理数组"的索引.但是采样器上OpenGL wiki(不是WebGL的完美参考,但是我找到的那个)说:

采样器的变量只能以两种方式之一定义.它可以定义为函数参数或统一变量.

均匀采样器2D纹理1;

那对我来说听起来像我可以没有采样器阵列.我已经阅读了几页纹理单元,但直到现在,这对我来说仍然是一个谜.

在上面引用的SO帖子中,Toji暗示了一个解决方案,但想要一个单独的问题 - 瞧!

谢谢,nobi

PS:我知道使用"纹理图集"的另一种可能性 - 如果这更有效或更简单 - 我会很高兴听到经验!

gma*_*man 12

您必须使用常量值对采样器数组进行索引,以便您可以执行类似的操作

#define numTextures 4

precision mediump float;
varying float v_textureIndex;
uniform sampler2D u_textures[numTextures];

vec4 getSampleFromArray(sampler2D textures[4], int ndx, vec2 uv) {
    vec4 color = vec4(0);
    for (int i = 0; i < numTextures; ++i) {
      vec4 c = texture2D(u_textures[i], uv);
      if (i == ndx) {
        color += c;
      }
    }
    return color;
}

void main() {
    gl_FragColor = getSampleFromArray(u_textures, int(v_textureIndex), vec2(0.5, 0.5));
}
Run Code Online (Sandbox Code Playgroud)

您还需要告诉它使用哪些纹理单位

var textureLoc = gl.getUniformLocation(program, "u_textures");
// Tell the shader to use texture units 0 to 3
gl.uniform1iv(textureLoc, [0, 1, 2, 3]);
Run Code Online (Sandbox Code Playgroud)

上面的示例使用恒定纹理坐标只是为了保持简单,但当然您可以使用任何纹理坐标.

这是一个示例:

http://jsfiddle.net/greggman/dQuxT/

  • 因为基于OpenGL ES 2.0的WebGL不允许使用除常量索引表达式之外的任何内容对采样器数组建立索引.参见GLSL 1.0.17附录A第5节[http://www.khronos.org/registry/gles/specs/2.0/GLSL_ES_Specification_1.0.17.pdf],这意味着您可以使用基于常量的常量或循环索引进行索引,但没有其他的. (2认同)