webgl2 实现msaa

官网上的示例加了许多新东西,不太利于理解,因此自己重新实现了一遍

主要就是renderbuffer后进行blit的操作。

直接替换掉 webgl指南源码中的framebufferObject中的代码即可,将context改为webgl2

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

//顶点坐标,纹理坐标,模型视图矩阵,将顶点着色器中的纹理坐标传递给片元v_TexCoord纹理坐标
var m_VSHADER_SOURCE =
    'attribute vec4 a_Position;\n' +
    'varying vec2 v_TexCoord;\n' +
    'attribute vec2 a_TexCoord;\n' +

    'void main() {\n' +
    '  gl_Position = a_Position;\n' +
    '  v_TexCoord = a_TexCoord;\n' +
    '}\n';

// 采样器,纹理坐标,纹理着色片元
var m_FSHADER_SOURCE =

    '#ifdef GL_ES\n' +
    'precision mediump float;\n' +
    '#endif\n' +
    'uniform sampler2D u_Sampler;\n' +
    'varying vec2 v_TexCoord;\n' +
    'void main() {\n' +
    '  gl_FragColor = texture2D(u_Sampler, v_TexCoord);\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 =
    'void main() {\n' +
    '  gl_FragData[0] = vec4(1.0, 0.0, 0.0, 1.0);\n' +

    '}\n';
// Size of off screen

var FRAMEBUFFER_SIZE
var  enabelMsaa = false;
function main() {
    // Retrieve <canvas> element
    var canvas = document.getElementById('webgl');
    FRAMEBUFFER_SIZE = {
        x: canvas.width,
        y: canvas.height
    };

    // Get the rendering context for 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);

    let colorfbo = gl.createFramebuffer();

    {
        gl.bindFramebuffer(gl.FRAMEBUFFER, colorfbo);
        let 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, FRAMEBUFFER_SIZE.x, FRAMEBUFFER_SIZE.y, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
        colorfbo.texture = texture; // Store the texture object
        gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0);
        gl.bindFramebuffer(gl.FRAMEBUFFER, null);
    }

    // Write the positions of vertices to a vertex shader
    gl.bindFramebuffer(gl.FRAMEBUFFER,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(enabelMsaa){
        gl.drawArrays(gl.LINE_LOOP, 0, n);
    }
    else{
        gl.bindFramebuffer(gl.FRAMEBUFFER, null);
        gl.drawArrays(gl.LINE_LOOP, 0, n);
        return
    }
    gl.bindFramebuffer(gl.READ_FRAMEBUFFER, fbo);
    gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER,colorfbo );
    gl.clearBufferfv(gl.COLOR, 0, [0.0, 0.0, 0.0, 1.0]);
    gl.blitFramebuffer(
        0, 0, FRAMEBUFFER_SIZE.x, FRAMEBUFFER_SIZE.y,
        0, 0, FRAMEBUFFER_SIZE.x, FRAMEBUFFER_SIZE.y,
        gl.COLOR_BUFFER_BIT, gl.NEAREST
    );
    gl.bindFramebuffer(gl.FRAMEBUFFER, null);        // Change the drawing destination to color buffer
    gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);  // Clear FBO

    {
        let initProgram =  initShaders(gl, m_VSHADER_SOURCE, m_FSHADER_SOURCE)
        n = initVertexBuffers2(gl)
        gl.activeTexture(gl.TEXTURE0);
        gl.bindTexture(gl.TEXTURE_2D, colorfbo.texture)
        gl.drawArrays(gl.TRIANGLE_STRIP, 0, n);
    }



}
function initFramebufferObject(gl,ext) {
    var framebuffer, texture, 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, FRAMEBUFFER_SIZE.x, FRAMEBUFFER_SIZE.y, 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
    }
    // 4.将帧缓冲区绑定到程序上
    gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);
    //5.输出到对应的纹理中
    gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0);


    // 7.创建渲染缓冲区 gl.createRenderbuffer(),输出深度值
    {
        depthBuffer = gl.createRenderbuffer(); // Create a renderbuffer object
        gl.bindRenderbuffer(gl.RENDERBUFFER, depthBuffer); // Bind the object to target

        gl.renderbufferStorageMultisample(gl.RENDERBUFFER, 8, gl.RGBA8, FRAMEBUFFER_SIZE.x, FRAMEBUFFER_SIZE.y);
        //将帧缓冲区绑定到渲染缓冲区上
        gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, 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 vertexCount = 18;
    var data = new Float32Array(vertexCount * 2);
    var angle;
    var radius = 1;
    ///圆上的分割点
    for(var i = 0; i < vertexCount; i++ )
    {
        angle = Math.PI * 2 * i / vertexCount;
        data[2 * i] = radius * Math.sin(angle);
        data[2 * i + 1] = radius * Math.cos(angle);
    }
    // console.log(data)
    // -- Init buffers
    var vertexDataBuffer = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, vertexDataBuffer);
    gl.bufferData(gl.ARRAY_BUFFER, data, gl.STATIC_DRAW);
    var a_Position = gl.getAttribLocation(gl.program, 'a_Position');
    gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, 0, 0);
    gl.enableVertexAttribArray(a_Position);

    return vertexCount;
}

function initVertexBuffers2(gl) {
    var verticesTexCoords = new Float32Array([
        // Vertex coordinates, texture coordinate
        -1,  1,   0.0, 1.0,
        -1, -1,   0.0, 0.0,
        1,  1,   1.0, 1.0,
        1, -1,   1.0, 0.0,
    ]);
    var n = 4; // The number of vertices

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

    // Bind the buffer object to target
    gl.bindBuffer(gl.ARRAY_BUFFER, vertexTexCoordBuffer);
    gl.bufferData(gl.ARRAY_BUFFER, verticesTexCoords, gl.STATIC_DRAW);

    var FSIZE = verticesTexCoords.BYTES_PER_ELEMENT;
    //Get the storage location of a_Position, assign and enable buffer
    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, FSIZE * 4, 0);
    gl.enableVertexAttribArray(a_Position);  // Enable the assignment of the buffer object

    // Get the storage location of a_TexCoord
    var a_TexCoord = gl.getAttribLocation(gl.program, 'a_TexCoord');
    if (a_TexCoord < 0) {
        console.log('Failed to get the storage location of a_TexCoord');
        return -1;
    }
    // Assign the buffer object to a_TexCoord variable
    gl.vertexAttribPointer(a_TexCoord, 2, gl.FLOAT, false, FSIZE * 4, FSIZE * 2);
    gl.enableVertexAttribArray(a_TexCoord);  // Enable the assignment of the buffer object

    return n;
}

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: WebGL 是一种基于 JavaScript 和 OpenGL 的 3D 图形库,它可以在 Web 浏览器中渲染 3D 图形,从而实现浏览器中的 3D 视觉效果。实现阴影效果可以使用 WebGL 中的阴影映射技术,简单来说,就是在场景中添加光源,然后从光源的角度渲染场景,生成一张深度图,再将深度图应用到场景中的物体上,就可以实现阴影效果了。同时,还可以使用其他技术,例如环境映射和法线映射,来增强场景的真实感和深度感。总之,WebGL 提供了丰富的工具和技术,使得在 Web 浏览器中实现 3D 阴影效果成为可能。 ### 回答2: WebGL是一种基于Web的图形渲染技术,可以实现高性能的3D图形渲染。要实现阴影效果,可以借助WebGL的功能来完成。 首先,要实现阴影效果,需要一个光源。在WebGL中,可以通过设置光源的位置和方向来控制光的照射效果。 其次,还需要一个或多个需要投射阴影的物体。通过在渲染过程中为这些物体添加一个额外的"shadow"属性,可以标识它们需要投射阴影。 然后,在渲染阴影之前,需要创建一个用于渲染阴影的额外场景。在该场景中,只包含需要投射阴影的物体。这个场景可以使用一个特殊的着色器来渲染,这个着色器和其他场景使用的着色器可能稍有不同,因为它只关注渲染阴影而不需要考虑光照。 接下来,在渲染主场景之前,需要对每个需要投射阴影的物体进行阴影计算。这可以通过使用光源的位置和方向来确定每个像素是否在阴影之中。可以使用阴影映射技术(Shadow Mapping)来完成这个计算过程,这个过程涉及渲染一个特殊的深度贴图来表示场景中的深度信息。 最后,在主场景渲染过程中,可以使用计算得到的阴影信息来对物体进行阴影投射。可以使用对阴影贴图进行采样的方式,来判断像素是否位于阴影之中。 综上所述,WebGL通过设置光源、创建阴影场景、进行阴影计算和使用阴影信息投射,可以实现3D场景中的阴影效果。 ### 回答3: WebGL是一种在网页浏览器上运行3D图形的技术,它使用JavaScript和OpenGL的子集来实现。要实现阴影效果,我们可以借助WebGL的着色器程序和纹理功能。 首先,为了产生阴影,我们需要一个光源。可以使用WebGL的光照功能来定义光源的位置和类型,例如平行光或点光源。 接下来,我们需要为阴影接收器(即产生阴影的物体)和阴影投射器(即光源)创建阴影贴图。阴影贴图是一个与场景大小相同的二维纹理,它记录了物体与光源之间的相对位置关系。 然后,我们需要通过在阴影投射器和阴影接收器之间进行渲染来生成阴影贴图。我们可以使用投射阴影的算法,如阴影映射或体积光,来计算每个像素的阴影强度。 在渲染阶段,我们可以在顶点着色器和片段着色器中应用阴影贴图。顶点着色器将物体的顶点位置转换为世界坐标和光源坐标,并将它们传递给片段着色器。片段着色器使用阴影贴图来计算每个像素的阴影强度,并将其与物体的颜色进行混合。 最后,我们可以通过在片段着色器中使用深度测试来控制阴影的渲染顺序,并使用透明度来调整阴影的强度和透明度。 总体来说,WebGL通过使用光照、阴影贴图和着色器程序来实现阴影效果。这样可以使3D场景更加逼真和生动,并增强用户对物体之间关系的认知。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值