在非Qt库下使用帧缓存
在glad库下,帧缓存使用如下方式创建
// 帧缓存
// -------------------------
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, viewwidth, viewheight, 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, viewwidth, viewheight); // 创建为一个深度和模板附件渲染缓冲对象
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);
Qt下使用帧缓存
类QOpenGLFramebufferObject
构造函数
QOpenGLFramebufferObject( int width,
int height,
const QOpenGLFramebufferObjectFormat &format
)
QOpenGLFramebufferObject( const QSize &size,
const QOpenGLFramebufferObjectFormat &format
)
QOpenGLFramebufferObject( int width,
int height,
QOpenGLFramebufferObject::Attachment attachment,
GLenum target = GL_TEXTURE_2D,
GLenum internalFormat = 0
)
QOpenGLFramebufferObject( const QSize &size,
QOpenGLFramebufferObject::Attachment attachment,
GLenum target = GL_TEXTURE_2D,
GLenum internalFormat = 0
)
QOpenGLFramebufferObject( int width,
int height,
GLenum target = GL_TEXTURE_2D
)
QOpenGLFramebufferObject( const QSize &size,
GLenum target = GL_TEXTURE_2D
)
其中的参数:
width
、height
(或Qsize
) 帧缓存宽高QOpenGLFramebufferObjectFormat
:
framebuffer对象有以下几个特征:- 每像素的样本数。
void setSamples(int samples)
- 深度和/或模板附件。
void setAttachment (QOpenGLFramebufferObject::Attachment attachment)
- 结构的目标。
void setMipmap(bool enabled)
,void setTextureTarget(GLenum target)
- 内部结构格式。
void setInternalTextureFormat(GLenum internalTextureFormat)
- 每像素的样本数。
QOpenGLFramebufferObject::Attachment
QOpenGLFramebufferObject::NoAttachment
----------------0(default value)QOpenGLFramebufferObject::CombinedDepthStencil
-----1QOpenGLFramebufferObject::Depth
-------------------------2
GLenum target
= GL_TEXTURE_2D
默认情况下,QOpenGLFramebufferObject类生成一个2D OpenGL纹理(使用GL_TEXTURE_2D目标),它被用作内部渲染目标.GLenum internalFormat
= 0
默认的内部格式是桌面OpenGL
的GL_RGBA8
和OpenGL/ES
的GL_RGBA
使用
创建一个帧缓冲对象并添加一个深度缓存(默认创建一个颜色附件)
framebuffer=new QOpenGLFramebufferObject(size(),QOpenGLFramebufferObject::Depth);
或
framebuffer=new QOpenGLFramebufferObject(w,h,QOpenGLFramebufferObject::Depth);
等同于
// 帧缓存
// -------------------------
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, viewwidth, viewheight, 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, viewwidth, viewheight); // 创建为一个深度和模板附件渲染缓冲对象
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rbo); // 附加到帧缓冲的深度和模板附件上
glBindFramebuffer(GL_FRAMEBUFFER, 0);
绑定帧缓存,将图形生成到该缓冲上
framebuffer->bind();
等同于
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
在绑定期间,所有的Draw操作都会渲染到绑定的帧缓存上。
解绑
framebuffer->release();
等同于
glBindFramebuffer(GL_FRAMEBUFFER, 0);
解绑后渲染的图像会显示在屏幕上
获取帧缓存的纹理并输出到屏幕
framebuffer->texture()
返回该帧缓存0号纹理在GPU端的ID。
故通过
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D,framebuffer->texture()); // use the color attachment texture as the texture of the quad plane
screenShader.setUniformValue("screenTexture",0);
将纹理绑定到0号采样器,传入shader的sampler2D中。
注:
framebuffer可添加多个附加纹理void QOpenGLFramebufferObject::addColorAttachment(const QSize &size, GLenum internalFormat = 0)
创建并附加一个大小为宽度和高度的附加纹理或渲染缓冲区。
在GL_COLOR_ATTACHMENT0
处总是有一个附件。调用这个函数来设置附加附件在GL_COLOR_ATTACHMENT1
, GL_COLOR_ATTACHMENT2
,…
当internalFormat不为0时,它指定纹理或渲染缓冲区的内部格式。否则使用默认的GL_RGBA或GL_RGBA8。
若存在多个纹理,可通过QVector<GLuint> QOpenGLFramebufferObject::textures() const
返回所有附加纹理的纹理id。
如若想返回纹理的图像而不是id,使用
QImage fboImage(framebuffer.toImage());
QImage image(fboImage.constBits(), fboImage.width(), fboImage.height(), QImage::Format_ARGB32);
其他
当窗口大小发生改变时,帧缓存也要随之变化。
delete framebuffer;
framebuffer=new QOpenGLFramebufferObject(w,h,QOpenGLFramebufferObject::Depth);