首页 > 解决方案 > Right order to specifying framebuffer and binding uniform textures?

问题描述

Is there a sequence to setting the output of a program and binding textures to uniforms in the fragment shader?

I have the following code. If I place the lines containing "attachFrameBuffer" after the last "g.uniform1i()" call, I get the error:

There is no texture bound to the unit 1.

But if I leave them where they are then everything is fine. This worries me that there is more initialization that I probably have missed.

gl.useProgram(program);

// Create and bind a framebuffer
var outputTexture = this.makeTexture(gl.FLOAT, null);
this.attachFrameBuffer(outputTexture);

gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, aTexture);
gl.uniform1i(AHandle, 0);

gl.activeTexture(gl.TEXTURE1);
gl.bindTexture(gl.TEXTURE_2D, bTexture);
gl.uniform1i(BHandle, 1);

gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);

and the code for makeTexture:

   texture = gl.createTexture();
   // Bind the texture so the following methods effect this texture.
   gl.bindTexture(gl.TEXTURE_2D, texture);
   gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
   gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
   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);
   // Pixel format and data for the texture
   gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, type, data);
   // Unbind the texture.
   gl.bindTexture(gl.TEXTURE_2D, null);

code for attachFrameBuffer():

   frameBuffer = gl.createFramebuffer();
   gl.bindFramebuffer(gl.FRAMEBUFFER, frameBuffer);
   gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0); 

标签: webgl

解决方案


纹理绑定到“纹理单元”。纹理单元是全局状态。你可以想象他们是这样的

glState = {
  activeTextureUnit: 0,
  textureUnits: [
    { TEXTURE_2D: null, TEXTURE_CUBE_MAP: null, },
    { TEXTURE_2D: null, TEXTURE_CUBE_MAP: null, },
    { TEXTURE_2D: null, TEXTURE_CUBE_MAP: null, },
    { TEXTURE_2D: null, TEXTURE_CUBE_MAP: null, },
    ...
    ... up to gl.getParameter(gl.MAX_TEXTURE_IMAGE_UNITS) ....
  ]
};

当你调用gl.activeTexture(textureUnit)WebGL 内部发生的事情时

gl.activeTexture = function(textureUnit) {
  // convert texture unit to 0 to N index
  glState.activeTextureUnit = textureUnit - gl.TEXTURE0;
};

当你打电话时会发生gl.bindTexture什么

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

统一采样器间接引用纹理单元。你给他们你希望他们从中获取纹理的纹理单元的索引。

所以,在你的情况下,这段代码

gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, aTexture);

gl.activeTexture(gl.TEXTURE1);
gl.bindTexture(gl.TEXTURE_2D, bTexture);

有效地使 glState

glState = {
  activeTextureUnit: 1,    // because the last call to activeTexture was gl.TEXTURE1
  textureUnits: [
    { TEXTURE_2D: aTexture, TEXTURE_CUBE_MAP: null, },  // <=- aTexture bound
    { TEXTURE_2D: bTexture, TEXTURE_CUBE_MAP: null, },  // <=- bTexture bound
    { TEXTURE_2D: null, TEXTURE_CUBE_MAP: null, },
    { TEXTURE_2D: null, TEXTURE_CUBE_MAP: null, },
    ...
    ... up to gl.getParameter(gl.MAX_TEXTURE_IMAGE_UNITS) ....
  ]
};

如果你打电话

// Create and bind a framebuffer
var outputTexture = this.makeTexture(gl.FLOAT, null);
this.attachFrameBuffer(outputTexture);

之后,好吧,makeTexture将不同的纹理绑定到单元 1(因为上次调用activeTexture设置activeTextureUnit为 1。然后在最后它绑定null,因此不再有纹理绑定到单元 1。然后你绘制并得到你看到的错误

There is no texture bound to the unit 1.

没有“正确的顺序”。只有全局 webgl 状态,您有责任在调用gl.draw???. 你可以随心所欲地做到这一点。例如,您可以让 makeTexture 在制作纹理时使用不同的纹理单元。您还可以让 makeTexture 查找当前绑定的纹理,制作其新纹理,然后重新绑定旧纹理。或者,就像您发现的那样,您可以在绑定纹理以进行绘图之前调用它。

也就是说,您的代码确实看起来有点可疑,因为大多数 WebGL 应用程序绘制了很多次,因此它们通常将资源创建代码(初始化)与渲染代码(绘图)分开。创建代码创建着色器、程序、缓冲区、纹理,可能还有顶点数组对象,渲染代码使用它们。

然后渲染代码将设置绘制所需的所有状态

for each thing to draw
  useProgram 
  bind buffers and set attributes (or use vertex array object)
  bind textures to texture units
  set uniforms for program
  draw

但是您发布的代码useProgram遵循了我makeTexture的创建时间问题(您不太可能在每次绘制调用之前创建纹理)。因此,随着您的程序变大,您可能会makeTexture在初始化/创建时调用其他地方,而不是绘制/渲染时间

PS:这是一个webgl 状态图,您可以单步查看 WebGL 状态变化。


推荐阅读