webgl draw_buffers mrt

主题逻辑与framebuffer 的实现没有什么区别,主要的区别在于初始化frameuffer时,要调用draw_buffers,着色器中使用gl_fragData数组

开启扩展,

渲染流程如下:

 

shader部分

初始化帧缓冲区部分

使用texture部分

原始代码  (本文所用的代码均截至 webgl指南源码的 framebufferObjects中,可以用下面代码直接替换原书中的代码即可)

// HelloQuad.js (c) 2012 matsuda
// Vertex shader program

//顶点坐标,纹理坐标,模型视图矩阵,将顶点着色器中的纹理坐标传递给片元v_TexCoord纹理坐标
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'




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';
// Size of off screen
var OFFSCREEN_WIDTH = 256;
var OFFSCREEN_HEIGHT = 256;

function main() {
    // Retrieve <canvas> element
    var canvas = document.getElementById('webgl');

    // Get the rendering context for WebGL
    var gl = getWebGLContext(canvas);
    var ext = gl.getExtension('WEBGL_draw_buffers');
    // 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);

    // Write the positions of vertices to a vertex shader
    var n = initVertexBuffers(gl);


        //绑定帧缓冲区
    // gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);              // Change the drawing destination to FBO
    //
    //
    // gl.bindFramebuffer(gl.FRAMEBUFFER,null)


    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;
    }

    // Specify the color for clearing <canvas>
    gl.clearColor(0, 0, 0, 1);

    // Clear <canvas>
    gl.clear(gl.COLOR_BUFFER_BIT);

    gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);              // Change the drawing destination to FBO
    // Draw the rectangle
    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);
    // Bind the texture object to the target
    gl.activeTexture(gl.TEXTURE0);
    gl.bindTexture(gl.TEXTURE_2D, fbo.texture2);
     initVertexBuffers(gl);
    gl.drawArrays(gl.TRIANGLE_STRIP, 0, n);


}
function initFramebufferObject(gl,ext) {
    var framebuffer, texture,texture2, depthBuffer;

    //  1.创建FBO 帧缓冲区
    framebuffer = gl.createFramebuffer();
    // 2.创建texture1  texture = gl.createTexture(),并挂载到framebuffer.texture属性上
    {
        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
    }
    // 3.创建texture2  texture = gl.createTexture(),并挂载到framebuffer.texture2属性上
    {
        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
    }
    // 4.将帧缓冲区绑定到程序上
    gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);
    //5.输出到对应的纹理中
    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);
    //6.调用drawbuffers
    ext.drawBuffersWEBGL([
        ext.COLOR_ATTACHMENT0_WEBGL, // gl_FragData[0]
        ext.COLOR_ATTACHMENT1_WEBGL, // gl_FragData[1]
    ]);

    // 7.创建渲染缓冲区 gl.createRenderbuffer(),输出深度值
    {
        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);
    }
     //8.解除帧缓冲区绑定  解除 渲染缓冲区绑定,解除纹理绑定
    {  // 解除帧缓冲区绑定
        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

    // Create a buffer object
    var vertexBuffer = gl.createBuffer();
    if (!vertexBuffer) {
        console.log('Failed to create the buffer object');
        return -1;
    }

    // Bind the buffer object to target
    gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
    // Write date into the buffer object
    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;
    }
    // Assign the buffer object to a_Position variable
    gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, 0, 0);

    // Enable the assignment to a_Position variable
    gl.enableVertexAttribArray(a_Position);

    return n;
}

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值