WebGL - 连续应用多个程序

时间:2016-05-02 20:44:56

标签: javascript webgl post-processing

如何让WebGl连续应用多个程序,例如

  • 画一些东西
  • 将其转换为黑白

在这个例子中,很容易将所有内容放在一个着色器中,但我希望能够将事物分开,以便重复使用较大的着色器。

到目前为止,要做一次通过,我就像

gl = canvas.getContext("webgl");
gl.viewport(0, 0, canvas.width, canvas.height);

fragmentShader = attachShader(fragmentShaderCode, gl, gl.FRAGMENT_SHADER);
vertexShader = attachShader(vertexShaderCode, gl, gl.VERTEX_SHADER);

program = gl.createProgram();
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragmentShader);
gl.linkProgram(program);

gl.useProgram(program);

// attach textures and variables

gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0);

并且我不确定如何有效地添加第一次传递的第二次传递。我最好的猜测是使用第二个画布,将第一个画布作为纹理输入。但这听起来像渲染两次而且不是很棒。

2 个答案:

答案 0 :(得分:4)

除了WebGL术语之外@ssube所说的......

在初始时

  1. 您创建了一个帧缓冲区(gl.createFramebuffer)
  2. 您附加纹理(gl.framebufferTexture2D)。
  3. 如果您的场景需要深度缓冲区,您还需要将深度缓冲区附加到帧缓冲区(gl.renderbufferStorage,gl.framebufferRenderbuffer)。
  4. 在渲染时间

    1. 通过帧缓冲区将场景渲染到纹理中。

      // make rendering render to framebuffer's attachments
      gl.bindFramebuffer(gl.FRAMEBUFFER, yourFramebuffer);
      
      // .. render scene ..
      
    2. 然后使用后期处理着色器渲染到framebuffer的纹理到画布

      // make rendering render to canvas
      gl.bindFramebuffer(gl.FRAMEBUFFER, null);
      
      // .. render framebuffer's texture to canvas with post processing shader..
      
    3. 正如@ssube所说,要应用多个后期处理效果,您可以创建带有附加纹理的帧缓冲区。您将场景渲染到第一个帧缓冲区纹理,然后使用第一个后​​期处理效果将该纹理渲染到第二个纹理中,现在您可以使用下一个后期处理效果将第二个纹理渲染回第一个纹理。最后一个后期处理效果渲染到画布。

      For an example of applying multiple effects see this

答案 1 :(得分:2)

你想要再次渲染,但你需要获取第一遍的输出并将其用作第二遍的输入纹理。

交换纹理和绘制矩形(两个tris)很便宜,尤其是在现代可编程硬件上。

对于简单效果(使用可见图像作为输入,而不是几何或深度),您:

  1. 像往常一样将场景绘制为可读纹理。
  2. 将该纹理绑定为下一个程序的输入。
  3. 使用您的程序和上一个输出绘制一个矩形。
  4. 您可以重复#2和#3来运行多种效果。这至多需要两个纹理(一个用作输入,一个用作输出,然后交换)。这适用于模糊,黑白,绽放等简单效果。

    更复杂的效果可能需要额外的输入纹理(包括深度),并且可能会使用其他数据。