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.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值