1

I'm trying to use two textures in a fragment shader and having trouble getting WebGL to send the textures properly. I can send one at a time, but when I try to do both at once, I just get black. I've seen some other multitexturing examples around, but all of them deal with loading an array of images.

I want to load a video into one texture, and a canvas into the 2nd texture. I'm fairly certain all my shaders are fine, since I'm just moving them over from a c++ opengl program I wrote. Also, I can display the video or canvas each separately by commenting one or the other out, but like I mentioned above, together they seem to trigger an error.

Here's the snippet of code where I'm creating and filling the textures.

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);

And then inside my draw loop:

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);

I'm also getting a warning message saying:

GL_INVALID_ENUM : glActiveTexture: texture was GL_FALSE

GL_INVALID_ENUM : glActiveTexture: texture was GL_LINES

and also:

WebGL: drawArrays: texture bound to texture unit 0 is not renderable. It maybe non-power-of-2 and have incompatible texture filtering or is not 'texture complete'. Or the texture is Float or Half Float type with linear filtering while OES_float_linear or OES_half_float_linear extension is not enabled.

The line triggering the warning is:

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

Thanks in advance for the help!

4

1 回答 1

2

gl.activeTexture设置纹理单元所有其他纹理命令效果。对于每个纹理单元,有 2 个绑定点,TEXTURE_2D并且TEXTURE_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 个纹理,texture1但是texture2它只设置纹理参数,texture2因为第二次调用设置绑定到gl.bindTexture当前绑定点的纹理,然后只运行在那个纹理上。activeTextureTEXTURE_2Dgl.texParameteri

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

类似地,绘制代码需要调用gl.activeTexture和/或gl.bindTexture在调用之前调用,否则它正在对绑定到当前活动纹理单元上的gl.texImage2D绑定点的任何纹理进行操作。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);
于 2014-02-27T07:54:58.333 回答