WebGL着色器检查纹理sampler2D的状态

时间:2017-03-31 13:38:29

标签: webgl shader

我想准备着色器组件(用于多采样器tex)

在我目前的状态下,我只使用(激活并绑定)2个纹理图像。

但这一行:

gl_FragColor = textureColor + textureColor1 + textureColor2;

我的纹理视图出现问题,因为纹理我没有绑定纹理。

在着色器中,不可能使用console.log或任何其他标准调试方法。我有兴趣了解有关着色器的更多信息,但我被卡住了。

代码:

...

precision mediump float;

varying vec2 vTextureCoord;
varying vec3 vLightWeighting;

uniform sampler2D uSampler;
uniform sampler2D uSampler1;
uniform sampler2D uSampler2;
uniform sampler2D uSampler3;
uniform sampler2D uSampler4;
uniform sampler2D uSampler5;
uniform sampler2D uSampler6;
uniform sampler2D uSampler7;
uniform sampler2D uSampler8;
uniform sampler2D uSampler9;
uniform sampler2D uSampler10;
uniform sampler2D uSampler11;
uniform sampler2D uSampler12;
uniform sampler2D uSampler13;


void main(void) {


vec4 textureColor = texture2D(uSampler, vec2(vTextureCoord.s, vTextureCoord.t));
vec4 textureColor1 = texture2D(uSampler1, vec2(vTextureCoord.s, vTextureCoord.t));
vec4 textureColor2 = texture2D(uSampler2, vec2(vTextureCoord.s, vTextureCoord.t));

// Need help here
gl_FragColor = textureColor + textureColor1 ;

//gl_FragColor = textureColor + textureColor1 + textureColor2;

//更新的问题

    if (  ${numTextures} == 1)
        {
            gl_FragColor = textureColor;
        }
    else if (${numTextures} == 2)
        {
            gl_FragColor = textureColor + textureColor1;
        }
    else if (${numTextures} == 3)
        {
            gl_FragColor = textureColor + textureColor1 + textureColor2;
        }

//我现在使用简单实用的if else。

//我将值传递给加载时的着色器

//我仍然无法在运行时更新着色器

///////////////////////////////////////

//这是绘制函数的一部分:

for (var t=0;t<object.textures.length;t++) {

 eval( "  world.GL.gl.activeTexture(world.GL.gl.TEXTURE"+t+");  " )
    world.GL.gl.bindTexture(world.GL.gl.TEXTURE_2D, object.textures[t]);
    world.GL.gl.pixelStorei(world.GL.gl.UNPACK_FLIP_Y_WEBGL, false);
    world.GL.gl.texParameteri(world.GL.gl.TEXTURE_2D, world.GL.gl.TEXTURE_MAG_FILTER, world.GL.gl.NEAREST);
    world.GL.gl.texParameteri(world.GL.gl.TEXTURE_2D, world.GL.gl.TEXTURE_MIN_FILTER, world.GL.gl.NEAREST);
    world.GL.gl.texParameteri(world.GL.gl.TEXTURE_2D, world.GL.gl.TEXTURE_WRAP_S, world.GL.gl.CLAMP_TO_EDGE);
    world.GL.gl.texParameteri(world.GL.gl.TEXTURE_2D, world.GL.gl.TEXTURE_WRAP_T, world.GL.gl.CLAMP_TO_EDGE);
    // -- Allocate storage for the texture
    //world.GL.gl.texStorage2D(world.GL.gl.TEXTURE_2D, 1, world.GL.gl.RGB8, 512, 512);
    //world.GL.gl.texSubImage2D(world.GL.gl.TEXTURE_2D, 0, 0, 0, world.GL.gl.RGB, world.GL.gl.UNSIGNED_BYTE, image);
    //world.GL.gl.generateMipmap(world.GL.gl.TEXTURE_2D);
    world.GL.gl.uniform1i(object.shaderProgram.samplerUniform, t);

}

...

也许在运行时最好的方法是使用object.textures数组进行操作?!

  • 最后:

    • 使用新标记覆盖着色器
    • 编译着色器 新材料已更新

1 个答案:

答案 0 :(得分:1)

你想要完成什么?

使用大量纹理的普通方法是使用texture atlas底部覆盖的this article

否则,没有办法检测着色器中是否加载了纹理。你需要传递自己的旗帜。例如

 uniform bool textureLoaded[NUM_TEXTURES];

 uniform float textureMixAmount[NUM_TEXTURES];

如果我是你,我会使用纹理图集,除非你真的知道你正在做一些实际上需要14个纹理的独特的东西。

在运行中生成着色器也很常见。几乎所有游戏引擎都这样做。 Three.js也是如此。因此,不是打开和关闭纹理,而是编写一些为N纹理生成着色器的代码。然后当你只有一个纹理生成一个纹理着色器时,当你有2个生成一个2纹理着色器等时,对于GPU而言,这比使用14纹理着色器并试图关闭13个纹理要高效得多。

示例:

// note, I'm not recommending this shader, only showing some code
// that generates a shader

function generateShaderSrc(numTextures) {

  return `
    // shader for ${numTextures} textures
    precision mediump float;
    
    varying vec2 vTextureCoord;
    varying vec3 vLightWeighting;

    uniform sampler2D uSampler[${numTextures}];
    uniform float uMixAmount[${numTextures}];
    
    void main() {
      vec4 color = vec4(0);

      for (int i = 0; i < ${numTextures}; ++i) {
        vec4 texColor = texture2D(uSampler[i], vTextureCoord);
        color = mix(color, texColor, uMixAmount[i]);
      }
      
      gl_FragColor = color;
    }
  `;
}

log(generateShaderSrc(1));
log(generateShaderSrc(4));

function log(...args) {
  const elem = document.createElement("pre");
  elem.textContent = [...args].join(' ');
  document.body.appendChild(elem);
}

这是一个非常简单的例子。真正的着色器生成器通常会执行更多的字符串操作。

您还应该知道WebGL 1.0仅需要支持8个纹理单元。 According to webglstats about 15% of devices only support 8 texture units所以您可能想要检查用户拥有多少纹理单位,并警告他们如果应用程序的应用程序需求少于您的应用程序,那么该应用程序将无法运行。