帧缓冲
opengl 中默认会为我们创建一个帧缓冲,以后的颜色深度模板等信息会保存在里面。
一 什么是帧缓冲
以下摘抄自著名的wiki:
A framebuffer (frame buffer, or sometimes framestore) is a portion of random-access memory (RAM)[1] containing a bitmap that drives a video display. It is a memory buffer containing a complete frame of data.[2] Modern video cards contain framebuffer circuitry in their cores. This circuitry converts an in-memory bitmap into a video signal that can be displayed on a computer monitor。
所谓帧缓冲就是一个包含了位图能够驱动显卡显示的位于RAM中的一块内存区域。它包含了完整的帧数据。现代的显卡在其核心中包含帧缓冲电路。这个电路将内存位图转换成可以在计算机显示器上显示的视频信号
二 帧缓冲能做什么
通过创建帧缓冲我们可以自己创建需要的颜色显示,最主要的实现效果是后处理。后处理可以实现,hdr,bloom,模糊,镜头光晕,体积光等。
三 帧缓冲的使用方法
流程:
创建缓冲 ->创建附件(纹理、缓冲对象)->附加到帧缓冲上->执行着色渲染->切换缓冲区->绑定到另外一个帧缓冲区。
OpenGL实现:帧缓冲可以同时附加纹理附件和缓冲对象附件来处理颜色深度等信息代码如下:
GLuint NewframeBuffer;
glGenFramebuffers(1, &NewframeBuffer);
//绑定帧缓冲
glBindFramebuffer(GL_FRAMEBUFFER, NewframeBuffer);
//创建绑定到帧缓冲上的纹理附件
GLuint NewTextureColorBuffer;
//创建贴图
glGenTextures(1, &NewTextureColorBuffer);
//绑定纹理贴图
glBindTexture(GL_TEXTURE_2D, NewTextureColorBuffer);
//生成贴图的格式
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, NewTextureColorBuffer, 0);
//创建绑定到帧缓冲的缓冲渲染缓冲附件(包含深度和模板信息等)
GLuint newRbo;
glGenRenderbuffers(1, &newRbo);
//绑定渲染缓冲对象
glBindRenderbuffer(GL_RENDERBUFFER, newRbo);
//设置渲染对象的数据格式(深度值使用24位保存,模板值使用8位)
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, 800, 600);
//设置帧缓冲 (渲染对象)附件
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, newRbo);
帧缓冲附件形式有两种纹理附件和缓冲对象。
纹理附件
当把一个纹理附加到帧缓冲的时候,所有的渲染指令将会写入到这个纹理中。使用纹理的优点是,所有渲染操作的结果将会被储存在一个纹理图像中,我们之后可以在着色器中很方便地使用它。
缓冲对象
渲染缓冲对象(Renderbuffer Object)和纹理图像一样,即一系列的字节、整数、像素等。渲染缓冲对象附加的好处是,它会将数据储存为OpenGL原生的渲染格式,它是为离屏渲染到帧缓冲优化过的。渲染缓冲对象直接将所有的渲染数据储存到它的缓冲中,不会做任何针对纹理格式的转换,让它变为一个更快的可写储存介质。然而,渲染缓冲对象通常都是只写的,所以你不能读取它们(比如使用纹理访问)。当然你仍然还是能够使用glReadPixels来读取它,这会从当前绑定的帧缓冲,而不是附件本身,可以在每个渲染迭代最后使用的glfwSwapBuffers,也可以通过渲染缓冲对象实现:只需要写入一个渲染缓冲图像,并在最后交换到另外一个渲染缓冲就可以。
四 帧缓冲需要注意什么
想使用帧缓冲的信息:创建或者切换到另外一个帧缓冲然后把要使用的帧缓冲的附件绑定给当该缓冲就可以了, 比如上面代码中想使用NewTextureColorBuffer 可以用 glBindTexture(GL_TEXTURE_2D, NewTextureColorBuffer);