问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501

求教opengl es2.0 中framebufferobject的一些生成机制

发布网友 发布时间:2022-04-23 20:25

我来回答

1个回答

热心网友 时间:2022-04-22 12:03

帧缓冲区对象呢又称为FBO,它允许我们把渲染从窗口的帧缓冲区转移到我们所创建的一个或者多个离屏帧缓冲区。被推荐用于数据渲染到纹理对象,相对于其他同类技术,如数据拷贝或者交换缓冲区等等,使用FBO技术会更高效且易于实现。此buffer包含了color buffer,depth buffer,stencil buffer.渲染到纹理这个技术在游戏中经常用来模拟电视机或者监视器等等的效果。

1.FBO并不受窗口大小的*。
2.纹理可以连接到FBO,允许直接渲染到纹理,不需要显示glCopyTexImage。
3.FBO可以包含许多颜色缓冲区,可以同时从一个片段着色器写入

FBO为OpenGL core API的一部分,使用它之前要检查GL_EXT_frmaebuffer_object扩展

FBO是一个图像容器,空的FBO容器里面存储的是texture(纹理)和renderbuffer(渲染缓冲区),纹理和渲染缓冲区都可以作为渲染的目标。一般使用的步骤:
设定好OpenGL基本环境 -> 建立FBO -> 启动FBO -> 对FBO绘图 -> 将FBO当成贴图 -> 启动原来的Frame Buffer -> 对Frame Buffer 画图 ->解除贴图的连接 -> 删除FBO

创建FBO:

生成一个对象,并取得一个有效的对象标识
GLuint fboname;
glGenFrameBuffersEXT(1,&fboname);

对FBO进行任何操作都需要首先绑定它:

把FBO与目标绑定,整型变量fboname用来保存FBO对象标识
glBindFrameBufferEXT(GL_FRAMEBUFFER_EXT,fboname);
要想关闭FBO,只要是fboname给0就可以:glBindFrameBufferEXT(GL_FRAMEBUFFER_EXT,0);即:除了创建新的FBO外,glBindFrameBufferEXT()也用于在FBO之间进行切换,绑定到名称0将会解除当前绑定的FBO,并把渲染重新定向到窗口的帧缓冲区。

加入一个深度缓存
一个FBO本身并没有多大用处,要想让他能被更有效的使用,我们需要把它与一些可被渲染的缓冲区绑定在一起,这样的缓冲区可以是纹理texture,也可以是渲染缓冲区renderbuffer,其实它就是一个用来支持离屏渲染的缓冲区,通常是帧缓冲区的一部分,一般不具有纹理格式,常见的模板缓冲和深度缓冲就是这样一类对象,我们要为FBO指定一个dephtbuffer:
GLuint dbname;
glGenRenderBuffersEXT(1,&dbname);

绑定该缓冲区,让它成为当前渲染缓冲:
glBindRenderBufferEXT(GL_RENDERBUFFER_EXT,dbname);

生成一个renderbuffer后,它本身并不会自动的分配内存空间,我们需要调用API来分配指定的内存空间:
glRenderBufferStorageEXT(GL_RENDERBUFFER_EXT,GL_DEPTH_COMPONENT,width,height);

这样就分配了一个w*h的深度缓冲区,这里使用了GL_DEPTH_COMPONENT,是指我们的空间用来保存深度值,除此之外还可以用来保存普通的GL_RGB/GL_RFBA格式的数据或者模板缓冲的信息。

接下来把这个深度缓存与准备好的FBO对象绑定在一起:
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT,GL_DEPTH_ATTACHMENT_EXT,GL_RENDERBUFFER_EXT,dbname);

一个FBO可以有多个不同的绑定点,这里是绑定在FBO的深度缓冲绑定点上,如GL_COLOR_ATTACHMENTi_EXT,GL_DEPTH_ATTACHMENT_EXT等等

加入用于渲染的纹理:
到现在为止,还没有办法往FBO写入颜色信息,有两种方法实现:
把一个颜色渲染缓冲与FBO绑定或者把一个纹理与FBO绑定,要想把纹理与FBO绑定,我们首先要生成这个纹理:
GLuint img;
glGenTexture(1,&img);
glBindTexture(GL_TEXTURE_2D,img);
glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA8,wight,height,0,GL_RGBA,GL_UNSIGEND_BYTE,NULL);
生成一个普通的RGBA图像,大小是w*h, 与前面生成的渲染缓冲区的大小是一样,FBO中要求所绑定的对象有相同的高度与宽度,这时候没有数据
生成纹理之后,把这个纹理与FBO绑定在一起,以便把数据渲染到纹理空间中去
glFramebufferTexture2Dext(GL_FRAMEBUFFER_EXT,GL_COLOR_ATTACHMENTO_EXT,GL_TEXTURE_2D,img,0);
参数GL_COLOR_ATTACHMENTO_EXT是告诉opengl把纹理对象绑定到FBO的0号绑定点,GL_TEXTURE_2D是纹理的格式,img是保存的纹理标识,指向之前就准备好的纹理对象,纹理可以使多重映射的图像,最后一个参数指定级为0,标识使用原图像
接下来测试FBO准备工作是否完,返回一个当前绑定FBO是否正确的状态信息,返回GL_FRAMEBUFFER_COMPLETE_EXT 就是指FBO准备好了 :
GLenum status=glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
渲染到纹理:
当我们要把数据渲染并输出到FBO时,我们就调用glBindFrameBufferEXT();当我们要停止输出FBO,把参数设置成0即可,当然,停止FBO输出很重要,我们完成FBO的工作就要停止FBO,让图像可以再屏幕上正确输出,
glBindFrameBufferEXT(GL_FRAMEBUFFER_EXT,fbname);
glPushAttrib(GL_VIEWPORT_BIT);
glViewPort(0,0,,wight,height);
//render as normal here
//output goes to the FBO and it's attached buffers
glPopAttrib();
glBindFrameBufferEXT(GL_FRAMEBUFFER_EXT,0);
面另外三行代码glPushAttrib/glPopAttrib 及 glViewport,是用来确保在你跳出FBO渲染的时候可以返回原正常的渲染路径。glViewport在这里的调用是十分必要的,我们不要常试把数据渲染到一个大于或小于FBO大小的区域。 函数glPushAtrrib 和 glPopAttrib 是用来快速保存视口信息。这一步也是必要的,因为FBO会共享主上下文的所有信息。任何的变动,都会同时影响到FBO及主上下文,当然也就会直接影响到你的正常屏幕渲染。
这里一个重要信息,你可能也注意到了,我们只是在绘制的时候绑定或解除FBO,但是我们没有重新绑定纹理或渲染缓冲区,这里因为在FBO中会一直保存了这种绑定关系,除非你要把它们分开或FBO对像被销毁了。

使用已渲染出来的纹理:

来到这里,我们已经把屏幕的数据渲染到了一个图像纹理上。现在我们来看一看如何来使用这张已经渲染好了的图像纹理。这个操作的本身其实是很简单的,我们只要把这张图像纹理当作普通纹理一样,绑定为当前纹理就可以了。
glBindTexture(GL_TEXTURE_2D, img);

以上这一函数调用完成之后,这张图像纹理就成了一个在绘图的时候用于被读取的普通纹理。
根据你在初始化时所指定的不同纹理滤波方式,你也许会希望为该纹理生成多重映像(mipmap)信息。如果要建立多重映像信息,多数的人都是在上传纹理数据的时候,通过调用函数gluBuild2DMipmaps()来实现,当然有些朋友可能会知道如何使用自动生成多重映像的扩展,但是在FBO扩展中,我们增加了第三种生成映像的方法,也就是使用GenerateMipmapEXT()函数。
这个函数的作用就是让OpenGL帮你自动创建多重映像信息。中间实现的过程,根据不同的显卡会有所不同,我们只关心它们最终的结果是一样就行了。值得注意的是:对于这种通过FBO渲染出来的纹理,要实现多重映像的话,只有这一种方法是正确的,这里你不可以使用自动生成函数来生成多重映像,这其中的原因有很多,如果你想深入了解的话,可以查看一下技术文档。
使用这一函数使方便,你所要做的就是先把该纹理对像绑定为当前纹理,然后调用一次该函数就可以了。
glGenerateMipmapEXT(GL_TEXTURE_2D);

OpenGL将会自动为我们生成所需要的全部信息,到现在我们的纹理便可以正常使用了。
一个重点要注意的地方:如果你打算使用多重映像(如 GL_LINEAR_MIPMAP_LINEAR),该函数glGenerateMipmapEXT()必须要在执行渲染到纹理之前调用。
在创建纹理的时候,我们可以按以下代码来做。
glGenTextures(1, &img);
glBindTexture(GL_TEXTURE_2D, img);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glGenerateMipmapEXT(GL_TEXTURE_2D);

到现在,这张纹理和普通纹理没什么区别,我们就按处理普通纹理的方法来使用就可以了。

删除FBO:
glDeleteFrameBufferEXT(1,&fboname);

同样的,你如果分配了渲染缓冲对像,也别忘了要把它清理掉。本实例中我们分配的是深度缓存渲染对像,我们用以下函数来清除它:
glDeleteRenderbuffersEXT(1, &depthbuffer);
声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com
联想Z470AM I5处理器与I3 联想ideapad z470 独显默认设置是什么 联想Z470 I5处理器 GT520M的显卡跟普通的GT520M显卡有什么区别 性能怎 ... 我新买了一台联想z470 i3-2310 但是朋友说显卡不太好!! 我玩天龙八部... 联想的z470笔记本 上面 的独显GT520M 能不能 更换 或者是升级阿? ...我的是双显卡的 z470- i5 显卡是 gt520m 能换吗 vivo手机耳机麦克风说话声音小 耳机通话声音小是怎么回事 为什么我手机耳机的麦克风声音很小怎么调 求:7个字的情侣游戏名,纯汉字,有诗意的(不要古诗)。不带任何符号或英文... FrameBuffer,xlib,opengl,gtk,qt,sdl之间的关系是怎样的 android上如何在应用程序里使用opengl截取framebuffer的内容? opengl后处理为什么需要两个framebuffer 手机不可以掉到马桶里弄湿(猜4字成语)? 手机掉到马桶里怎么办? 手机不可以掉到马桶里成语是什么? 手机不可以掉到马桶里歇后语是什么 歇后语:1 手机不可以掉到马桶里()2蜜蜂停在日历上()3老鼠给大象指路()4下雨天出日头()5无头苍蝇 手机掉到马桶里面应该怎么处理 手机掉马桶里,是捡还是不捡 企业级高清云视频会议解决方案如何选择? 手机掉进厕所里还能不能用?怎么处理? 手机掉进马桶 视频会议系统设计方案 大年三十手机掉马桶里有什么不好的寓意吗? 手机为什么不能丢到马桶里去 手机为什么不能丢到马桶里面去? 手机为什么不能丢到马桶里面去 脑筋急转弯,手机为什么不可以丢到马桶里去 一般设计标准视频会议系统技术方案主要考虑哪些因素啊? 运行游戏显示OpenGL framebuffer object support is missing.... 为openGL的选择缓冲区分配内存时要考虑什么因素? No OpenGL framebuffer support. Please upgrade the driver of your video card.是什么意思? opengl如何渲染到内存 求帮助解决OpenGL显示抗锯齿问题 请教关于opengl中FBO离屏渲染的使用 怎样opengl es渲染到纹理 Opengl怎么设置多个相机,并且从不同的相机的角度获得目标物体的图像 qt5.4 都添加了什么? 如何在Android上使用OpenGL ES 2.0绘制点 android opengl es与surfaceview什么关系 如何读取在OpenGL中绘制的超大像素的图像数据? Windows 支持 DirectX 和 OpenGL,为什么大多数 PC 游戏还是 201 C++语言,Opengl 中,为什么glClearColor不能让屏幕变色。 暴龙太阳镜和aoJo哪个好? 分手时,怎么样判断是真性分手还是假性分手? 暴龙眼镜和L0HO眼镜比起来哪个更好? 男朋友假分手,还想要复合会有哪些表现? 买开车用的眼镜,哪个牌子好? 假性分手和真性分手的区别是什么?