GPU deep mining (III): OpenGL frame buffer object 201

Source: Internet
Author: User

GPU deep mining (III): OpenGL frame buffer object 201
Author: Rob 'phantom '; Jones Translator: 文 Updated: 2007/6/15

Introduction

In the previous article OpenGL framebuffer object 101, I introduced some basic FBO applications. The article mainly introduced how to generate a FBO, how to render data to a single texture and apply the texture elsewhere. However, FBO extensions are not the only method to achieve this. In the previous article, we mainly talked about a comprehensive feature of FBO: attachment point ).

In this article, we will further introduce some in-depth concepts and applications of FBO. First, let's take a look at how to repeatedly render data to multiple textures in an FBO object. After that, let's take a look at how to use the OpenGL advanced coloring language (glsl) to render and output to multiple textures at the same time. Of course, the drawing buffer extension (draw buffers extension) is also needed here ).

One FBO with multiple textures

In the previous article, we talked about how to bind a texture to a FBO to render the image as a Color render target ). We mainly use the following function.

 

Glframebuffertexture2dext (gl_framebuffer_ext, gl_color_attachment0_ext, gl_texture_2d, IMG, 0 );

 

You may still remember that in this function, we use IMG to save the change with the texture flag to bind the corresponding texture to the currently enabled FBO. In this article, we will focus on the second parameter:Gl_color_attachment0_ext.

This parameter tells OpenGL to bind the texture to the 0 color binding point of FBO. However, an FBO pair has multiple color binding points for us to use. Currently, the specification allows 16 binding points (Gl_color_attachment0_extToGl_color_attachment15_ext), Each binding point can be bound with a separate texture. Of course, the number of bound points is limited by hardware and its drivers. We can use the following functions to query the maximum number of bound points:

GLuint maxbuffers;
glGetIntergeri(GL_MAX_COLOR_ATTACHMENTS, &maxbuffers);

The maxbuffers variable saves the maximum value of the color binding point. When writing this article, the maximum value returned by the current video card hardware is generally 4.

Therefore, if we want to bind the texture identifier quantity IMG to the second color binding point, the above function must be modified as follows:

glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_TEXTURE_2D, img, 0);

As you can see, it is quite easy to add a binding texture. But how can we make OpenGL render data to these textures separately?

Select output target

Okay. Now let's look back at this special function: gldrawbuffer (), which is usually used at the beginning of OpenGL.

This function, as well as its closely related function glreadbuffer (), is used to tell OpenGL where it should write data and where it should read data. By default, in a single buffer environment, both of them perform read and write on the front buffer (gl_front), while in a dual buffer environment, they perform read and write on the rear buffer (glback. However, after FBO is extended, the function is modified, it allows you to select gl_color_attachmentx_ext as the rendering output or reading target ('x' here refers to the FBO binding vertex number ).

When you bind an FBO object, the system automatically points the current color output targetGl_color_attachment0_ext,That is, the texture bound to the binding point 0. Therefore, if you want to output the data to the default color binding point, you do not need to make any additional changes. But when we want to output data to other buffers, We Have To Tell OpenGL what we want.

Therefore, if we want to render it to gl_color_attachmant1_ext, we must first enable a FBO and correctly specify a binding point for the write buffer. Assume that we have bound a texture object to the color binding point of FBO No. 1. The following is the implementation code:

Glbindframebuffer (gl_framebuffer_ext, FBO );
Glpushattrib (gl_viewport_bit | gl_color_buffer_bit );
Glviewport (0, 0, width, height );

// Set the render target
Gldrawbuffer (gl_color_attachment1_ext );

// Render as normal here
// Output goes to the FBO and it attached Buffers


Glpopattrib ();
Glbindframebufferext (gl_framebuffer_ext, 0 );

It is worth noting that the glpushattrib () function is used here. It is mainly used to save some attributes of the viewpoints' and color buffering, because we need to modify these attributes during the FBO operation. After the FBO operation is complete, we can use the glpopattrib () function to restore the previous settings. This is mainly because some attribute changes during the FBO operation will directly affect the main rendering program. Through attribute restoration, the rendering of the main program can be restored to a normal state.

When we bind multiple textures to an FBO object, it is very important that all these textures have the same size and color depth. Therefore, we cannot bind a 512*512 32bit texture to a 256*256 16bit texture to the same FBO object. Therefore, if you can accept this limitation, you can use one FBO to render and output to multiple textures, Which is compared to switching between multiple FBO images, the speed will be much faster. Of course, multi-FBO switching is not a very slow operation, but it is usually a good programming habit to avoid unnecessary overhead.

Example 1

In the first sample program, we demonstrate how to render the texture to two textures. Of course, here we render the output one by one and then apply these textures to another cube. The Code is based on the example written in the previous article. It only makes some minor changes.

First, in the initialization function, we start FBO and bind the second texture to the FBO object. Note how to bind the first texture differently. Here gl_color_attachment1_ext is used as the binding point.

The rendering output for the scenario is basically the same, but here we have made a total of two plotting, the first time we plot with the original color of the cube, in the second drawing, the brightness of the color is adjusted to half of the original brightness.

You may have noticed that in the example program, when we render the output to FBO, we need to clearly tell OpenGL that the first is to render it to gl_color_attachment0_ext, and then gl_color_attachmaent1_ext. This is because FBO will remember the last buffer you asked it to render the output. Therefore, in the drawing function, when we draw the second drawing, the first bound texture as the target output will not be updated automatically until we call the gldrawbuffer () function. If you want to see the effect of this function, you can comment out 103rd rows. This line is a call to the gldrawbuffer () function, you will see that the texture on the left hand side of the cube will no longer change.

Multiple render targets)

Now we know how to bind multiple textures to one FBO, but we still draw only one texture at a time, and then write multiple textures by switching the drawing target, is there a more useful and efficient way? As mentioned at the beginning of this article, we will introduce how to render and output to multiple textures at the same time.

In fact, once you understand how to bind multiple textures, it is very easy to do. The other technologies you need now include drawing buffer extensions (draw buffers extension) and OpenGL coloring language (glsl), which are now part of the opengl2.0 kernel.

Drawing buffer extension (draw buffers extension)

Now we will introduce the first extension: the creation of the drawing buffer. Create a drawing buffer. We use the gldrawbuffer () function provided by a system. You may remember this function. As we mentioned earlier, it can be used to specify the color buffer of the current rendering output. However, in the drawing buffer extension, this function is also extended, which can be used to specify multiple color buffers simultaneously written. The number of buffers that can be written at one time. You can use the following function to query the number:

GLuint maxbuffers;
glGetIntergeri(GL_MAX_DRAW_BUFFERS, &maxbuffers);

After the function is correctly executed, the variable maxbuffers saves the number of buffers that can be rendered at a time. When I write this document, this number is generally 4, however, the latest video card geforce8x00 series allows us to output to eight buffers at a time.

Therefore, if we have bound the two textures to the binding points 0 and 1 respectively, and now we want to render the two textures at the same time, we can write the following code:

GLenum buffers[] = ...{ GL_COLOR_ATTACHMENT0_EXT, GL_COLOR_ATTACHMENT1_EXT };
glDrawBuffers(2, buffers);

After the preceding functions are correctly run, OpenGL creates a dual-color buffer rendering output environment.

Use FBO and glsl to implement MRT

Now, if we use a standard fixed function pipeline for rendering, the two textures will get the same data. However, if glsl is used to override the part coloring code, we can send different data to these two textures.

Generally, when you write a glsl part coloring program, you will output the color value to gl_fragcolor. Normally, the color value is written to the frame buffer. However, here we also have the second method of color information output, that is, using the gl_fragdata [] array.

This special variable allows us to directly specify where the data goes. Which texture does the data output correspond? This is related to the order of the parameters specified in the gldrawbuffers () function. In this case, the corresponding relationship of the buffer zone is shown in:

Gldrawbuffers Value Fragdata syntax
Gl_color_attachment0_ext Gl_fragdata [0]
Gl_color_attachment1_ext Gl_fragdata [1]

When the above function is called, if the Parameter order changes, the corresponding ing relationship will also change, as shown below:

GLenum buffers[] = ...{ GL_COLOR_ATTACHMENT1_EXT, GL_COLOR_ATTACHMENT0_EXT };
glDrawBuffers(2, buffers);
Gldrawbuffers Value Fragdata syntax
Gl_color_attachment1_ext Gl_fragdata [0]
Gl_color_attachment0_ext Gl_fragdata [1]

If we want to output green to one of the targets and blue to the other, the glsl code can be written as follows:

#version 110

void main()
...{
    gl_FragData[0] = vec4(0.0, 1.0, 0.0);
    gl_FragData[1] = vec4(0.0, 0.0, 1.0);
}

The first line is that our driver supports at least glsl 1.10 or above (ogl2.0 ). The function body only writes green to the first buffer and blue to the second buffer.

 

Note: The CG code is as follows:

void main(out float4 col0:COLOR0,out float4 col0:COLOR1)
...{
        col0 = float4(0.0,1.0,0.0,1.0);
        col1 = float4(0.0,0.0,1.0,1.0);
}

 

Example 2

The second example is the combination of the first example and the previous example. It implements the same output in the first example, but here we only plot the Cube once. We use a coloring program to control the output.

The program is similar to the previous one. The main difference is the initialization code. We leave the glsl code imported aside, because this is not the scope of this article. The main code that can make multi-object rendering work normally is the following two lines:

GLenum mrt[] = ...{ GL_COLOR_ATTACHMENT0_EXT, GL_COLOR_ATTACHMENT1_EXT }
glDrawBuffers(2, mrt);

The two lines tell OpenGL that we want to render the two buffers and the two buffers we want to render. Remember that FBO has a memory function, that is, it records the output target used in the last rendering. With the above two lines of code, we can change the goal of the FBO rendering output so that it can be correctly rendered to multiple textures at the same time.

The plot loop function looks very similar. The same code is used for rendering to FBO. The changed part is about binding and calling the glsl program. Glsl is mainly used to control multiple outputs of colors. The code below is basically no different from the first example in this article, but the cube is painted twice in the first example, and only one painting is needed here.

For the two glsl coloring programs in the program, let's take a look at how they make the MRT work normally.

The Vertex coloring program is a piece of code that runs once every vertex you send to the video card. In this program, the color value of each vertex is transmitted through glcolor () to the segment coloring program, and some necessary matrix transformations are performed for each vertex, this allows us to draw a cube in the correct position.

The code of the part coloring program is as follows:

#version 110

void main(void)
...{
    gl_FragData[0] = vec4(gl_Color.r, gl_Color.g,gl_Color.b,1.0);
    gl_FragData[1] = vec4(gl_Color.r/2.0, gl_Color.g/2.0,gl_Color.b/2.0,1.0);
}

The key here is two gl_fragdata, which are used to determine the buffer to which data is written. In this example, gl_fragdata [0] indicates the first texture. It stores a color value that has not been modified, that is, the original color passed from the face of the vertex. For gl_fragdata [1], it corresponds to the second texture, which is also used to save the color passed from the vertex coloring, but the brightness of the color is changed to half of the original. From the result, the effect is the same as that of the first program.

Last thought

This article uses two examples to quickly introduce two different FBO extensions.

In the first example, you can use the same FBO for rendering and output to multiple textures, so that we do not need to switch between multiple fbrs frequently, the technology demonstrated in this example is very useful, because it is much faster to switch between different rendering targets in the same FBO for different FBO switching. Therefore, if you can group your textures and try to render multiple textures at the same time, this will save you a lot of time.

The second example shows how to use multiple render targets. Although the examples mentioned in this Article do not have great practical value, the MRT technology is the basis of many other advanced GPU technologies, for example, render-to-vertex buffer and post-processing. Therefore, this function can be used to output multiple color buffers. It is worth further study and research.

For more details, refer to the specifications of framebuffer object and draw buffers. In more OpenGL game programming, I wrote an article about FBO and glsl. The related technologies are also discussed.

Some notes in this example

In this example, glut is used during compilation and running (I use freeglut ).

Statement

This translation can be freely reproduced and requires that the original author information be retained, and the article is from the physical development network: www.physdev.com

MoreDeep GPU ExplorationArticle, please pay attention to the Physical Development Network

 

Reference

More OpenGL game programming
Framebuffer object spec
GDC 2005 framebuffer object PDF

See also:
OpenGL
Programming

 


 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.