创建一个帧缓冲
unsigned int fbo;
glGenFramebuffers(1, &fbo);
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
完整的帧缓冲组成
- 附加至少一个缓冲(颜色、深度或模板缓冲)。
- 至少有一个颜色附件(Attachment)。
- 所有的附件都必须是完整的(保留了内存)。
- 每个缓冲都应该有相同的样本数。
检查帧缓冲是否完整
if(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE)
激活默认帧缓冲
glBindFramebuffer(GL_FRAMEBUFFER, 0);
删除帧缓冲对象
glDeleteFramebuffers(1, &fbo);
纹理附件
- 创建一个纹理
unsigned int texture;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
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, texture, 0);
glFrameBufferTexture2D有以下的参数:
target:帧缓冲的目标(绘制、读取或者两者皆有)
attachment:我们想要附加的附件类型。当前我们正在附加一个颜色附件。注意最后的0意味着我们可以附加多个颜色附件。我们将在之后的教程中提到。
textarget:你希望附加的纹理类型
texture:要附加的纹理本身
level:多级渐远纹理的级别。我们将它保留为0。
- 附加深度缓冲,附件类型设为
GL_DEPTH_ATTACHMENT
。纹理格式和内部格式类型设为为GL_DEPTH_COMPONENT
。 - 附加模板缓冲,附件类型设为
GL_STENCIL_ATTACHMENT
,纹理格式设为GL_STENCIL_INDEX
。 - 附加深度模板缓冲,类型设为
GL_DEPTH_STENCIL_ATTACHMEN
。纹理的每32位数值将包含24位的深度信息和8位的模板信息
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);
渲染缓冲对象附件
渲染缓冲对象直接将所有的渲染数据储存到它的缓冲中,不会做任何纹理格式的转换,是一个更快的可写储存介质。
渲染缓冲对象通常是只写的,常用于深度和模板附件,因为我们不需要从深度和模板缓冲中读取值,只关心深度和模板测试。
- 创建一个渲染缓冲对象
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);
如果你不需要从一个缓冲中采样数据,那么使用渲染缓冲对象;
如果你需要从缓冲中采样颜色或深度值等数据,那么选择纹理附件。
渲染到纹理
将场景渲染到一个附加到帧缓冲对象上的颜色纹理中,之后在一个横跨整个屏幕的四边形上绘制这个纹理。
绘制流程为:
1.将新的帧缓冲绑定为激活的帧缓冲,和往常一样渲染场景
2.绑定默认的帧缓冲
3.绘制一个横跨整个屏幕的四边形,将帧缓冲的颜色缓冲作为它的纹理。
//创建并绑定帧缓冲对象
unsigned int framebuffer;
glGenFramebuffers(1, &framebuffer);
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
//创建纹理图像,作为颜色附件附加到帧缓冲上
unsigned int texColorBuffer;
glGenTextures(1, &texColorBuffer);
glBindTexture(GL_TEXTURE_2D, texColorBuffer);
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);
glBindTexture(GL_TEXTURE_2D, 0);
//附加到当前绑定的帧缓冲对象
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texColorBuffer, 0);
//使用渲染缓冲对象添加一个深度模板附件到帧缓冲中。
unsigned int rbo;
glGenRenderbuffers(1, &rbo);
glBindRenderbuffer(GL_RENDERBUFFER, rbo);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, 800, 600);
glBindRenderbuffer(GL_RENDERBUFFER, 0);
//将渲染缓冲对象附加到帧缓冲的深度模板附件
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rbo);
//检查帧缓冲是否是完整
if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
std::cout << "ERROR::FRAMEBUFFER:: Framebuffer is not complete!" << std::endl;
glBindFramebuffer(GL_FRAMEBUFFER, 0);
image.png
后期处理
整个场景都被渲染到了一个纹理上,可以通过修改纹理数据创建出各种效果。例如 反相、灰度、 核效果、模糊、 边缘检测等。
网友评论