OpenGL帧缓存

简述

一般在OpenGL环境搭建过程中,窗口系统会创建一个默认的帧缓存,这个帧缓存是唯一可以被图形服务器的显示系统所识别的帧缓存,所以应用程序自定义的帧缓存只能用于离屏渲染的场合。帧缓存不会直接存储渲染数据,必须将渲染的结果保存到一些附件中(颜色,深度和模板)。窗口系统的帧缓存在创建之初就有自己的缓存附件,自定义的帧缓存对象还需要手动添加这些附件。

帧缓存的内存模型如下:

红色区域就是实际存储数据的内存空间。

 

纹理对象

纹理附加到帧缓冲的时候,所有的渲染指令将会写入到这个纹理中,就想它是一个普通的颜色缓冲一样。使用纹理的优点是,所有渲染操作的结果将会被储存在一个纹理图像中,我们之后可以在着色器中很方便地使用它。

 

渲染缓存对象

渲染缓存是OpenGL所管理的一处高效的内存区域,它可以存储格式化的数据。渲染缓存中的数据只有关联到一个帧缓存对象之后才有意义。由于渲染缓冲对象通常都是只写的,它们会经常用于深度和模板附件,因为大部分时间我们都不需要从深度和模板缓冲中读取值,只关心深度和模板测试。我们需要深度和模板值用于测试,但不需要对它们进行采样,所以渲染缓冲对象非常适合它们。

 

帧缓存的完整性

纹理和缓存的格式组合是多样的,而且不同的帧缓存附件设置都可能导致帧缓存对象无法正常渲染。因此当创建好帧缓存及其附件后,对其进行一次检测,查看是否成功创建。

 

帧缓存的无效化

帧缓存会占用相当的系统资源,所以使用完成后需要释放,OpenGL中可以将帧缓冲的一块区域或整体声明为不在使用,并且可以立即释放可以通过函数gllnvalidateSubFramebuffer()和gllnvalidateFramebuffer()完成。

 

构建帧缓存的步骤

1,创建帧缓存对象,绑定帧缓存对象

glGenFramebuffers()

glBindFramebuffer()

2,创建纹理附件

glGenTextures()

glBindTexture()

3,把纹理附件附加到帧缓冲上

glFramebufferTexture2D()

 

4,创建一个用于深度和模板附件的渲染缓冲对象并绑定

glGenRenderbuffers()

glBindRenderbuffer()

5,创建一个深度和模板渲染缓冲对象,并给渲染缓冲对象分配空间

glRenderbufferStorage()

6,把模板和深度缓冲对象附加在这个渲染缓冲对象:

glFramebufferRenderbuffer()

7,判断是否创建成功

glCheckFramebufferStatus()

 

帧缓存实现流程

部分代码

//----------------------构建帧缓存----------------------
	glGenFramebuffers(1, &framebuffer);
	//绑定到帧缓存,之后所有的读取和写入帧缓冲的操作将会影响当前绑定的帧缓冲
	glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);

	//创建颜色附件
	glGenTextures(1, &textureColorbuffer);
	glBindTexture(GL_TEXTURE_2D, textureColorbuffer);
	//对于这个纹理,我们仅仅分配了内存而没有填充它
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 800, 600, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
	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, textureColorbuffer, 0);


	//创建一个用于深度和模板附件的渲染缓冲对象
	unsigned int rbo;
	glGenRenderbuffers(1, &rbo);
	//绑定渲染缓冲对象
	glBindRenderbuffer(GL_RENDERBUFFER, rbo);
	//创建一个深度和模板渲染缓冲对象,并给渲染缓冲对象分配空间
	glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, 800, 600);
	//把模板和深度缓冲对象附加在这个渲染缓冲对象:
	glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rbo);

	//判断检查帧缓冲是否完整,如果完整,则返回GL_FRAMEBUFFER_COMPLETE
	if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
	{
		cout << "ERROR::FRAMEBUFFER:: Framebuffer is not complete!" << endl;
	}
	//解除纹理绑定
	glBindTexture(GL_TEXTURE_2D, 0);
	//解除渲染缓冲绑定
	glBindRenderbuffer(GL_RENDERBUFFER, 0);
	//解除帧缓冲绑定
	glBindFramebuffer(GL_FRAMEBUFFER, 0);


参见:《OpenGL编程指南》第八版第3章

            learnOpengl教程


  • 4
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值