同一程序的多个输出纹理 [英] Multiple output textures from the same program

查看:65
本文介绍了同一程序的多个输出纹理的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试学习如何利用 gl.drawBuffer()功能从WebGL2中的同一程序进行多个输出.

I'm trying to learn how to do multiple outputs from the same program in WebGL2 leveraging gl.drawBuffer() capabilities.

我看了《 OpenGL ES 3.0编程指南》这本书,在第11章中列出了进行多输出所需要的内容.但是,着色器源示例非常琐碎,仅输出恒定值.

I looked at the book "OpenGL ES 3.0 Programming Guide", chapter 11 where it lists what is needed for multi-output to take place. However the shader source example is very trivial outputting only constant values.

我想知道是否有人有更好的例子?还是可以解释一下TextureCoordinates发生了什么变化?在普通的着色器代码中,我将使用它来从输入中查找数据值并将其写出.现在面对多种布局,TextureCoordinates变化如何对应于每个布局?viewPort的尺寸会发生什么变化?哪个输出纹理对应?

I'd like to know if someone has a better example? or if one could explain what happened to the TextureCoordinates varying? In normal shader code I would use that to find data values from my inputs and write them out. Now in the face of multiple layouts, how would the TextureCoordinates varying correspond to each layout? What happens to the dimensions of my viewPort? which output Texture does that correspond with?

以下是我理解它们的一些步骤:

Here are some steps the way I understood them:

  1. 创建颜色附件数组GL_COLOR_ATTACHMENT0,...
  2. 为每个输出创建一个帧缓冲对象
  3. 创建输出纹理
  4. 对于每个FB:

  1. Create a Color attachment array GL_COLOR_ATTACHMENT0, ...
  2. Create a framebuffer object for each output
  3. Create output textures
  4. For each FB:

  • BindFramebuffer
  • BindTexture
  • 将纹理与FBO相关联:frameBufferTexture2D(...,color_attchment_from_step1)

调用drawBuffers通过颜色附件数组

call drawBuffers passing the color attachment array

在着色器内部访问如下输出值:

Inside the shader access output values like this:

layout(location = 0) out vec4 fragData0;

layout(location = 1) out vec4 fragData1;

推荐答案

您只需要一个framebuffer对象.您将所有纹理附加到它.所以您的步骤将是

You only need one framebuffer object. You attach all the textures to it. So your steps would be

  1. 创建一个帧缓冲对象和BindFramebuffer
  2. 创建输出纹理
  3. 对于每种纹理:
  4. 将纹理与FBO相关联:frameBufferTexture2D(...)
  5. 创建颜色附件数组GL_COLOR_ATTACHMENT0,...
  6. 调用drawBuffers传递颜色附件数组

function main() {
  const gl = document.querySelector('canvas').getContext('webgl2');
  if (!gl) {
    return alert("need WebGL2");
  }
  const vs = `
  #version 300 es
  void main() {
    gl_PointSize = 300.0;
    gl_Position = vec4(0, 0, 0, 1);
  }
  `;

  const fs = `
  #version 300 es
  precision mediump float;

  layout(location = 0) out vec4 outColor0;
  layout(location = 1) out vec4 outColor1;
  layout(location = 2) out vec4 outColor2;
  layout(location = 3) out vec4 outColor3;

  void main() {
    outColor0 = vec4(1, .5, .3, .7);   // orange
    outColor1 = vec4(.6, .5, .4, .3);  // brown
    outColor2 = vec4(.2, .8, .0,  1);  // green
    outColor3 = vec4(.3, .4, .9, .6);  // blue
  } 
  `

  const program = twgl.createProgram(gl, [vs, fs]);

  const textures = [];
  const fb = gl.createFramebuffer();
  gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
  for (let i = 0; i < 4; ++i) {
    const tex = gl.createTexture();
    textures.push(tex);
    gl.bindTexture(gl.TEXTURE_2D, tex);
    const width = 1;
    const height = 1;
    const level = 0;
    gl.texImage2D(gl.TEXTURE_2D, level, gl.RGBA, width, height, 0, 
                  gl.RGBA, gl.UNSIGNED_BYTE, null);
    // attach texture to framebuffer
    gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0 + i,
                            gl.TEXTURE_2D, tex, level);
  }

  // our framebuffer textures are only 1x1 pixels
  gl.viewport(0, 0, 1, 1);

  // tell it we want to draw to all 4 attachments
  gl.drawBuffers([
    gl.COLOR_ATTACHMENT0,
    gl.COLOR_ATTACHMENT1, 
    gl.COLOR_ATTACHMENT2,
    gl.COLOR_ATTACHMENT3,
  ]);

  // draw a single point
  gl.useProgram(program);
  {
    const offset = 0;
    const count = 1
    gl.drawArrays(gl.POINT, 0, 1);
  }

  // --- below this is not relevant to the question but just so we
  // --- we can see it's working

  // render the 4 textures
  const fs2 = `
  #version 300 es
  precision mediump float;
  uniform sampler2D tex[4];
  out vec4 outColor;
  void main() {
    vec4 colors[4];

    // you can't index textures with non-constant integer expressions
    // in WebGL2 (you can in WebGL1 lol)
    colors[0] = texture(tex[0], vec2(0));
    colors[1] = texture(tex[1], vec2(0));
    colors[2] = texture(tex[2], vec2(0));
    colors[3] = texture(tex[3], vec2(0));
    
    vec4 color = vec4(0);
    for (int i = 0; i < 4; ++i) { 
      float x = gl_PointCoord.x * 4.0;
      float amount = step(float(i), x) * step(x, float(i + 1));
      color = mix(color, colors[i], amount);
    }
    outColor = vec4(color.rgb, 1);
  }
  `;
  const prgInfo2 = twgl.createProgramInfo(gl, [vs, fs2]);
  gl.bindFramebuffer(gl.FRAMEBUFFER, null);
  gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);
  gl.useProgram(prgInfo2.program);
  // binds all the textures and set the uniforms
  twgl.setUniforms(prgInfo2, {
    tex: textures,
  });
  gl.drawArrays(gl.POINTS, 0, 1);
}
main();

<script src="https://twgljs.org/dist/4.x/twgl.min.js"></script>
<canvas></canvas>

这篇关于同一程序的多个输出纹理的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆