6 Framebuffers
文本统计:约 648 个字 • 39 行代码
我们正常的渲染过程是在默认渲染缓冲中先渲染,然后再与屏幕进行交换进而得到图像。我们也可以通过创建自己的帧缓冲,获得额外的渲染目标。然后一个帧缓冲可以包含颜色缓冲,深度缓冲,模板缓冲,至少包含一个。
创建一个附件可以有两个选项分别是纹理对象或者是渲染缓冲对象
纹理对象:当把一个纹理附加到帧缓冲的时候,所有的渲染指令将会写入到这个纹理中,就像它是一个普通的颜色/深度或模板缓冲一样。使用纹理的优点是,所有渲染操作的结果将会被储存在一个纹理图像中,我们之后可以在着色器中很方便地使用它。
这里相当于这个附件就是纹理,把它当作纹理来理解。
颜色附件使用纹理对象的例子会在后面的例子显示,深度附件与模板附件使用纹理对象的时候如下所示
glTexImage2D(
GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, 800, 600, 0,
GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, NULL
);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, texture, 0);
渲染缓冲对象:渲染缓冲对象直接将所有的渲染数据储存到它的缓冲中,不会做任何针对纹理格式的转换,让它变为一个更快的可写储存介质。然而,渲染缓冲对象通常都是只写的,所以你不能读取它们(比如使用纹理访问)。
所以一般情况下我们创建帧缓冲的时候,一般颜色附件用纹理对象,深度和模板附件用渲染缓冲对象(当然也不绝对)
以本次练习的代码为例,深入理解一下帧缓冲的作用
(1)创建帧缓冲
unsigned int framebuffer;
glGenFramebuffers(1, &framebuffer);
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
// 创建颜色附件(纹理附件)
unsigned int textureColorbuffer;
glGenTextures(1, &textureColorbuffer);
glBindTexture(GL_TEXTURE_2D, textureColorbuffer);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, SCR_WIDTH, SCR_HEIGHT, 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, SCR_WIDTH, SCR_HEIGHT);//用一个模板对象创建一个深度模板缓冲区对象
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rbo);
//检测帧缓冲是否正确
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
cout << "ERROR::FRAMEBUFFER:: Framebuffer is not complete!" << endl;
glBindFramebuffer(GL_FRAMEBUFFER, 0);
(2)设置帧缓冲为创建的帧缓冲,之后渲染的结果都在颜色附件上,即纹理 textureColorbuffer
(3)接着我们在处理默认缓冲的时候,就可以使用我们创建的那个缓冲所带的纹理对象来做了
// now bind back to default framebuffer and draw a quad plane with the attached framebuffer color texture
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glDisable(GL_DEPTH_TEST);
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
screenShader.use();
glBindVertexArray(quadVAO);
glBindTexture(GL_TEXTURE_2D, textureColorbuffer); // use the color attachment texture as the texture of the quad plane
//glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
glDrawArrays(GL_TRIANGLES, 0, 6);
总结一下,我们使用帧缓冲的作用在于可以将整个图像整体处理,比如说模糊之类的处理,当然这只是其中一个例子,使用帧缓冲达到了之前不能做到的效果。还有一个例子在练习中,做到后视镜的效果,只需要将相机旋转180度,得到帧缓冲的结果,然后贴图到相应的镜面上即可。