Color Mixing OpenGL

Source: Internet
Author: User
What is hybrid? Mixing is to mix the two colors together. Specifically, the original color at a certain pixel location and the color to be painted are mixed together in some way to achieve special effects.
Suppose we need to draw a scenario: to look at the green object through the red glass, we can first draw the green object, then draw the red glass. When drawing the red glass, use the "mix" function to mix the red and the original green to get a new color, it looks like the glass is translucent.
To use the mixed functions of OpenGL, you only need to call: glable (gl_blend.
To disable the OpenGL hybrid function, you only need to call: gldisable (gl_blend.
Note: The hybrid function can be used only in rgba mode. The hybrid function cannot be used in color index mode.
I. Source and target factors
As we have mentioned above, you need to find out the original color and the color to be painted. After some processing, you can get a new color. Here, the color to be painted is called "Source color", and the original color is called "target color ".
OpenGL extracts the source color and the target color respectively and times the coefficient (the source color multiplied by the coefficient is called the "source factor", and the target color multiplied by the coefficient is called the "Target Factor "), then add the new colors. (Or not adding. The new version of OpenGL can be used to set the calculation method, including adding, subtracting, and obtaining larger values of the two, smaller values of the two, and logical operations, but we will not discuss this here for the sake of simplicity)
The following uses mathematical formulas to express this calculation method. Assume that the four components of the source color (red, green, blue, and alpha) are (RS, GS, BS, as), and the four components of the target color are (Rd, Gd, BD, AD), and the source factor is (Sr, SG, Sb, SA), and the target factor is (DR, DG, DB, DA ). The new color generated by the hybrid operation can be expressed:
(RS * Sr + RD * Dr, GS * SG + GD * DG, BS * Sb + bd * dB, as * Sa + Ad * Da)
Of course, if a certain color component exceeds 1.0, it will be automatically truncated to 1.0, and the problem of crossing the border does not need to be considered.

The source and target factors can be set through the glblendfunc function. Glblendfunc has two parameters. The former indicates the source factor, and the latter indicates the target factor. These two parameters can be multiple values. The following describes several commonly used parameters.
Gl_zero: 0.0 is used as the factor, which is equivalent to not using this color for hybrid operation.
Gl_one: 1.0 is used as the factor. In fact, this color is used completely in the hybrid operation.
Gl_src_alpha: indicates that the alpha value of the source color is used as a factor.
Gl_dst_alpha: Use the Alpha value of the target color as a factor.
Gl_one_minus_src_alpha: Used to subtract the Alpha value of the source color from 1.0 as a factor.
Gl_one_minus_dst_alpha: the Alpha value of the target color minus 1.0 is used as a factor.
In addition, there are also gl_src_color (four components of the source color are used as the four components of the factor respectively), gl_one_minus_src_color, gl_dst_color, and gl_one_minus_dst_color. The first two components can only be used, the last two versions of OpenGL can only be used to set source factors. The new version of OpenGL does not have this restriction, and supports the new gl_const_color (set a constant color and use its four components as the four components of the factor respectively), gl_one_minus_const_color, gl_const_alpha, and gl_one_minus_const. In addition, there is gl_src_alpha_saturate. The new version of OpenGL also allows different mixing factors for the Alpha and RGB values of colors. But these are not what we need to know now. After all, this is an entry-level teaching material and does not need to be too complicated ~

For example:
If glblendfunc (gl_one, gl_zero); is set, the source color is used completely, and the target color is not used at all, therefore, the image effect is the same as that when the image is not mixed (of course, the efficiency may be a little lower ). If the source and target factors are not set, this is the default setting.
If glblendfunc (gl_zero, gl_one); is set, the source color is not used at all. Therefore, no matter what you want to draw, it will not be painted at last. (But this does not mean that this setting is useless, and sometimes it may be used for special purposes)
If glblendfunc (gl_src_alpha, gl_one_minus_src_alpha) is set, the source color is multiplied by its own Alpha value, and the target color is multiplied by 1.0 minus the Alpha value of the source color, the larger the Alpha value of the source color, the larger the proportion of the source color in the new color, and the smaller the proportion of the target color. In this case, we can simply think of the Alpha value of the source color as "opacity ". This is also the most common method for mixing.
If glblendfunc (gl_one, gl_one); is set, the source color and the target color are used completely. The final color is actually a simple addition of the two colors. For example, red (1, 0, 0) and green (0, 1, 0) are added to get (1, 1, 0), and the result is yellow.
Note:
The source color and target color are related to the draw sequence. If a red object is first drawn, then a green object is drawn on it. Green indicates the source color, and red indicates the target color. If the order is reversed, red indicates the source color, and Green indicates the target color. When drawing, pay attention to the order, so that the source color of the painting corresponds to the set source factor, and the target color corresponds to the set target factor. Do not be confused by the disordered order.
 
I. Source and target factors
As we have mentioned above, you need to find out the original color and the color to be painted. After some processing, you can get a new color. Here, the color to be painted is called "Source color", and the original color is called "target color ".
OpenGL extracts the source color and the target color respectively and times the coefficient (the source color multiplied by the coefficient is called the "source factor", and the target color multiplied by the coefficient is called the "Target Factor "), then add the new colors. (Or not adding. The new version of OpenGL can be used to set the calculation method, including adding, subtracting, and obtaining larger values of the two, smaller values of the two, and logical operations, but we will not discuss this here for the sake of simplicity)
The following uses mathematical formulas to express this calculation method. Assume that the four components of the source color (red, green, blue, and alpha) are (RS, GS, BS, as), and the four components of the target color are (Rd, Gd, BD, AD), and the source factor is (Sr, SG, Sb, SA), and the target factor is (DR, DG, DB, DA ). The new color generated by the hybrid operation can be expressed:
(RS * Sr + RD * Dr, GS * SG + GD * DG, BS * Sb + bd * dB, as * Sa + Ad * Da)
Of course, if a certain color component exceeds 1.0, it will be automatically truncated to 1.0, and the problem of crossing the border does not need to be considered.

The source and target factors can be set through the glblendfunc function. Glblendfunc has two parameters. The former indicates the source factor, and the latter indicates the target factor. These two parameters can be multiple values. The following describes several commonly used parameters.
Gl_zero: 0.0 is used as the factor, which is equivalent to not using this color for hybrid operation.
Gl_one: 1.0 is used as the factor. In fact, this color is used completely in the hybrid operation.
Gl_src_alpha: indicates that the alpha value of the source color is used as a factor.
Gl_dst_alpha: Use the Alpha value of the target color as a factor.
Gl_one_minus_src_alpha: Used to subtract the Alpha value of the source color from 1.0 as a factor.
Gl_one_minus_dst_alpha: the Alpha value of the target color minus 1.0 is used as a factor.
In addition, there are also gl_src_color (four components of the source color are used as the four components of the factor respectively), gl_one_minus_src_color, gl_dst_color, and gl_one_minus_dst_color. The first two components can only be used, the last two versions of OpenGL can only be used to set source factors. The new version of OpenGL does not have this restriction, and supports the new gl_const_color (set a constant color and use its four components as the four components of the factor respectively), gl_one_minus_const_color, gl_const_alpha, and gl_one_minus_const. In addition, there is gl_src_alpha_saturate. The new version of OpenGL also allows different mixing factors for the Alpha and RGB values of colors. But these are not what we need to know now. After all, this is an entry-level teaching material and does not need to be too complicated ~

For example:
If glblendfunc (gl_one, gl_zero); is set, the source color is used completely, and the target color is not used at all, therefore, the image effect is the same as that when the image is not mixed (of course, the efficiency may be a little lower ). If the source and target factors are not set, this is the default setting.
If glblendfunc (gl_zero, gl_one); is set, the source color is not used at all. Therefore, no matter what you want to draw, it will not be painted at last. (But this does not mean that this setting is useless, and sometimes it may be used for special purposes)
If glblendfunc (gl_src_alpha, gl_one_minus_src_alpha) is set, the source color is multiplied by its own Alpha value, and the target color is multiplied by 1.0 minus the Alpha value of the source color, the larger the Alpha value of the source color, the larger the proportion of the source color in the new color, and the smaller the proportion of the target color. In this case, we can simply think of the Alpha value of the source color as "opacity ". This is also the most common method for mixing.
If glblendfunc (gl_one, gl_one); is set, the source color and the target color are used completely. The final color is actually a simple addition of the two colors. For example, red (1, 0, 0) and green (0, 1, 0) are added to get (1, 1, 0), and the result is yellow.
Note:
The source color and target color are related to the draw sequence. If a red object is first drawn, then a green object is drawn on it. Green indicates the source color, and red indicates the target color. If the order is reversed, red indicates the source color, and Green indicates the target color. When drawing, pay attention to the order, so that the source color of the painting corresponds to the set source factor, and the target color corresponds to the set target factor. Do not be confused by the disordered order.

3. 3D Mixing
Maybe you can't wait to draw a 3D scene with a translucent object. However, I am afraid I am not able to do it now. Another point is that we must pay attention when mixing 3D scenes, that is, deep buffering.
Deep buffer is such a piece of data, which records how close each pixel is to the observer. When the deep buffer test is enabled, if the pixel to be drawn is closer than the original pixel, the pixel will be drawn. Otherwise, pixels will be ignored and will not be drawn. This is useful when drawing opaque objects-whether it is to draw near objects first and then draw distant objects, or to draw distant objects and then draw near objects first, or simply draw in a disordered order, and the final display result is always close to the object to cover the distant object.
However, when you need to achieve a translucent effect, you will find that everything is not that good. If you draw a close-range semi-transparent object, it retains some information in the depth buffer, so that the distant object cannot be drawn again. Although a translucent object is still translucent, what you see through it is not the correct content.
To solve the above problem, you need to set the depth buffer to read-only when creating a translucent object. As a result, although the translucent object is drawn, the depth buffer remains in the original state. If another object appears after the translucent object, it can be drawn before the opaque object (because the depth of the object is recorded in the depth buffer ). To draw an opaque object later, you only need to set the depth buffer to readable and writable. Hmm? How do I draw a part of a semi-transparent part of an object? To do this well, you only need to divide the object into two parts, one of which is semi-transparent and the other part is non-transparent. You can draw them separately.
Even with the above techniques, we still cannot draw in chaotic order as we wish. You must first draw an opaque object, and then draw a transparent object. Otherwise, assume that the background is blue, near a red glass, and a green object in the middle. If you first draw a red translucent glass, it will first mix it with the blue background, then when you draw a green object in the middle, you can no longer mix it with the red glass.
To sum up, the order of drawing is: first, draw all opaque objects. If both objects are non-transparent, it does not matter who is first or who is later. Then, set the depth buffer to read-only. Next, draw all translucent objects. If the two objects are semi-transparent, then the first one needs to follow his own wishes (note that the first one will become the "target color ", the source color, so the order will have some impact on the result ). Finally, set the depth buffer to the readable and writable form.
Call gldepthmask (gl_false); you can set the depth buffer to read-only. Call gldepthmask (gl_true); you can set the depth buffer to a readable and writable form.
Some online tutorials, including the well-known nehe tutorials, disable the depth buffer directly when using 3D hybrid, that is, call gldisable (gl_depth_test );. This is incorrect. If you first draw an opaque object and then draw a translucent object behind it, the translucent object behind it will not be displayed (it is covered by an opaque object), but If you disable the depth buffering function, then it will be displayed and mixed. Nehe mentioned that some graphics cards may have some problems when using the gldepthmask function, but it may be because of my limited experience and I have not found such a situation.

So, let's demonstrate it. Let's draw some translucent and opaque sphere. Assume that there are three sphere, one with a red opacity, one with a green translucent, and one with a blue translucent. Red is the farthest, Green is in the middle, and blue is the closest. Based on the content described above, the red opaque sphere must be drawn first, while the green and blue aspects can be modified at will. To demonstrate the danger of not setting the depth buffer, we would like to draw the nearest blue sphere first, and then draw a green sphere.
We use light to make these sphere a little stereoscopic. Set a white light source at (1, 1,-1. The Code is as follows:
Void setlight (void)
{
Static const glfloat light_position [] = {1.0f, 1.0f,-1.0f, 1.0f };
Static const glfloat light_ambient [] = {0.2f, 0.2f, 0.2f, 1.0f };
Static const glfloat light_diffuse [] = {1.0f, 1.0f, 1.0f, 1.0f };
Static const glfloat light_specular [] = {1.0f, 1.0f, 1.0f, 1.0f };

Gllightfv (gl_light0, gl_position, light_position );
Gllightfv (gl_light0, gl_ambient, light_ambient );
Gllightfv (gl_light0, gl_diffuse, light_diffuse );
Gllightfv (gl_light0, gl_specular, light_specular );

Glable (gl_light0 );
Glable (gl_lighting );
Glenable (gl_depth_test );
}
The color of each sphere is different. So their materials are also different. Here we use a function to set the material.
Void setmatirial (const glfloat mat_diffuse [4], glfloat mat_shininess)
{
Static const glfloat mat_specular [] = {0.0f, 0.0f, 0.0f, 1.0f };
Static const glfloat mat_emission [] = {0.0f, 0.0f, 0.0f, 1.0f };

Glmaterialfv (gl_front, gl_ambient_and_diffuse, mat_diffuse );
Glmaterialfv (gl_front, gl_specular, mat_specular );
Glmaterialfv (gl_front, gl_emission, mat_emission );
Glmaterialf (gl_front, gl_shininess, mat_shininess );
}
With these two functions, we can write the entire program code based on the previous knowledge. Here we only show the part of the plot. You can complete the other part on your own.
Void mydisplay (void)
{
// Define some material colors
Const static glfloat red_color [] = {1.0f, 0.0f, 0.0f, 1.0f };
Const static glfloat green_color [] = {0.0f, 1.0f, 0.0f, 0.3333f };
Const static glfloat blue_color [] = {0.0f, 0.0f, 1.0f, 0.5f };

// Clear the screen
Glclear (gl_color_buffer_bit | gl_depth_buffer_bit );

// Start the mixing and set the mixing factor
Glable (gl_blend );
Glblendfunc (gl_src_alpha, gl_one_minus_src_alpha );

// Set the light source
Setlight ();

// With (0, 0, 0.5) as the center, draw an opaque red sphere with a radius of. 3 (farthest from the observer)
Setmatirial (red_color, 30.0 );
Glpushmatrix ();
Gltranslatef (0.0f, 0.0f, 0.5f );
Glusolidsphere (0.3, 30, 30 );
Glpopmatrix ();

// A translucent object is drawn below, so the depth buffer is set to read-only
Gldepthmask (gl_false );

// Centered on (0.2, 0,-0.5), draw a translucent blue sphere with a radius of. 2 (closest to the observer)
Setmatirial (blue_color, 30.0 );
Glpushmatrix ();
Gltranslatef (0.2f, 0.0f,-0.5f );
Glusolidsphere (0.2, 30, 30 );
Glpopmatrix ();

// In the center of (0.1, 0, 0), draw a translucent green sphere with a radius of. 15 (between the first two sphere)
Setmatirial (green_color, 30.0 );
Glpushmatrix ();
Gltranslatef (0.1, 0, 0 );
Glusolidsphere (0.15, 30, 30 );
Glpopmatrix ();

// Draws a translucent object and restores the depth buffer to a readable and writable format.
Gldepthmask (gl_true );

Gluswapbuffers ();
}

You can also delete the gldepthmask from the above two parts. The result shows that the recent blue ball is translucent, but it is a red ball directly behind it, the green ball in the middle is not correctly drawn.

Summary:
This course introduces the knowledge of OpenGL hybrid functions.
Mixing is to create a new color instead of directly overwriting the old color. Instead, the new color and the old color are computed to generate a new color. The new color is called the source color, and the old color is called the target color. In the traditional sense, the source color is multiplied by the source factor, the target color is multiplied by the target factor, and then added.
The source and target factors can be set. Different Source and target factors directly lead to different mixing results. Using the Alpha value of the source color as the source factor, using 1.0 minus the Alpha value of the source color as the target factor is a common method. At this time, the Alpha value of the source color is equivalent to "opacity. This feature allows you to draw some translucent objects.
The order of drawing is very important when mixing. Because the source color is to be drawn at the time of painting, the original color is the target color, so the first object to be drawn becomes the target color, and then drawn becomes the source color. The draw sequence should be clearly considered. The target color corresponds to the set target factor, and the source color corresponds to the set source factor.
In 3D mixing, not only the source and target factors, but also the depth buffer zone should be considered. You must first draw all opaque objects and then draw translucent objects. Before creating a translucent object, you must set the depth buffer to read-only. Otherwise, an image error may occur.

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.