WebGL MRT 简单示例

718 阅读1分钟

Frame Buffer Object (csb.app)

(10条消息) webgl draw_buffers mrt_A873054267的博客-CSDN博客

image.png

FBO

  • 流程
    • texture
      • createTexture 创建
      • bindTexture 使用
      • texImage2D 输入数据
      • texParameteri 输入参数
    • framebuffer
      • createFramebuffer创建窗口
      • bindFramebuffer使用窗口
      • framebufferTexture2D framebuffer Texture2D进行attachment与texture绑定
      • drawBuffersWEBGL使用attachment
    • renderrbuffer
      • createRenderbuffer创建渲染
      • bindRenderbuffer使用渲染
      • renderbufferStorage精度大小
    • 两者
      • framebufferRenderbuffer
function initFramebufferObject(gl,ext) {
    var framebuffer, texture,texture2, depthBuffer;
    framebuffer = gl.createFramebuffer();
    {
        texture = gl.createTexture(); // Create a texture object
        gl.bindTexture(gl.TEXTURE_2D, texture); // Bind the object to target
        gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, OFFSCREEN_WIDTH, OFFSCREEN_HEIGHT, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
        framebuffer.texture = texture; // Store the texture object
    }
    {
        texture2 = gl.createTexture(); // Create a texture object
        gl.bindTexture(gl.TEXTURE_2D, texture2); // Bind the object to target
        gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, OFFSCREEN_WIDTH, OFFSCREEN_HEIGHT, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
        framebuffer.texture2 = texture2; // Store the texture object
    }
    gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);
    gl.framebufferTexture2D(gl.FRAMEBUFFER, ext.COLOR_ATTACHMENT0_WEBGL, gl.TEXTURE_2D, texture, 0);
    gl.framebufferTexture2D(gl.FRAMEBUFFER, ext.COLOR_ATTACHMENT1_WEBGL, gl.TEXTURE_2D, texture2, 0);
    ext.drawBuffersWEBGL([
        ext.COLOR_ATTACHMENT0_WEBGL, // gl_FragData[0]
        ext.COLOR_ATTACHMENT1_WEBGL, // gl_FragData[1]
    ]);
    {
        depthBuffer = gl.createRenderbuffer(); // Create a renderbuffer object
        gl.bindRenderbuffer(gl.RENDERBUFFER, depthBuffer); // Bind the object to target
        gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, OFFSCREEN_WIDTH, OFFSCREEN_HEIGHT);
        gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, depthBuffer);
    }
    {  // 解除帧缓冲区绑定
        gl.bindFramebuffer(gl.FRAMEBUFFER, null);
        gl.bindTexture(gl.TEXTURE_2D, null);
        gl.bindRenderbuffer(gl.RENDERBUFFER, null);
    }
    return framebuffer;
}

顶点数据

function initVertexBuffers(gl) {
    var vertices = new Float32Array([ //正方形
        -0.5, 0.5,   -0.5, -0.5,      0.5, 0.5, 0.5, -0.5
    ]);
    var n = 4; // The number of vertices
    var vertexBuffer = gl.createBuffer();
    if (!vertexBuffer) {
        console.log('Failed to create the buffer object');
        return -1;
    }
    gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
    gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
    var a_Position = gl.getAttribLocation(gl.program, 'a_Position');
    if (a_Position < 0) {
        console.log('Failed to get the storage location of a_Position');
        return -1;
    }
    gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, 0, 0);
    gl.enableVertexAttribArray(a_Position);
    return n;
}

main函数

function main() {
    var canvas = document.getElementById('webgl');
    var gl = getWebGLContext(canvas);
    var ext = gl.getExtension('WEBGL_draw_buffers');
    if (!gl) {
        console.log('Failed to get the rendering context for WebGL');
        return;
    }
   let initProgram =  initShaders(gl, VSHADER_SOURCE, FSHADER_SOURCE)
    var fbo = initFramebufferObject(gl,ext); //得到fbo
    var n = initVertexBuffers(gl); //得到
    gl.viewport(0, 0, OFFSCREEN_WIDTH, OFFSCREEN_HEIGHT); // Set a viewport for FBO
    gl.clearColor(0.2, 0.2, 0.4, 1.0); // Set clear color (the color is slightly changed)
    gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);  // Clear FBO
    if (n < 0) {
        console.log('Failed to set the positions of the vertices');
        return;
    }
    gl.clearColor(0, 0, 0, 1);
    gl.clear(gl.COLOR_BUFFER_BIT);
    gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);              // Change the drawing destination to FBO
    gl.drawArrays(gl.TRIANGLE_STRIP, 0, n);
    gl.bindFramebuffer(gl.FRAMEBUFFER, null);        // Change the drawing destination to color buffer
    gl.viewport(0, 0, canvas.width, canvas.height);  // Set the size of viewport back to that of <canvas>
    let newProgram =  initShaders(gl, m_VSHADER_SOURCE, m_FSHADER_SOURCE);
    gl.activeTexture(gl.TEXTURE0);
    gl.bindTexture(gl.TEXTURE_2D, fbo.texture2); //可以texture2替换为texture来试下
    initVertexBuffers(gl);
    gl.drawArrays(gl.TRIANGLE_STRIP, 0, n);
}

fbo 多Texture的glsl

  • 没有MRT输出用gl_FragColor
  • 有MRT输出用gl_FragData[0] gl_FragData[1]
  var VSHADER_SOURCE =
    "attribute vec4 a_Position;\n" +
    "void main() {\n" +
    "  gl_Position = a_Position;\n" +
    "}\n";

  // Fragment shader program
  var FSHADER_SOURCE =
    "#extension GL_EXT_draw_buffers : require\n" +
    "void main() {\n" +
    "  gl_FragData[0] = vec4(1.0, 0.0, 0.0, 1.0);\n" +
    "  gl_FragData[1] = vec4(0.0, 1.0, 0.0, 1.0);\n" +
    "}\n";

展示texture颜色的glsl

  var m_VSHADER_SOURCE =
    "attribute vec4 a_Position;\n" +
    "void main() {\n" +
    "  gl_Position = a_Position;\n" +
    "}\n";

  // 采样器,纹理坐标,纹理着色片元
  var m_FSHADER_SOURCE =
    "#ifdef GL_ES\n" +
    "precision mediump float;\n" +
    "#endif\n" +
    "uniform sampler2D u_Sampler;\n" +
    "void main() {\n" +
    "  gl_FragColor = texture2D(u_Sampler, vec2(0.5,0.5));\n" +
    "}\n";