当前位置: 首页 > news >正文

learnopengl——Framebuffers

原文网址:https://learnopengl.com/Advanced-OpenGL/Framebuffers

framebuffers
so far we have used several types of screen buffers: a color buffer for writing color values, a depth buffer to write depth information and finally a stencil buffer that allows us to discard certain fragments based on some condition. the combination of these buffers is called a framebuffer and is stored somewhere in memory. opengl gives us the flexibility to define our own framebuffers and thus define our own color and optionally a depth and stencil buffer.

the rendering operations we have done so far were all done on top of the render buffers attached to the default framebuffer. the default framebuffer is created and configured when u create your window (GLFW does this for us). by creating our own framebuffer we can get an additional means to render to.

the application of framebuffers might not immediately make sense, but rendering your scene to a different framebuffer allows us to create mirrors in a scene or do cool post-processing effects for example. first we will discuss how they actually work and then we will use them by implementing those cool post-processing effects.

creating a framebuffer
just like any other object in opengl we can create a framebuffer object (abbreviated to FBO) by using a function called glGenFramebuffers:

unsigned int fbo;
glGenFramebuffers(1, &fbo);

this pattern of object creating and usage is sth. we have seen dozens of times now so their usage functions are similar to all the other object’s we have seen; first we create a framebuffer object, bind it as the active framebuffer, do some operations and unbind the framebuffer. to bind the framebuffer we use glBindFramebuffer:

glBindFramebuffer(GL_FRAMEBUFFER, fbo);  

by binding to the GL_FRAMEBUFFER target all the next read and write framebuffer operations will affect the currently bound framebuffer. it is also possible to bind a framebuffer to a read or write target specifically by binding to GL_READ_FRAMEBUFFER or GL_DRAW_FRAMEBUFFER respectively. the framebuffer bound to GL_READ_FRAMEBUFFER is then used for all read operations like glReadPixels and the framebuffer bound to GL_DRAW_FRAMEBUFFER is used as the destination for rendering, clearing and other write operations. most of the times u will not need to make this distinction though and u generally bind to both with GL_FRAMEBUFFER.

unfortunately, we can not use our framebuffer yet because it is not complete. for a framebuffer to be complete the following requirements have to be satisfied:

  1. we have to attach at least one buffer (color, depth or stencil buffer).
  2. there should be at least one color attachment.
  3. all attachments should be complete as well (reserved memory).
  4. each buffer should have the same number of samples.

do not worry if u do not know what samples are, we will get to those in a later tutorial.

from the requirements it should be clear that we need to create some kind of attachment for the framebuffer and attach this attachment to the framebuffer. after we have completed all requirements we can check if we actually successfully completed the framebuffer by calling glCheckFramebufferStatus with GL_FRAMEBUFFER. it then checks the currently bound framebuffer and returns any of these values found in the specification. if it returns GL_FRAMEBUFFER_COMPLETE we are good to go:

if(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE)
  // execute victory dance

all subsequent rendering operations will now render to the attachments of the currently bound frambuffer. since our framebuffer is not the default framebuffer, the rendering commands will have no impact on the visual output of your window. for this reason it is called off-screen rendering while rendering to a different framebuffer. to make sure all rendering operations will have a visual impact on the main window we need to make the default framebuffer active by binding to 0:

glBindFramebuffer(GL_FRAMEBUFFER, 0);  

when we are done with all framebuffer operations, do no forget to delete the framebuffer object:

glDeleteFramebuffers(1, &fbo);  

now before the completeness check is executed we need to attach one or more attachments to the framebuffer. an attachment is a memory location that can act as a buffer for the framebuffer, think of it as an image. when creating an attachment we have two options to take: textures or renderbuffer objects.

texture attachments
when attaching a texture to a framebuffer, all rendering commands will write to the texture as if it was a normal color/depth or stencil buffer. the advantage of using textures is that the result of all rendering operations will be stored as a texture image that we can then easily use in our shaders.

creating a texture for a framebuffer is roughly the same as a normal texture:

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); 

the main differences here is that we set the dimensions equal to the screen size (although this is not required) and we pass NULL as the texture’s data parameter. for this texture, we are only allocating memory and not actually filling it. filling the texture will happen as soon as we render to the framebuffer. also note that we do not care about any of the wrapping methods or mipmapping since we will not needing those in most cases.

if u want to render your whole screen to a texture of a smaller or larger size u need to call glViewport again (before rendering to your framebuffer) with the new dimensions of your texture, otherwise only a small part of the texture or screen would be drawn onto the texture. 

now that we have created a texture that last thing we need to do is actually attach it to the framebuffer.

glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0); 

The glFrameBufferTexture2D has the following parameters:

  1. target: the framebuffer type we are targeting (draw, read or both).
  2. attachment: the type of attachment we are going to attach. right now we are attaching a color attachment. note that the 0 at the end suggests we can attach more than 1 color attachment. we will get to that in a later tutorial.
  3. textarget: the type of the texture u want to attach.
  4. texture: the actual texture to attach.
  5. level: the mipmap level. we keep this at 0.

相关文章:

  • learnopengl——纹理
  • [转帖]Application Request Route实现IIS Server Farms集群负载详解
  • learnopengl——三角形
  • songho——OpenGL的帧缓冲
  • while 循环 及 and or not
  • songho——OpenGL的顶点缓冲对象
  • OGL(教程35)——延迟渲染1——代码结构梳理
  • 安装MySQL_安装Navicat_启动数据库服务
  • android studio查看android手机日志
  • Python02(Linux命令)
  • luaforwindws安装与调用方式
  • vs添加链接文件
  • httpclient
  • 继成ScriptableObject的静态类对象竟然没有销毁
  • 国内镜像站
  • 《剑指offer》分解让复杂问题更简单
  • Django 博客开发教程 8 - 博客文章详情页
  • IndexedDB
  • javascript数组去重/查找/插入/删除
  • PhantomJS 安装
  • Python打包系统简单入门
  • React as a UI Runtime(五、列表)
  • 阿里中间件开源组件:Sentinel 0.2.0正式发布
  • 漫谈开发设计中的一些“原则”及“设计哲学”
  • 目录与文件属性:编写ls
  • 小程序开发中的那些坑
  • 优化 Vue 项目编译文件大小
  • ​学习一下,什么是预包装食品?​
  • !$boo在php中什么意思,php前戏
  • (02)vite环境变量配置
  • (09)Hive——CTE 公共表达式
  • (14)Hive调优——合并小文件
  • (Python) SOAP Web Service (HTTP POST)
  • (生成器)yield与(迭代器)generator
  • (数位dp) 算法竞赛入门到进阶 书本题集
  • (转)http协议
  • (转)ObjectiveC 深浅拷贝学习
  • .net core使用ef 6
  • .NET delegate 委托 、 Event 事件
  • .Net6使用WebSocket与前端进行通信
  • .net安装_还在用第三方安装.NET?Win10自带.NET3.5安装
  • .net对接阿里云CSB服务
  • .net反编译工具
  • .ui文件相关
  • @ConditionalOnProperty注解使用说明
  • @Resource和@Autowired的区别
  • []指针
  • [2021 蓝帽杯] One Pointer PHP
  • [④ADRV902x]: Digital Filter Configuration(发射端)
  • [AIGC] Nacos:一个简单 yet powerful 的配置中心和服务注册中心
  • [BZOJ 4034][HAOI2015]T2 [树链剖分]
  • [BZOJ4016][FJOI2014]最短路径树问题
  • [hive小技巧]同一份数据多种处理
  • [JavaEE] 线程与进程的区别详解
  • [java后端研发]——文件上传与下载(2种方式)