如何设置片段着色器的读取和写入纹理?

时间:2017-12-29 08:45:14

标签: webgl

我是WebGL的新手,我正在尝试通过阅读本教程来了解WebGL纹理的工作原理:WebGL Image Processing Continued

在同一个教程系列中还有另一个example,它通过为输入纹理单元0和1明确设置uniform来使用两个纹理:

// set which texture units to render with.
gl.uniform1i(u_image0Location, 0);  // texture unit 0
gl.uniform1i(u_image1Location, 1);  // texture unit 1

但是在第一个例子中,片段着色器使用sampler2D u_image作为输入纹理,所以我希望在代码中会有类似的东西:

gl.uniform1i(gl.getUniformLocation(program, "u_image"), 0);

...但我无法找到它。 这是如何工作的?只是猜测:所有WebGL程序中所有2D采样器的默认纹理单元0是什么?那么,为什么第二个例子中需要gl.uniform1i(u_image0Location, 0);

编辑:

到目前为止,我从上面提到的教程中了解到 - 如果我错了,请纠正我:

至少有两种使用纹理的方法:

  1. 输入纹理,我可以从中读取 - 在这里,我需要传递给片段着色器的位置(即" u_image")
  2. 输出纹理,我可以写入 - 这是当前绑定的纹理(在上面提到的教程中,纹理单元0)
  3. 我无法完全理解此示例的工作原理,因为未设置u_image制服,而且代码中没有任何gl.activeTexture()调用

    编辑2:

    感谢Rabbid76我相信我在gman(上述教程的作者)in this answerquestion的评论中找到了进一步的说明:

      

    你需要framebuffers。通过将纹理附加到帧缓冲区和   然后绑定那个帧缓冲区你正在使着色器写入   质地。

1 个答案:

答案 0 :(得分:1)

  
      
  1. 输入纹理,我可以从中读取 - 在这里,我需要将片段着色器传递给位置(即" u_image")
  2.   

是的,纹理可以这种方式使用。

如果要在片段着色器中使用不同的纹理,则必须将纹理绑定到不同的纹理单元。并且您必须将纹理单元的索引设置为纹理采样器均匀变量。

纹理绑定到的纹理单元可以由WebGLRenderingContext.activeTexture()设置:

var textureObj = gl.createTexture();
.....

var texUnit = 0; // texture unit 0 in this example
gl.activeTexture(gl.TEXTURE0 + texUnit);
gl.bindTexture(gl.TEXTURE_2D, textureObj);

链接程序(linkProgram)后,可以检索纹理采样器制服的位置:

u_image0Location = gl.getUniformLocation(program, "u_image");

程序成为活动程序(useProgram)后,可以设置纹理采样器制服:

gl.uniform1i(u_image0Location, texUnit);


  
      
  1. 输出纹理,我可以写入 - 这是当前绑定的纹理(在上面提到的教程中,纹理单元0)
  2.   

不,完全错了。没有什么比输出纹理更好,并且确保绑定到纹理单元0的纹理不是输出纹理。

在片段着色器中,您写入gl_FragColor。您写入gl_FragColor的颜色将存储在片段位置的帧缓冲区中。

如果您要写入纹理,则必须通过WebGLRenderingContext.framebufferTexture2D()将纹理附加到帧缓冲区:

var vp_w, vp_h; // withd and height of the viewport

var fbTexObj = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, fbTexObj );
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, vp_w, vp_h, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
.....

var fbo = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);

gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, fbTexObj, 0);

注意,绑定(gl.bindTexture)并指定(gl.texImage2DfbTexObj时,任何纹理单元都可以处于活动状态。