LearnOpenGL14-Mixing and processing translucent objects

Reprinted from
https://blog.csdn.net/qq_36696486/article/details/104409547
https://learnopengl-cn.github.io/04%20Advanced%20OpenGL/03%20Blending/#_1

Preface

In OpenGL, blending is usually a technique for achieving object transparency (Transparency). That is a transparent object (or portion thereof) is not a solid (Solid Color), and its color is the color of the object itself and other objects behind it colors different bonding strength. A colored glass window is a transparent object. The glass has its own color, but its final color also includes the color of all objects behind the glass. This is where the name blend comes from. We blend (Blend) (of different objects) multiple colors into one color. So transparency allows us to see through objects.
Insert picture description here
Transparent objects can be completely transparent (let all colors pass through) or semi-transparent (it let colors pass through and also show their own colors). The transparency of an object is determined by the aplha value of its color.

Discard fragments

The texture we have been using currently has three color components: red, green, and blue. But some materials have an embedded alpha channel, which contains an alpha value for each texel. This alpha value tells us exactly the transparency of each part of the texture.
Insert picture description here

So when adding vegetation like grass to the scene, we don't want to see a square image of grass, but only show the grass part and be able to see through the rest of the image. We want to discard (Discard) the fragments that show the transparent part of the texture, and not store these fragments in the color buffer.
GLSL gave us the discard command. Once it is called, it will ensure that the fragment will not be processed further, so it will not enter the color buffer. With this instruction, we can detect in the fragment shader whether the alpha value of a fragment is below a certain threshold, and if it is, discard the fragment as if it does not exist:

#version 330 core
out vec4 FragColor;

in vec2 TexCoords;

uniform sampler2D texture1;

void main()
{
    
                 
    vec4 texColor = texture(texture1, TexCoords);
    if(texColor.a < 0.1)
        discard;
    FragColor = texColor;
}

mixing

Although it is good to discard the fragment directly, it does not allow us to render a semi-transparent image. We either render a fragment or discard it altogether. To render images with multiple levels of transparency, we need to enable Blending. Like most functions of OpenGL, we can enable GL_BLEND to enable blending:

glEnable(GL_BLEND);

Mixed equation:

result = sourceFsource + destinationFdestination

Insert picture description here
We have two squares, and we want to draw this semi-transparent green square on top of the red square. The red square will be the target color (so it should be in the color buffer first), and we will draw this green square on top of this red square. Insert picture description here
Insert picture description here
The result is that the overlapping square fragment contains a dirty color of 60% green and 40% red:
Insert picture description here
**glBlendFunc(GLenum sfactor, GLenum dfactor)** function accepts two parameters to set the source and target factors.
The formula is similar to interpolation. The values ​​of
Fsource and Fdestination are the following options: the
Insert picture description here
general choice is:

glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

You can also use glBlendFuncSeparate to set different options for the RGB and alpha channels respectively

glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ZERO);

Render translucent texture

Rendering translucent objects directly
Now (whenever OpenGL renders a fragment) it will blend the color of the current fragment with the color of the fragment in the current color buffer according to the alpha value. Since the glass part of the window texture is translucent, we should be able to see the scene behind it through the window.
Insert picture description here

The reason for this phenomenon is that depth testing and mixing together will cause some trouble. When writing to the depth buffer, the depth buffer does not check whether the fragment is transparent, so the transparent part will be written into the depth buffer like other values. The result is that the entire quad of the window will be tested for depth regardless of transparency. Even though the transparent parts should show the windows behind them, the depth test still discards them.
So we can't arbitrarily decide how to render the window, let the depth buffer solve all the problems. This is also the part where mixing becomes a little troublesome. To ensure that the windows behind them can be displayed in the windows, we need to draw the part of the windows behind them first. This means that when drawing, we must manually sort the windows from the farthest to the nearest, and then render them in order.

Solution

To make the blend work on multiple objects, we need to draw the furthest object first and the closest object last. Ordinary objects that do not need to be blended can still be drawn normally using the depth buffer, so they do not need to be sorted. But we still have to make sure that they are drawn before the (sorted) transparent objects are drawn. When drawing a scene with opaque and transparent objects, the general principles are as follows:

  1. First draw all opaque objects.
  2. Sort all transparent objects from far to near.
  3. Draw all transparent objects in order.

One way to sort transparent objects is to get the distance of the objects from the observer's perspective. This can be obtained by calculating the distance between the camera position vector and the object position vector. Next, we store the distance and its corresponding position vector in a map data structure of the STL library. The map will automatically sort its values ​​according to the key value, so as long as we add all the positions and use their distance as the key, they will automatically be sorted according to the distance value.
Then traverse the map in reverse
Insert picture description here

Guess you like

Origin blog.csdn.net/J_avaSmallWhite/article/details/113837993