帧缓冲(FrameBuffer)小记

  1. 什么是帧缓冲?
    帧缓冲是颜色缓冲、深度缓冲、模板缓冲的结合,存储于内存中;其中,颜色缓冲用于写入颜色值,深度缓冲用于写入深度信息,模板缓冲用于基于一些条件丢弃指定片段。
  2. 帧缓冲的创建与使用
    首先需要创建一个帧缓冲对象,并将其绑定到当前帧缓冲中;
    在绑定后,所有的读/写帧缓冲的操作都会影响当前绑定的帧缓冲;
    如GL_READ_FRAMEBUFFER: 可执行读取操作;
    GL_DRAW_FRAMEBUFFER: 可执行写入操作;
    gl_ReadPixels在绑定到GL_DRAW_FRAMEBUFFER上时可以进行渲染、清空和其他写入操作;
    为帧缓冲添加至少一个附件(attachment)(颜色、深度、模板缓冲)且其中至少一个附件是颜色附件;附件应当是已经做好的(已经存储在内存中);每个缓冲都应该有同样数目的样本;
    使用glCheckFramebufferStatus检查是否成功;
    由于我们的帧缓冲不是默认的帧缓冲,渲染命令对窗口的视频输出不会产生任何影响。出于这个原因,它被称为离屏渲染(off-screen rendering),就是渲染到一个另外的缓冲中。为了让所有的渲染操作对主窗口产生影响我们必须通过绑定为0来使默认帧缓冲被激活;
    做完所有帧缓冲操作,不要忘记删除帧缓冲对象;
GLuint fbo; //创建一个帧缓冲对象
glGenFrameBuffers(1,&fbo);  //创建帧缓冲
glBindFrameBuffer(GL_FRAMEBUFFER,fbo); //绑定到当前帧缓冲
glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo); //读
//glBindFramebuffer(GL_DRAW_FRAMEBUFFER,fbo); //写
glReadBuffer(GL_COLOR_ATTACHMENT0); //读取颜色附件
if(glCheckFramebufferStatus(GL_FRAMEBUFFER)==GL_FRAMEBUFFER_COMPLETE)
{
	return true;
}
glBindFrameBuffer(GL_FRAMEBUFFER,0);//绑定到主窗口
glDeleteFramebuffers(1,&fbo);//删除帧缓冲对象

  1. 纹理
    在执行完成检测前,我们需要把一个或更多的附件附加到帧缓冲上。一个附件就是一个内存地址,这个内存地址里面包含一个为帧缓冲准备的缓冲,它可以是个图像。当创建一个附件的时候我们有两种方式可以采用:纹理或渲染缓冲(renderbuffer)对象。
    当把一个纹理附加到帧缓冲上的时候,所有渲染命令会写入到纹理上,就像它是一个普通的颜色/深度或者模板缓冲一样。使用纹理的好处是,所有渲染操作的结果都会被储存为一个纹理图像,这样我们就可以简单的在着色器中使用了。
    创建一个帧缓冲的纹理和创建普通纹理差不多:我们只分配内存,而不去填充它。纹理填充会在渲染到帧缓冲的时候去做。
    如果打算把整个屏幕渲染到一个或大或小的纹理上,你需要用新的纹理的尺寸作为参数再次调用glViewport要在渲染到你的帧缓冲之前做好),否则只有一小部分纹理或屏幕能够绘制到纹理上。现在我们已经创建了一个纹理,最后一件要做的事情是把它附加到帧缓冲上:
GLuint texture;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 800, 600, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL); //将纹理的维度设置为屏幕的大小,且传递了NULL作为纹理的data参数
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,GL_TEXTURE_2D, texture, 0);//将纹理绑定到FrameBuffer上
  1. glReadPixels函数
    GPU渲染完数据在显存,回传内存的唯一方式。
    共有七个参数:
    前四个可以得到一个矩形区域,该区域所包含的所有像素都会被读取出来;
    x,y :指定从帧缓冲区读取的第一个像素的窗口坐标。 此位置是矩形像素块的左下角;
    width, height: 指定像素矩形的尺寸。 一个宽度和高度对应于单个像素;
    format: 指定像素数据的格式。 接受以下符号值:GL_ALPHA,GL_RGB和GL_RGBA; 例如:GL_RGB就会依次读取像素的红、绿、蓝三种数据,GL_RGBA则会依次读取像素的红、绿、蓝、alpha四种数据,GL_RED则只读取像素的红色数据(类似的还有GL_GREEN,GL_BLUE,以及GL_ALPHA)。如果采用的不是RGBA颜色模式,而是采用颜色索引模式,则也可以使用GL_COLOR_INDEX来读取像素的颜色索引。除了颜色之外,还可以读取其它内容,例如深度缓冲区的深度数据等;
    type: 指定像素数据的数据类型。 必须是GL_UNSIGNED_BYTE,GL_UNSIGNED_SHORT_5_6_5,GL_UNSIGNED_SHORT_4_4_4_4或GL_UNSIGNED_SHORT_5_5_5_1之一;
    data: 返回像素数据,像素数据被读取后,将被保存到这个指针所表示的地址。
    注意:glReadPixels实际上是从缓冲区中读取数据,如果使用了双缓冲区,则默认是从正在显示的缓冲(即前缓冲)中读取,而绘制工作是默认绘制到后缓冲区的。因此,如果需要读取已经绘制好的像素,往往需要先交换前后缓冲。
void WINAPI glReadPixels(
   GLint   x,
   GLint   y,
   GLsizei width,
   GLsizei height,
   GLenum  format,
   GLenum  type,
   GLvoid  *pixels
);
  1. glBlitFramebuffer函数
    帧缓冲区位块传送(Blit)也是 OpenGL ES 3.0 的新特性,主要用于帧缓冲区之间的像素拷贝,性能高且使用方便,可以指定缓冲区任意矩形区域的像素拷贝。
    进行帧缓冲区间位块传之前,需要指定好源帧缓冲区 GL_READ_FRAMEBUFFER 和目标帧缓冲区 GL_DRAW_FRAMEBUFFER;
glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo1); 
glBindFramebuffer(GL_DRAW_FRAMEBUFFER,fbo2); 
glReadBUffer(GL_COLOR_ATTACHMENT0);
glDrawBuffer(GL_COLOR_ATTACHMENT0);
glClearColor(0.0f,0.0f,0.0f,1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glBlitFrameBuffer(0,0,RenderImage.width, RenderImage.height,0, 0, m_SurfaceWidth, m_SurfaceHeight, GL_COLOR_BUFFER_BIT, GL_LINEAR);
//将RenderImage.width*height的像素拷贝至SurfaceWidth*Height上;

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值