【问题标题】:How to set the read-from and write-to textures for a fragment shader?如何为片段着色器设置读取和写入纹理?
【发布时间】:2017-12-29 08:45:14
【问题描述】:

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

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

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

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

编辑:

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

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

  1. 输入纹理,我可以从中读取 - 在这里,我需要将位置(即“u_image”)传递给片段着色器
  2. 输出纹理,我可以在其中写入 - 这是当前绑定的纹理(在上面提到的教程中,到纹理单元 0)

我无法完全理解此示例的工作原理,因为未设置 u_image 制服,而且代码中没有任何 gl.activeTexture() 调用

编辑 2:

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

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

【问题讨论】:

  • @Rabbid76: THX,在引用的示例中,绘图目标纹理是通过使用:gl.bindTexture(gl.TEXTURE_2D, textures[ii % 2]); 绑定的,所以我猜当前纹理单元始终为 0 并且永远不会改变,我怀疑是如何输入纹理工作...
  • @Rabbid76:编辑了我的问题

标签: webgl


【解决方案1】:
  1. 输入纹理,我可以从中读取 - 在这里,我需要将位置(即“u_image”)传递给片段着色器

是的,纹理可以这样使用。

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

纹理绑定的纹理单元,可以通过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");

程序变成activ program(useProgram)后,就可以设置纹理采样器制服了:

gl.uniform1i(u_image0Location, texUnit);


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

不,完全错误。没有什么能比得上输出纹理,而且肯定绑定到纹理单元 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.texImage2D) fbTexObj 时,任何纹理单元都可以处于活动状态。

【讨论】:

  • 如果我理解正确:鉴于帧缓冲区对象只是一堆附件 - 我应该告诉 WebGL 我的绘图应写入特定纹理(我称之为 输出 i>) 通过使用 framebufferTexture2D 将该纹理附加到 fbo ?我现在正确吗? (即使这不是 100% 完美的表达方式……)
  • @deblocker 是的,你可以这样说
  • 非常感谢!即使你没有回答我所有的问题,你也帮助我在理解这些东西的工作原理方面向前迈出了一大步。
猜你喜欢
  • 2013-09-17
  • 2019-01-23
  • 2011-11-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多