OpenGL authoring effects in some applications can be implemented by a single shader, that is, by modifying the vertex shader or the slice shader. But more scenes are required to have a combination of multiple special effects, such as the final effect is the gray scale of the picture plus upside down, the effect is not complex conditions can be achieved by modifying the element shader, when the effect of complex special effects, combined special effects, special effects modular development will be achieved through the chain filter.

First, the concept of chain filter

Chain filters combine and stack effects through frame buffering and off-screen rendering technology. Achieve the desired effect through multiple draws.

Frame buffering in the rendering process

OpenGL workflow, input pixel data and vertex data, two kinds of data respectively after operation, through rasterization, fragment, and then through fragment processing, finally drawn to the frame buffer, and finally converted into pixel data. The final destination for OpenGL pipeline rendering is the FrameBuffer. The following is an OpenGL rendering flowchart.

Frame buffer object

In the OpenGL rendering pipeline, geometric data and textures are transformed and tested many times, and finally displayed on the screen as two-dimensional pixels. The final rendering destination of the OpenGL pipeline is called the framebuffer. The frame buffer is a collection of two-dimensional arrays and storage areas used by OpenG: color cache, depth cache, template cache, and accumulative cache. In general, the frame cache is completely generated and managed by the Window system and used by OpenGL. This default frame cache is called a window-system-provided frame cache. OpenGL allows us to define our own frame buffers, which means we can define our own color buffers, even depth buffers and template buffers. There are multiple color associations, a depth association, and a template association in a frame cache object. Each frame cache has at least one color correlation point, the number of which is related to the physical graphics card. You can query the maximum number of color-associated points by using GL_MAX_COLOR_ATTACHMENTS_EXT. Note: There are no images stored in FBO, only multiple association points.

4. Customize the frame buffer

1: Create a frame buffer.

unsigned int fbo;
glGenFramebuffers(1, &fbo);
Copy the code

GlBindFramebuffer (FBO) is enabled when the frame buffer is bound.

3: Render to 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);

glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
Copy the code

Render chain

The frame buffer 0 binding is used to reactivate the default frame buffer and has visual effects in the main window.

1: Gray fragment shaderGray

precision highp float; uniform sampler2D Texture; varying vec2 TextureCoordsVarying; Const highp vec3 W = vec3(0.2125, 0.7154, 0.0721); void main (void) { vec4 mask = texture2D(Texture, TextureCoordsVarying); floatluminance = dot(mask.rgb, W); Gl_FragColor = vec4 (vec3 (luminance), 1.0); }Copy the code

1: Fragments shaderReverse

precision highp float; uniform sampler2D Texture; varying vec2 TextureCoordsVarying; Void main (void) {color = texture2D(Texture, vec2(TextureCoordsVarying. X, 1.0-Texturecoordsvarying. gl_FragColor = color; }Copy the code

The pseudocode is as follows:

// Step one unsigned int fbo; glGenFramebuffers(1, &fbo); glBindFramebuffer(GL_FRAMEBUFFER, fbo); 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); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0); DrawShaderGray(); / / draw the results on the texture / / setp two DrawWithGrayInShaderReverse (texture)Copy the code