帧缓冲区

帧缓冲区对象保存的是渲染的中间结果,因此分别存在三个关联对象——颜色关联对象(color attachment)、深度关联对象(depth attachment)和模版关联对象(stencil attachment),用来代替颜色缓冲区、深度缓冲区和模版缓冲区。

关联对象分为两种:纹理对象和渲染缓冲区对象(renderbuffer object)。

一般来说,可以定义一个纹理对象作为帧缓冲区的颜色关联对象,定义一个渲染缓冲区对象作为帧缓冲区的深度关联对象,来实现离屏绘制。![截屏2023-06-09 15.52.46](/Users/a666/Desktop/截屏2023-06-09 15.52.46.png)

帧缓冲区的具体设置过程可以分为以下8步:

  1. 创建帧缓冲对象(gl.createFramebuffer())

    // 初始化帧缓冲区对象 (FBO)
    function initFramebufferObject(gl) {
      //...
    
      // 创建帧缓冲区对象 (FBO)
      framebuffer = gl.createFramebuffer();
      if (!framebuffer) {
        console.log('Failed to create frame buffer object');
        return error();
      }
    
      //...
    }
    
  2. 创建纹理对象并设置其尺寸和参数

    gl.texImage2D函数的最后一个参数需设置为null,表示新建了一片空白区域,以便帧缓存绘制。

    function initFramebufferObject(gl) {
      //...
    
      // 创建纹理对象并设置其尺寸和参数
      texture = gl.createTexture(); // 创建纹理对象
      if (!texture) {
        console.log('Failed to create texture object');
        return error();
      }
      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);
      gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
      gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
      gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
      framebuffer.texture = texture; // 保存纹理对象
    
      //...
    }
    
  3. 创建渲染缓冲区对象(gl.createRenderbuffer())

    创建渲染缓冲区对象,这个渲染缓冲区对象将被指定为深度关联对象。

    function initFramebufferObject(gl) {
      //...
    
      // 创建渲染缓冲区对象并设置其尺寸和参数
      depthBuffer = gl.createRenderbuffer(); //创建渲染缓冲区
      if (!depthBuffer) {
        console.log('Failed to create renderbuffer object');
        return error();
      }
    
      //...
    }
    
  4. 绑定渲染缓冲区并设置尺寸(gl.bindRenderbuffer(),gl.renderbufferStorage())

    将渲染缓冲区绑定到目标上,通过目标设置渲染缓冲区的尺寸等参数。

    function initFramebufferObject(gl) {
      //...
    
      gl.bindRenderbuffer(gl.RENDERBUFFER, depthBuffer); // Bind the object to target
      gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, OFFSCREEN_WIDTH, OFFSCREEN_HEIGHT);
    
        //...
    }
    
  5. 将纹理对象关联到帧缓冲区对象(gl.bindFramebuffer(),gl.framebufferTexture2D)

  6. 将渲染缓冲区对象关联到帧缓冲区对象(gl.framebufferRenderbuffer())

  7. 检查帧缓冲区的配置(gl.checkFramebufferStatus())

  8. 在帧缓冲区进行绘制(gl.bindFramebuffer())