QT With OpenGL(帧缓存篇)

在非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
						)

其中的参数:

  • widthheight(或Qsize) 帧缓存宽高
  • QOpenGLFramebufferObjectFormat :
    framebuffer对象有以下几个特征:
    1. 每像素的样本数。 void setSamples(int samples)
    2. 深度和/或模板附件。 void setAttachment (QOpenGLFramebufferObject::Attachment attachment)
    3. 结构的目标。 void setMipmap(bool enabled), void setTextureTarget(GLenum target)
    4. 内部结构格式。 void setInternalTextureFormat(GLenum internalTextureFormat)
  • QOpenGLFramebufferObject::Attachment
    1. QOpenGLFramebufferObject::NoAttachment----------------0(default value)
    2. QOpenGLFramebufferObject::CombinedDepthStencil-----1
    3. QOpenGLFramebufferObject::Depth-------------------------2
  • GLenum target= GL_TEXTURE_2D
    默认情况下,QOpenGLFramebufferObject类生成一个2D OpenGL纹理(使用GL_TEXTURE_2D目标),它被用作内部渲染目标.
  • GLenum internalFormat = 0
    默认的内部格式是桌面OpenGLGL_RGBA8OpenGL/ESGL_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);
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Elsa的迷弟

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值