cocos2D-X源码分析之从cocos2D-X学习OpenGL(15)----帧缓冲

时间:2022-08-22 23:29:10

       cocos2d-x中提供一个叫RenderTexture的类,它可以保存屏幕到一张图片,也可以在begin到end之间实现自己的绘制,俨然就是一个独立于屏幕的画布(关于RenderTexture的介绍文章地址:http://blog.csdn.net/bill_man/article/details/7250911),这个类其实使用了openGL的帧缓冲技术,在调用任何openGL命令之前,首先需要创建一个渲染上下文和绘图表面并使之成为现行上下文和表面,由原生窗口系统提供的绘图表面可以是一个在屏幕上显示的表面,也可以是屏幕外的表面,这个“表面”就被称作帧缓冲区,默认情况下,直接使用屏幕的帧缓冲进行绘制,但是许多程序需要渲染到纹理,为此,使用窗口系统提供的帧缓冲区作为绘图表面就不是通常的选择了,这时候就需要使用屏幕外帧缓冲。

       帧缓冲对象是一组颜色,深度和模板纹理或者渲染目标。各种2D图像可以连接到帧缓冲对象中的颜色附着点。帧缓冲对象的创建必须满足如下条件,就是要至少有一个附件,至少有一个颜色附件,并且所有附件必须是完整的,每个缓冲要有相同数量的样本,当创建一个附件的时候我们可以选择单纯的使用纹理附件创建,或者使用渲染缓冲区。

       首先介绍如何创建一个帧缓冲

glGenFramebuffers(1, &_FBO);
glBindFramebuffer(GL_FRAMEBUFFER, _FBO);
        这种格式的代码相信我们已经轻车熟路,glGenFramebuffers分配n个帧缓冲区对象名称,然后调用glBindFramebuffer设置当前帧缓冲区对象,需要注意的是,对于在用glBindFramebuffer绑定缓冲区对象之前指定其名称来说,glGenFramebuffers并不是必须的。应用程序可以将未用的帧缓冲区对象名称指定给glBindFramebuffer。但是这样有可能出现错误,所以提前调用glGenFramebuffers是一种被推荐的做法
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, _texture->getName(), 0);
        然后就是需要为帧缓冲指定缓冲附件,这个函数有五个参数,第一个参数是我们所创建的帧缓冲类型的目标,GL_READ_FRAMEBUFFER为读取帧缓冲,GL_DRAW_FRAMEBUFFER为绘制帧缓冲,第二个参数为附件类型,可以是颜色附件,深度附件,模板附件和深度模板附件,第四个参数是纹理对象,第五个参数是纹理,第六个参数是mipmap级别。

       我们之前说了,还可以使用渲染缓冲对象附件,它的优势是,它以openGL的方式储存数据,因此在离屏渲染到帧缓冲时,这些数据已经被优化过了,因为格式已经是原生格式,所以把它写到其他缓冲中时非常快。

if (depthStencilFormat != 0){    //创建渲染缓冲区    glGenRenderbuffers(1, &_depthRenderBufffer);    glBindRenderbuffer(GL_RENDERBUFFER, _depthRenderBufffer);    glRenderbufferStorage(GL_RENDERBUFFER, depthStencilFormat, (GLsizei)powW, (GLsizei)powH);
    //加入深度缓冲附件
    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, _depthRenderBufffer);    //如果有模板缓冲附件,那么加入模板缓冲附件    if (depthStencilFormat == GL_DEPTH24_STENCIL8)    {        glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, _depthRenderBufffer);    }}
       在cocos2d-x中的RenderTexture类中,我们采用渲染缓冲对象作为模板缓冲和深度缓冲的附件,其中glGenRenderbuffers和glBindRenderbuffer和之前介绍的glGenFramebuffers以及glBindFramebuffer类似,一旦绑定渲染缓冲区对象,就可以指定保存渲染缓冲区中的图像大小和格式,glRenderbufferStorage就是完成这个工作的,除了不提供图像数据,glRenderbufferStorage和glTexImage2D类似,第一个参数是描述缓冲目标,第二个参数是格式,第三个参数是格式,可以使用颜色缓冲,深度缓冲和模板缓冲格式,后两个参数是缓冲区宽高,必须小于或等于GL_MAX_RENDERBUFFER_SIZE,创建了缓冲区后就可以添加附件了,使用glFramebufferRenderbuffer添加缓冲区附件,它类似于glFramebufferTexture2D,第一个参数设置缓冲目标,第二个参数设置附件形式,第三个参数必须为GL_RENDERBUFFER,第四个参数是0或者数据对象名称。

       关于两种帧缓冲方式的对比,如果对于渲染到纹理的用例,你应该将一个纹理对象链接到帧缓冲区的对象,当图像没有当做纹理使用时,你需要用渲染缓冲区,因为可以用更高效的格式存储渲染缓冲区,但是对于一般的情况下,更多的是组合使用二者,如同cocos2d-x中的RenderTexture一样,纹理使用纹理缓冲,深度缓冲和模板缓冲使用渲染缓冲区。

       下一篇开始介绍光照

       能力不足,水平有限,如有错误,欢迎指出。