【问题标题】:WebGL Multitexturing with Video带有视频的 WebGL 多纹理
【发布时间】:2014-03-30 08:05:51
【问题描述】:

我正在尝试在片段着色器中使用两个纹理,但无法让 WebGL 正确发送纹理。我可以一次发送一个,但是当我尝试同时发送两个时,我只会变黑。我已经看到了一些其他的多纹理示例,但它们都处理加载图像数组。

我想将视频加载到一个纹理中,并将画布加载到第二个纹理中。我相当肯定我的所有着色器都很好,因为我只是将它们从我编写的 c++ opengl 程序中移过来。此外,我可以通过评论一个或另一个来分别显示视频或画布,但就像我上面提到的那样,它们似乎一起触发了错误。

这是我创建和填充纹理的代码的 sn-p。

var texture1 = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, texture1);

var texture2 = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, texture2);

gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MIN_FILTER, gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MAG_FILTER, gl.NEAREST);

然后在我的绘制循环中:

gl.texImage2D(gl.TEXTURE_2D,0,gl.RGBA,gl.RGBA,gl.UNSIGNED_BYTE, video);
var tex1loc = gl.getUniformLocation(program,"u_image");
gl.uniform1i(tex1loc, 0);
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, texture1);

gl.texImage2D(gl.TEXTURE_2D,0,gl.RGBA,gl.RGBA,gl.UNSIGNED_BYTE, canvas);
var tex2loc = gl.getUniformLocation(program, "u_image2");
gl.uniform1i(tex2loc, 1);
gl.activeTexture(gl.TEXTURE1);
gl.bindTexture(gl.TEXTURE_2D, texture2);

我还收到一条警告消息:

GL_INVALID_ENUM : glActiveTexture: 纹理是 GL_FALSE

GL_INVALID_ENUM : glActiveTexture: 纹理是 GL_LINES

还有:

WebGL:drawArrays:绑定到纹理单元 0 的纹理不可渲染。它可能不是 2 的幂并且具有不兼容的纹理过滤或不是“纹理完整”。或者纹理是具有线性过滤的浮点或半浮点类型,而 OES_float_linear 或 OES_half_float_linear 扩展未启用。

触发警告的行是:

gl.drawArrays(gl.TRIANGLES, 0,6);

提前感谢您的帮助!

【问题讨论】:

    标签: canvas webgl shader texturing multitexturing


    【解决方案1】:

    gl.activeTexture 设置纹理单元所有其他纹理命令效果。每个纹理单元有 2 个绑定点,TEXTURE_2DTEXTURE_CUBE_MAP

    你可以这样想

    gl = {
      activeTextureUnit: 0,
      textureUnits: [
         { TEXTURE_2D: null: TEXTURE_CUBE_MAP: null, },
         { TEXTURE_2D: null: TEXTURE_CUBE_MAP: null, },
         { TEXTURE_2D: null: TEXTURE_CUBE_MAP: null, },
         ...
      ],
    };
    

    gl.activeTexture 就是这么做的

    gl.activeTexture = function(unit) {
     gl.activeTextureUnit = unit - gl.TEXTURE0;
    };
    

    gl.bindTexture 这样做

    gl.bindTexture = function(bindPoint, texture) {
      gl.textureUnits[gl.activeTextureUnit][bindPoint] = texture;
    };
    

    gl.texImage2Dgl.texParamteri 像这样查找要使用的纹理

    gl.texImage2D = function(bindPoint, .....) {
      var texture = gl.textureUnits[gl.activeTextureUnit][bindPoint];
      // now do something with texture
    

    所以,知道了这一切,代码的第一个问题是它创建了 2 个纹理,texture1texture2,但它只设置了 texture2 的纹理参数,因为第二次调用 gl.bindTexture 设置了在其TEXTURE_2D 绑定点上绑定到当前activeTexture 的纹理,然后gl.texParameteri 仅对该纹理进行操作。

    在绑定texture2之前需要设置texture1的参数。

    类似地,绘制代码需要在调用gl.texImage2D 之前调用gl.activeTexture 和/或gl.bindTexture,否则它正在对绑定到绑定点TEXTURE_2D 的任何纹理进行操作,无论是当前活动的纹理单元。

    至于您与gl.activeTexture 相关的警告,您确定您发布了所有与纹理相关的代码吗?如果您发布了所有这些警告,则这些警告没有多大意义,因为您对 gl.activeTexture 的唯一调用看起来是有效的。

    否则,关于单元 0 上的纹理不可渲染的另一个警告是因为您没有如上所述设置 texture1 的参数。

    所以,要清楚,你的代码应该是这样的

    var texture1 = gl.createTexture();
    gl.bindTexture(gl.TEXTURE_2D, texture1);
    
    // you need to set parameters for texture1
    gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
    gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
    gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MIN_FILTER, gl.NEAREST);
    gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MAG_FILTER, gl.NEAREST);
    
    var texture2 = gl.createTexture();
    gl.bindTexture(gl.TEXTURE_2D, texture2);
    
    gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
    gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
    gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MIN_FILTER, gl.NEAREST);
    gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MAG_FILTER, gl.NEAREST);
    
    // these should be looked up at init time
    var tex1loc = gl.getUniformLocation(program,"u_image");
    var tex2loc = gl.getUniformLocation(program, "u_image2");
    

    绘制循环:

    // call active texture first
    gl.activeTexture(gl.TEXTURE0);
    // then bind a texture. This now binds texture1 to unit 0
    gl.bindTexture(gl.TEXTURE_2D, texture1);
    gl.texImage2D(gl.TEXTURE_2D,0,gl.RGBA,gl.RGBA,gl.UNSIGNED_BYTE, video);
    gl.uniform1i(tex1loc, 0);
    
    // call active texture first
    gl.activeTexture(gl.TEXTURE1);
    // then bind a texture. This now binds texture2 to unit 1
    gl.bindTexture(gl.TEXTURE_2D, texture2);
    gl.texImage2D(gl.TEXTURE_2D,0,gl.RGBA,gl.RGBA,gl.UNSIGNED_BYTE, canvas);
    gl.uniform1i(tex2loc, 1);
    

    【讨论】:

    • 你能举例说明draw call的样子吗?
    • gl.drawArrays(gl.TRIANGLE, 0, 6) 是一个平局调用。您提出这个问题的事实表明您可能会发现 some WebGL tutorials 非常有帮助。 WebGL 需要在每次绘制调用之前调用多达 60 个或更多函数来设置状态。所有这些函数的作用以及它们设置的状态对于单个 SO 答案来说太大了。
    猜你喜欢
    • 2012-04-14
    • 2018-11-08
    • 1970-01-01
    • 1970-01-01
    • 2020-09-17
    • 1970-01-01
    • 2016-02-06
    • 2011-10-15
    • 1970-01-01
    相关资源
    最近更新 更多