OpenGL video basis of FBO-- of beauty

Original link: https://www.jianshu.com/p/c16c7e7cdf91

https://www.jianshu.com/p/c16c7e7cdf91

 

OpenGL video basis of FBO-- of beauty

0.582017.10.04 23:45:59 2938 read 4548 words

Foreword

In OpenGL, there is a very important point is that knowledge FBO (Frame Buffer Object). It provides the technical means to do video beauty.

The Internet can find a lot of articles introduced FBO, but few will make it clear relationship between FBO, Texture and Render Buffer.

This article describes the FBO at the same time, a clear description of the relationship between the three. I hope this article to be helpful.

FBO

OpenGL default rendering of the framebuffer as a destination. It is created and managed by the window system. framebuffer Object is a collection of two-dimensional array, which includes color buffers, depth buffer, stencil buffer.

OpenGL extensions, GL_ARB_framebuffer_object provided to create additional non-display framebuffer object (FBO) interface. FBO called framebuffer framebuffer applications can be created to distinguish the default window provided by the system. By using FBO, OpenGL rendering application can redirect the output, it is output to the framebuffer FBO rather than the traditional window systems provide.

Frame buffer similar to that provided with the window system, comprising a series of rendering the FBO set destination; include color, depth, and stencil buffer. FBO of these buffers is called a logical frame buffer can be attached.

There are two types of framebuffer attachable; texture (the Texture) and renderbuffer. If the texture is attached to the FBO, OpenGL will perform "render to texture." If renderbuffer is attached to the FBO, the OpenGL will perform "off-screen rendering."

By the way, renderbuffer is a new type of storage objects defined extensions GL_ARB_framebuffer_object. It is used to render a 2D image of a single destination during rendering.

The following figure shows the connection between the FBO, textures and renderbuffer. Renderbuffer texture object or a plurality of objects may be attached to the attachment points through the FBO.

FBO in

  • A plurality of additional color points (GL_COLOR_ATTACHMENT0, ..., GL_COLOR_ATTACHMENTn),
  • A depth of the attachment point (GL_DEPTH_ATTACHMENT)
  • A template additional point (GL_STENCIL_ATTACHMENT).

Number of colors depending on implementation attachment points, but each must have at least one color FBO attachment point. You can use GL_MAX_COLOR_ATTACHMENTS query maximum number of colors additional point, the data from the graphics support.

FBO additional reason for having a plurality of color dots is allowed at the same time render the color buffer to the plurality of destinations. This "multiple render targets" (MRT) can be extended by the GL_ARB_draw_buffers completed. Please note, FBO itself does not store data, it only has multiple attachment points. This is somewhat like a pointer to the data structure, storing only pointers, not to store data.

FBO provides an efficient switching mechanism; separation buffer from the previous frame in the FBO, and attach a new image frame buffer may be attached to the FBO. May be attached to the image frame buffer switching ratio of the switching between the FBO much faster. FBO provided glFramebufferTexture2D () to switch between 2D texture objects, and glFramebufferRenderbuffer () to switch to renderbuffer object.

Creating FBO

glGenFramebuffers()

void glGenFramebuffers(GLsizei n, GLuint* ids)
void glDeleteFramebuffers(GLsizei n, const GLuint* ids)

glGenFramebuffers () requires two parameters:

  • The first is the number of frame buffer to be created;
  • The second parameter is a pointer to a variable or array to store GLuint single or a plurality of ID ID pointers.
  • It returns the object ID framebuffer unused. ID 0 represents the default frame buffer, the frame buffer which is provided by the window system.
  • And, when the FBO no longer in use, can be deleted by calling glDeleteFramebuffers ().

glBindFramebuffer()

After you create a FBO, it must first bind FBO.

void glBindFramebuffer(GLenum target, GLuint id)
  • The first parameter is the target GL_FRAMEBUFFER;
  • The second parameter is the object ID framebuffer. After FBO binding, all OpenGL FBO operations will affect the current binding.
  • Object ID, 0 reserved to the default window frame buffer provided by the system. Accordingly, in order to cancel the current frame binding buffer (the FBO), in use ID 0 glBindFramebuffer () in.

Renderbuffer

In addition, renderBuffer objects are newly introduced for offscreen rendering. It allows the scene to render directly to renderbuffer object instead of rendering to a texture object.

Renderbuffer just a data storage objects may be rendered single internal format comprising image. It is used to store no corresponding logical buffer OpenGL texture formats, such as templates or the depth buffer.

glGenRenderbuffers ()

void glGenRenderbuffers(GLsizei n, GLuint* ids)
void glDeleteRenderbuffers(GLsizei n, const Gluint* ids)

Once a renderbuffer created, it returns a non-zero positive integer. ID 0 is reserved OpenGL.

glBindRenderbuffer ()

void glBindRenderbuffer(GLenum target, GLuint id)

As with other OpenGL object, you must bind the current renderbuffer object before references. Renderbuffer target parameter object should be GL_RENDERBUFFER.

glRenderbufferStorage ()

void glRenderbufferStorage(GLenum  target,
                           GLenum  internalFormat,
                           GLsizei width,
                           GLsizei height)

When you create a renderbuffer object that does not have any data storage, so we have to allocate a memory space for it. This can be done by using glRenderbufferStorage ().

  • The first argument must be GL_RENDERBUFFER;
  • The second parameter is rendered color (GL_RGB, GL_RGBA, etc.), can render the depth (GL_DEPTH_COMPONENT) or renders the template (GL_STENCIL_INDEX);
  • width and height in pixels for the size of the image renderbuffer units.

Width and height should be less than GL_MAX_RENDERBUFFER_SIZE, GL_INVALID_VALUE would otherwise generate an error.

glGetRenderbufferParameteriv ()

void glGetRenderbufferParameteriv(GLenum target,
                                  GLenum param,
                                  GLint* value)

You can also get a variety of parameters renderbuffer object currently bound.

  • The goal should be GL_RENDERBUFFER;
  • The second parameter is the name of the parameter;
  • The last is a pointer to an integer variable for storing the value returned.

Name renderbuffer available parameters are:

GL_RENDERBUFFER_WIDTH
GL_RENDERBUFFER_HEIGHT
GL_RENDERBUFFER_INTERNAL_FORMAT
GL_RENDERBUFFER_RED_SIZE
GL_RENDERBUFFER_GREEN_SIZE
GL_RENDERBUFFER_BLUE_SIZE
GL_RENDERBUFFER_ALPHA_SIZE
GL_RENDERBUFFER_DEPTH_SIZE
GL_RENDERBUFFER_STENCIL_SIZE

The image is attached to the FBO

FBO itself does not store any data for. Instead, we must be extra framebuffer additional image (texture or renderbuffer objects) on the FBO. This mechanism allows fast switching FBO frame buffer images (and additional removal) may be attached to the FBO. Attachable frame buffer switching between FBO than faster switching. And it can save unnecessary data copies and memory consumption. For example, a plurality of textures can be attached to the FBO, and which may be shared by a plurality of image FBO.

2D texture image attached to the FBO

glFramebufferTexture2D(GLenum target,
                       GLenum attachmentPoint,
                       GLenum textureTarget,
                       GLuint textureId,
                       GLint  level)

glFramebufferTexture2D () is a 2D texture image attached to the FBO.

  • The first argument must be GL_FRAMEBUFFER;
  • The second parameter is the point of attachment of the texture image. FBO having a plurality of additional color points (GL_COLOR_ATTACHMENT0, ..., GL_COLOR_ATTACHMENTn), GL_DEPTH_ATTACHMENT and GL_STENCIL_ATTACHMENT;
  • The third parameter "textureTarget" In most cases GL_TEXTURE_2D;
  • The fourth parameter is the identifier of the texture of the object;
  • The last parameter is the mipmap level to attach the texture.

If textureId parameter is set to 0, then the texture image is separated from the FBO. If the texture is still attached to the object is deleted, the texture image will be automatically isolated from the currently bound FBO in the FBO. However, if it is attached to multiple FBO and deleted, it will only FBO bound separation, but will not be separated from any other FBO unconstrained.

Attached to the image to FBO Renderbuffer

void glFramebufferRenderbuffer(GLenum target,
                               GLenum attachmentPoint,
                               GLenum renderbufferTarget,
                               GLuint renderbufferId)

You can attach renderbuffer by calling glFramebufferRenderbuffer ().

  • The first and second parameters glFramebufferTexture2D () the same;
  • The third parameter must be GL_RENDERBUFFER;
  • The last parameter is the ID renderbuffer object.

If renderbufferId parameter is set to 0, then the FBO renderbuffer image from the additional separation points. If renderbuffer object is deleted, still attached to the FBO, then it is automatically separated from the bound FBO. However, it will not be separated from any other FBO unconstrained.

FBO status check

Once the image (texture and the renderbuffer) may be connected to the FBO attached, and before performing operation FBO must use glCheckFramebufferStatus () to verify whether the complete state FBO. FBO If not completed, the read command and any drawing (glBegin (), glCopyTexImage2D (), etc.) will fail.

GLenum glCheckFramebufferStatus(GLenum target)

glCheckFramebufferStatus () to verify that all the additional image on the currently bound FBO and frame buffer parameters. Moreover, this function can not be glBegin () / glEnd () on the call. Target parameters should be GL_FRAMEBUFFER. It returns a nonzero value after checking the FBO. If you meet all the requirements and rules, GL_FRAMEBUFFER_COMPLETE is returned. Otherwise, it returns a value related errors, it tells what the rules are violated.

FBO integrity rules are:

  • framebuffer can be additional image width and height must not be zero.
  • If a color image is attached to the attachment point, the image must be rendered color internal format. (GL_RGBA, GL_DEPTH_COMPONENT, GL_LUMINANCE, etc.)
  • If the image is attached to GL_DEPTH_ATTACHMENT, the image must be rendered depth internal format. (GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT24, etc.)
  • If the image is attached to GL_STENCIL_ATTACHMENT, the image must have a template can render internal format. (GL_STENCIL_INDEX, GL_STENCIL_INDEX8, etc.)
  • FBO must install at least one picture.
  • All additional FBO image must have the same width and height.
  • All attachment points additive color image must have the same internal format.

Note that even if all the above conditions are met, OpenGL drivers may not support some combination of internal format and parameters. If the driver does not support OpenGL particular implementation, so glCheckFramebufferStatus () returns GL_FRAMEBUFFER_UNSUPPORTED.

example

Sometimes it is necessary to dynamically generate dynamic texture. The most common example is to generate a mirror / reflection effect, dynamic cube / shadow mapping and environment mapping. Dynamic texture can be achieved by rendering the scene to a texture. One conventional method to render the texture like typical draw buffer, and then use glCopyTexSubImage2D () to copy the framebuffer into the texture images.

Use FBO, we can render a scene directly to the texture, so we do not have to use the window frame buffer provided by the system. Furthermore, we can eliminate the extra copy of the data (from the frame buffer to texture).

Use FBO has another advantage. In the conventional case, if the resolution is larger than the texture rendering window size, the window area of ​​the region to be cut. However, FBO is not affected by such problems. You can create a framebuffer-renderable image larger than the display window.

The following code is provided FBO before rendering the start of the cycle and may be additional image frame buffer. Note that not only the texture image attached to the FBO, and renderBuffer be added to the depth image attachment point of FBO. We did not actually use such a depth buffer, but FBO itself needs depth testing. If we do not this may render the depth image to a FBO, due to the lack of depth testing, the rendered output will be damaged. If you need to test the template during rendering FBO, the additional image rendering cache should be attached to GL_STENCIL_ATTACHMENT.

...
// create a texture object
GLuint textureId;
glGenTextures(1, &textureId);
glBindTexture(GL_TEXTURE_2D, textureId);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE); // automatic mipmap
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, TEXTURE_WIDTH, TEXTURE_HEIGHT, 0,
             GL_RGBA, GL_UNSIGNED_BYTE, 0);
glBindTexture(GL_TEXTURE_2D, 0);

// create a renderbuffer object to store depth info
GLuint rboId;
glGenRenderbuffers(1, &rboId);
glBindRenderbuffer(GL_RENDERBUFFER, rboId);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT,
                      TEXTURE_WIDTH, TEXTURE_HEIGHT);
glBindRenderbuffer(GL_RENDERBUFFER, 0);

// create a framebuffer object
GLuint fboId;
glGenFramebuffers(1, &fboId);
glBindFramebuffer(GL_FRAMEBUFFER, fboId);

// attach the texture to FBO color attachment point
glFramebufferTexture2D(GL_FRAMEBUFFER,        // 1. fbo target: GL_FRAMEBUFFER 
                       GL_COLOR_ATTACHMENT0,  // 2. attachment point
                       GL_TEXTURE_2D,         // 3. tex target: GL_TEXTURE_2D
                       textureId,             // 4. tex ID
                       0);                    // 5. mipmap level: 0(base)

// attach the renderbuffer to depth attachment point
glFramebufferRenderbuffer(GL_FRAMEBUFFER,      // 1. fbo target: GL_FRAMEBUFFER
                          GL_DEPTH_ATTACHMENT, // 2. attachment point
                          GL_RENDERBUFFER,     // 3. rbo target: GL_RENDERBUFFER
                          rboId);              // 4. rbo ID

// check FBO status
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if(status != GL_FRAMEBUFFER_COMPLETE)
    fboUsed = false;

// switch back to window-system-provided framebuffer
glBindFramebuffer(GL_FRAMEBUFFER, 0);
...

Rendering the texture rendering process is almost the same with ordinary drawing. We only need to render the destination switch from the framebuffer window system can be provided to the FBO.

...
// set rendering destination to FBO
glBindFramebuffer(GL_FRAMEBUFFER, fboId);

// clear buffers
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

// draw a scene to a texture directly
draw();

// unbind FBO
glBindFramebuffer(GL_FRAMEBUFFER, 0);

// trigger mipmaps generation explicitly
// NOTE: If GL_GENERATE_MIPMAP is set to GL_TRUE, then glCopyTexSubImage2D()
// triggers mipmap generation automatically. However, the texture attached
// onto a FBO should generate mipmaps manually via glGenerateMipmap().
glBindTexture(GL_TEXTURE_2D, textureId);
glGenerateMipmap(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, 0);
...

Note, glGenerateMipmap () also contains as part FBO extended to explicitly generate mipmap texture image after modifying the basic level. If GL_GENERATE_MIPMAP set GL_TRUE, the glTex {Sub} Image2D () and glCopyTex {Sub} Image2D () automatically triggers mipmap generation (in OpenGL 1.4 or later). However, since no call FBO glCopyTex {Sub} Image2D () to modify the texture, and therefore does not automatically generate texture FBO basic level. Therefore, you must explicitly call glGenerateMipmap () to generate a mipmap.

Further, if you need to process the texture, the pixel buffer may be combined with the object (a PBO), to effectively modify the texture.

summary

This paper describes the OpenGL FBO in what is, at the same time clarifying the relationship between the FBO texture and Render Buffer. Finally, an example illustrates the use of the FBO.

Guess you like

Origin blog.csdn.net/u010029439/article/details/100924155