湖北网站建设优化,怎么做qq代挂网站,莱芜都市网二手房,成都网站建设排行榜QT之OpenGL帧缓冲1. 概述1.1 帧缓冲的创建与删除1.2 帧缓冲的数据来源1.2.1 数据源与帧缓冲的关系1.2.2 纹理Attachment1.2.3 渲染缓冲对象Attachment1.2.4 两者的区别1.2.5 关于两者的使用场景2. Demo3. 后期处理4. 参考1. 概述
OpenGL管线的最终渲染目的地被称作帧缓冲(fram…
QT之OpenGL帧缓冲1. 概述1.1 帧缓冲的创建与删除1.2 帧缓冲的数据来源1.2.1 数据源与帧缓冲的关系1.2.2 纹理Attachment1.2.3 渲染缓冲对象Attachment1.2.4 两者的区别1.2.5 关于两者的使用场景2. Demo3. 后期处理4. 参考1. 概述
OpenGL管线的最终渲染目的地被称作帧缓冲(framebuffer)它由用于写入颜色值的颜色缓冲、用于写入深度信息的深度缓冲和允许根据一些条件丢弃特定片段的模板缓冲组合而成它被储存在内存中。
1.1 帧缓冲的创建与删除 创建 unsigned int fbo;
/*
第一个是要创建的帧缓存的数目
第二个是指向存储一个或者多个ID的变量或数组的指针
默认帧缓冲的id是0
*/
glGenFramebuffers(1, fbo);绑定激活 /*
GL_READ_FRAMEBUFFER : 绑定到GL_READ_FRAMEBUFFER的帧缓冲将会使用在所有像是glReadPixels的读取操作中
GL_DRAW_FRAMEBUFFER : 而绑定到GL_DRAW_FRAMEBUFFER的帧缓冲将会被用作渲染、清除等写入操作的目标
GL_FRAMEBUFFER : 通常都会使用GL_FRAMEBUFFER绑定到两个上
*/
glBindFramebuffer(GL_FRAMEBUFFER, fbo);删除 glDeleteFramebuffers(1, fbo);OpenGL允许自定义帧缓冲一个完整帧缓冲需要满足以下条件 附加至少一个缓冲(颜色、深度或模板缓冲)至少有一个颜色attachment所有的attachment都必须是完整的(保存在内存)每个缓冲都应有相同的样本数 完整性检查 if(glCheckFramebufferStatus(GL_FRAMEBUFFER) GL_FRAMEBUFFER_COMPLETE)1.2 帧缓冲的数据来源 1.2.1 数据源与帧缓冲的关系 只是用纹理Attachment 只是用渲染缓冲对象Attachment 纹理Attachment与渲染缓冲对象Attachment结合使用
注
GL_COLOR_ATTACHMENT的数量可以通过GL_MAX_COLOR_ATTACHMENTS获取一个帧缓冲至少要有一个颜色缓冲Attachment这里的Attachment仅仅是一个附着点并不是将数据拷贝到FBO中FBO提供了一种高效的切换机制将前面帧缓冲关联的图形从FBO分离然后把心的帧缓冲图像关联到FBO。在帧缓冲关联图像之间切换比在FBO之间切换要快的多。 切换函数如下// 切换纹理图像
glFramebufferTexture2D();
// 切换渲染缓冲区
glFramebufferRenderbuffer();1.2.2 纹理Attachment 把一个纹理附加附加到缓冲区的时候所有的渲染指令都将会写入到这个纹理中就像他是一个普通的颜色/深度或模板缓冲一样。使用纹理的优点是所有渲染操作的结果将会被存储在一个纹理图像中可以很方便的在着色器中只是用。 纹理创建unsigned int texture;
glGenTextures(1, texture);
glBindTexture(GL_TEXTURE_2D, texture);/*
这里的data部分设置为NULL表示仅仅分配了内存而没有进行数据填充。纹理的填充会在渲染到帧缓冲之后进行如果想将屏幕渲染到一个更小或更大的纹理上需要在渲染到帧缓冲之前再次调用glViewport使用纹理的新维度作为参数否则只有一小部分的纹理或屏幕会被渲染到这个纹理上
*/
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);附加到帧缓冲/*
target帧缓冲的目标绘制、读取或者两者皆有
attachment我们想要附加的附件类型。当前我们正在附加一个颜色附件。注意最后的0意味着我们可以附加多个颜色附件。我们将在之后的教程中提到。
textarget你希望附加的纹理类型
texture要附加的纹理本身
level多级渐远纹理的级别。我们将它保留为0。
*/
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
/*除了颜色附件之外还可以附加一个深度和模板缓冲纹理到帧缓冲对象中。要附加深度缓冲需要将附件类型设置为GL_DEPTH_ATTACHMENT。注意纹理的格式(Format)和内部格式(Internalformat)类型将变为GL_DEPTH_COMPONENT来反映深度缓冲的储存格式。要附加模板缓冲的话需要将第二个参数设置为GL_STENCIL_ATTACHMENT并将纹理的格式设定为GL_STENCIL_INDEX。也可以将深度缓冲和模板缓冲附加为一个单独的纹理。纹理的每32位数值将包含24位的深度信息和8位的模板信息。要将深度和模板缓冲附加为一个纹理的话我们使用GL_DEPTH_STENCIL_ATTACHMENT类型并配置纹理的格式让它包含合并的深度和模板值。将一个深度和模板缓冲附加为一个纹理到帧缓冲的例子如下所示
*/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.2.3 渲染缓冲对象Attachment
渲染缓冲对象(Renderbuffer Object)是在纹理之后引入OpenGL的它也是一个真正的缓冲它会将数据存储为OpenGL原生的渲染格式它是为了离屏渲染到帧缓冲优化过的。
创建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);注: 因为它的数据已经是原生的格式了当写入或者复制它的数据到其它缓冲中时是非常快的。所以交换缓冲这样的操作在使用渲染缓冲对象时会非常快。我们在每个渲染迭代最后使用的glfwSwapBuffers也可以通过渲染缓冲对象实现只需要写入一个渲染缓冲图像并在最后交换到另外一个渲染缓冲就可以了。渲染缓冲对象对这种操作非常完美。
1.2.4 两者的区别
纹理是可读可写的而渲染缓冲对象则是只写的但可以使用glReadPixels来读取它(从当前绑定的帧缓冲而不是Attachment本身中返回特定区域的像素)
1.2.5 关于两者的使用场景
如果不需要从一个缓冲中采样此时使用渲染缓冲对象更好些如果需要从一个缓冲中进行采样颜色或深度值等数据此时使用纹理Attachment更合理两者在性能方面不会差别非常大
2. Demo
将场景渲染到一个小窗口中源码链接
3. 后期处理
Demo效果展示如下: 反相(Inversion) 灰度(Grayscale) 加权(Weighted) 核(kernel) 在一个纹理图像上做后期处理的另外一个好处是我们可以从纹理的其它地方采样颜色值。比如说我们可以在当前纹理坐标的周围取一小块区域对当前纹理值周围的多个纹理值进行采样。 核(Kernel)或卷积矩阵(Convolution Matrix)是一个类矩阵的数值数组它的中心为当前的像素它会用它的核值乘以周围的像素值并将结果相加变成一个值。 锐化(Sharpen) 模糊(Blur) 边缘检测(Edge-detection)
4. 参考 OpenGL Learn http://www.songho.ca/opengl/gl_fbo.html http://www.songho.ca/opengl/gl_fbo.html的翻译版 FBO使用示例 单独使用 渲染缓冲对象示例