The following content is sorted out from the OpenGL getting started tutorial ~~~~
View an image:
Two white sphere of the same size are drawn in the figure. The one on the right is without any illumination effect, and it looks like a two-dimensional disc with no stereoscopic feeling. The one on the left uses a simple illumination effect. We can easily think of it as a three-dimensional object through the illumination hierarchy.
The reason why the eyes see various objects is that the light directly or indirectly reaches the eyes from them. Humans are more responsive to changes in light intensity than to changes in color. Therefore, for humans, light is very much a manifestation of the three-dimensional sense of an object.
Establish Illumination Model
OpenGL uses this approximation when processing illumination: the illumination system is divided into three parts: light source, material and illumination environment.
The light source is the source of light, which can be the previously mentioned sun or lamp.
Material refers to the surface of various objects that receive light. Because how an object reflects light is determined only by the surface of the object (the refraction of light is not considered in OpenGL ), the material characteristics determine the characteristics of the light reflected by the object.
Lighting Environment refers to some additional parameters that will affect the final lighting screen. For example, after multiple reflections of some light, it is impossible to tell which light source it is sent from, specify an environment brightness parameter to bring the final image closer to the actual situation.
In physics, if light is injected into an ideal smooth plane, the light after reflection is quite regular (such reflection is called a mirror reflection ).
If light is injected into a rough, non-smooth plane, the light after reflection is messy (such reflection is called diffuse reflection ).
Objects in real life do not have absolute mirror reflection or diffuse reflection when reflecting light, but they can be seen as the superposition of these two kinds of reflection.
For the light emitted by the light source, you can set the light intensity after the mirror reflection and diffuse reflection respectively. For materials illuminated by light, you can also set the light intensity after the light passes through the mirror reflection and diffuse reflection respectively. These factors combine to form the final illumination effect.
Normal Vector
According to the light reflection Law, the light's outbound direction can be obtained from the Light's incident direction and the normal of the incident point.
Therefore, after a light source is specified for a specified object, the reflection direction of the light source can be calculated to calculate the image of the light source effect.
In OpenGL, the direction of the normal is expressed by a vector.
Unfortunately, OpenGL does not calculate the normal of each vertex on the surface of the object composed of these polygon based on the vertices of the polygon you specify (this sounds a bit confusing ), generally, to achieve illumination, You need to specify its normal vector for each vertex in the code.
The method of specifying the normal vector is similar to that of specifying the color. When specifying a color, you only need to specify the color of each vertex. OpenGL can calculate the color of other vertices on its own.
In addition, once the color is specified, unless a new color is specified, all vertices in the future will use this amount as their own color.
When specifying a normal vector, you only need to specify the normal vector of each vertex. OpenGL will calculate the normal vector of other points between the vertex.
In addition, once the normal vector is specified, unless a new normal vector is specified, all vertices specified in the future will use this constant amount as their own normal vector.
The glcolor * function can be used to specify the color, while the glnormal * function can be used to specify the normal vector.
Note: The gltranslate * function or glrotate * function can change the appearance of an object, but the normal vector does not change.
However, using the glscale * function to scale each coordinate axis to varying degrees may lead to incorrect normal vectors. Although OpenGL provides some measures to correct this problem, but it also brings about various expenses.
Therefore, when using a normal vector, try to avoid using the glscale * function. Even if used, it is best to ensure proportional scaling of each coordinate axis.
Control Light Source
In OpenGL, only a limited number of light sources are supported.
Use gl_light0 to represent the 0th light source, gl_light1 to represent the 1st light source, and so on.
OpenGL supports at least eight light sources, namely, gl_light0 to gl_light7.
You can enable these functions using the glenable function. For example, glable (gl_light0); can enable light source 0th.
You can use the gldisable function to disable the light source.
Some OpenGL implementations may support more light sources, but in general, enabling too many light sources will lead to a serious reduction in the program running speed. Some friends who have played 3D mark may also have some experience. In some scenarios, there may be hundreds of thousands of electric lights. In this case, some similar approaches may be required for programming. Otherwise, such a program cannot run on the current computer.
Each light source can be set with its properties. This action is completed using the gllight * function.
The gllight * function has three parameters. The first parameter indicates which light source is set, and the second parameter indicates which property is set for the light source, the third parameter specifies the value of the attribute. There are many attributes of the light source, which will be described below.
(1) gl_ambient, gl_diffuse, and gl_specular attributes.
These three attributes indicate the reflection (and color) of the light emitted by the light source ).
Each attribute is represented by four values, representing the R, G, B, And A values of the color respectively.
Gl_ambient indicates the light emitted by the light source. After many reflections, the light intensity (color) remains in the entire illumination environment ).
Gl_diffuse indicates the light emitted by the light source. The light intensity (color) is obtained by diffuse reflection when the light source is exposed to a rough surface)
Gl_specular indicates the intensity (color) of the light emitted by the light source, which is reflected by a mirror when it is shining on a smooth surface ).
(2) gl_position attribute.
The position of the light source.
It is represented by four values (X, Y, Z, W.
If the fourth value of w is zero, it indicates that the light source is in an infinite distance, and the first three values indicate the direction of the light source.
This type of light source is called a directional light source. Generally, the sun can be considered as a directional light source.
If the fourth value W is not zero, X/W, Y/W, Z/W represent the position of the light source.
This type of light source is called a positional light source. For positional light sources, the method for setting their positions is similar to that for setting polygon vertices. Various matrix transformation functions such as gltranslate * And glrotate * are also effective here.
The direction light source is much faster than the position light source in computing. Therefore, the direction light source should be used as much as possible when the visual effect permits.
(3) gl_spot_direction, gl_spot_exponent, and gl_spot_cutoff attributes.
Indicates that a light source is used as a spotlight (these properties are only valid for a positional light source ). Many light sources emit light in all directions, but sometimes some light sources only emit light in a certain direction. For example, a flashlight only emits light at a small angle.
The gl_spot_direction attribute has three values, indicating a vector, that is, the direction of light source emission.
The gl_spot_exponent attribute has only one value, indicating the degree of concentration. If it is set to zero, it indicates that the intensity of light emitted to each direction is the same. If it is a positive value, it indicates that the light is centralized to the center, it is receiving more light from the position in the direction of transmission, and less light from other locations. The larger the value, the more obvious the concentration effect.
The gl_spot_cutoff attribute has only one value, indicating an angle. It is half of the angle covered by the light source light emitting light (see figure). Its value ranges from 0 to 90, you can also take the special value 180. When the value is 180, it indicates that the light source emits 360 degrees of light, that is, the spotlight is not used and the light is sent to the entire surrounding area.
(4) gl_constant_attenuation, gl_linear_attenuation, and gl_quadratic_attenuation attributes.
These three properties represent the linear propagation of light emitted by a light source (these properties are only valid for a positional light source ).
In real life, the intensity of light decreases with the increase of distance. OpenGL abstracts this weakening trend into a function:
Attenuation Factor = 1/(K1 + K2 * D + K3 * K3 * D)
D indicates the distance, and the initial intensity of the light is multiplied by the attenuation factor to obtain the light intensity of the corresponding distance.
K1, K2, and K3 are gl_constant_attenuation, gl_linear_attenuation, and gl_quadratic_attenuation.
By setting these three constants, we can control the weakening trend of light in the propagation process.
There are still a lot of attributes. Of course, if you use a directional light source, (3) (4) These two types of attributes will not be used, and the problem will become simple and clear.
Control Material
Materials are similar to light sources, and many attributes need to be set. The difference is that the light source is set through the gllight * function, while the material is set through the glmaterial * function.
The glmaterial * function has three parameters. The first parameter indicates the attribute of the specified side. It can be gl_front, gl_back, or gl_front_and_back. The material of the front, back, or both sides are set.
The second and third parameters are similar to the second and third parameters of the gllight * function.
The following describes the material attributes that can be specified by the glmaterial * function.
(1) gl_ambient, gl_diffuse, and gl_specular attributes.
These three attributes are similar to the three corresponding properties of the light source. Each attribute is composed of four values.
Gl_ambient indicates the light intensity (color) that is left in the environment after many reflections ).
Gl_diffuse indicates the light intensity (color) formed by diffuse reflection when the light is shining on the material ).
Gl_specular indicates the light intensity (color) formed after the light is reflected on the mirror ).
Generally, gl_ambient and gl_diffuse take the same value to achieve a more realistic effect.
You can use gl_ambient_and_diffuse to set the gl_ambient and gl_diffuse attributes at the same time.
(2) gl_shininess attribute.
This attribute has only one value, called the "mirror Index". The value range is 0 to 128.
The smaller the value, the rougher the material, and the light emitted by the point light source can also generate a large highlight. The larger the value, the more similar the material to the mirror, the light source after irradiation to the above, produce a small highlight.
(3) gl_emission attribute. This attribute is composed of four values, indicating a color. OpenGL believes that the material itself emits light slightly outward, so that the eyes feel that it has such a color, but the light is so weak that it will not affect the color of other objects.
(4) gl_color_indexes attribute.
This attribute is only used in the color index mode. Because the illumination in the color index mode is more complex than that in the rgba mode, and the usage range is small, we will not discuss it here.
Select Illumination Model
The "Illumination Model" mentioned here is the term of OpenGL, which is equivalent to the "illumination environment" we mentioned earlier ".
In OpenGL, the illumination model consists of four parts:
The intensity,
Whether to calculate the illumination,
Whether the calculation of the mirror color (the color specified by the gl_specular attribute) is separated from other illumination calculations and applied after the texture operation.
The above four aspects are all set through the same function gllightmodel.
This function has two parameters: the first parameter indicates the project to be set and the second parameter indicates the value to be set.
Gl_light_model_ambient indicates the global ambient light intensity, which consists of four values.
Gl_light_model_local_viewer indicates whether to watch in the near future. If so, it is set to gl_true; otherwise (that is, watching in the infinite distance) it is set to gl_false.
Gl_light_model_two_side indicates whether to perform double-sided illumination calculation. If it is set to gl_true, OpenGL will not only calculate the front illumination based on the normal vector, but also reverse the normal vector and calculate the back illumination.
Gl_light_model_color_control indicates the color calculation method.
If it is set to gl_single_color, the operation is performed in the normal order. The illumination is calculated first, and then the texture is calculated.
If it is set to gl_separate_specular_color, The gl_specular attribute is separated. The rest of the illumination is calculated first, and gl_specular is calculated after the texture operation is complete.
The latter can usually make the image more realistic (of course, if you do not perform any texture operations, such separation does not make any sense ).
OpenGL disables illumination by default. To enable the light processing function, use the following statement:
Glable (gl_lighting );
To disable the light processing function, use gldisable (gl_lighting.
Code:
# Include <Gl/glut. h> # define width 400 # define height 400 static glfloat angle = 0.0f; void mydisplay (void) {glclear (gl_color_buffer_bit | gl_depth_buffer_bit ); // clear color and depth buffering // create a perspective effect view glmatrixmode (gl_projection); // operate glloadidentity () on the projection matrix; // move the coordinate origin to the center gluperspective (90.0f, 1.0f, 1.0f, 202.16f); // you can specify the glmatrixmode (gl_modelview) of the Perspective Projection Matrix. // you can specify glloadidentity () for the model visual matrix. glulookat (0.0, 5.0,-10.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0); // viewpoint conversion // defines the solar light source, which is a white light source {glfloat sun_light_position [] = {0.0f, 0.0f, 0.0f, 1.0f }; glfloat labels [] = {0.0f, 0.0f, 0.0f, 1.0f}; glfloat sun_light_diffuse [] = {1.0f, 1.0f, 1.0f, 1.0f}; glfloat sun_light_specular [] = {1.0f, 1.0f, 1.0f, 1.0f}; gllightfv (gl_light0, gl_position, sun_light_position); // specify the position of The 0th light source gllightfv (gl_light0, gl_ambient, sun_light_ambient ); // gl_ambient indicates that various light rays are shining on this material, // After many reflections, the light intensity (color) gllightfv (gl_light0, gl_diffuse, sun_light_diffuse) in the environment is finally left behind. // After the reflection, the light intensity (color) gllightfv (gl_light0, gl_diffuse, sun_light_diff ~~ Gllightfv (gl_light0, gl_specular, sun_light_specular); // After mirror reflection ~~~ Glenable (gl_light0); // use gl_lighting (gl_lighting) with no. 0th; // use gl_depth_test in subsequent rendering; // This sentence is to enable deep testing, in this way, the objects behind the house will be blocked. For example, if there is a tree behind the house, if you do not enable the deep test, // If you first draw a house and then draw a tree, the tree will cover the house; however, no matter how you draw a tree after enabling the deep test, the tree must be behind the house (blocked by the House)} // define the sun material and draw the sun {glfloat sun_mat_ambient [] = {0.0f, 0.0f, 0.0f, 1.0f}; glfloat sun_mat_diffuse [] = {0.0f, 0.0f, 0.0f, 1.0f}; glfloat sun_mat_specular [] = {0.0f, 0.0f, 0.0f, 1.0f }; glfloat sun_mat_emission [] = {0.5f, 0.0f, 0.0f, 1.0f}; glfloat reverse = 0.0f; glmaterialfv (gl_front, gl_ambient, callback); // define the front of the material using "multiple reflections" glmaterialfv (gl_front, gl_diffuse, sun_mat_diffuse); // The front of the material is the diffuse reflection glmaterialfv (gl_front, gl_specular, sun_mat_specular); // The front of the definition material is the mirror reflection glmaterialfv ); // define the front of the material as the mirror index glmaterialf (gl_front, gl_shininess, sun_mat_shininess); // color g used before the material Lutsolidsphere (2.0, 40, 32);} // defines the material of the earth and draws the earth {glfloat earth_mat_ambient [] = {0.0f, 0.0f, 0.5f, 1.0f }; glfloat functions [] = {0.0f, 0.0f, 0.5f, 1.0f}; glfloat earth_mat_specular [] = {0.0f, 0.0f, 1.0f, 1.0f}; glfloat functions [] = {0.0f, 0.0f, 0.0f, 1.0f}; glfloat earth_mat_shininess = 30366f; glmaterialfv (gl_front, gl_ambient, earth_mat_ambient); glmaterialfv (gl_front, gl_diffuse, earth_ma T_diffuse); glmaterialfv (gl_front, gl_specular, lens); glmaterialfv (gl_front, lens, lens); lens (gl_front, gl_shininess, lens); glrotatef (angle, 0.0f,-1.0f, 0.0f); gltranslatef (5.0f, 0.0f, 0.0f); // if you use the glusolidsphere function to draw a sphere, the function automatically specifies these normal vectors. // you do not have to manually specify them. If you specify a number of vertices to draw a sphere, You need to specify the normal vector. Glusolidsphere (2.0, 40, 32);} maid (); // swap buffer} void myidle (void) {angle + = 1.0f; If (angle> = 360.0f) angle = 0.0f; mydisplay ();} int main (INT argc, char * argv []) {gluinit (& argc, argv); gluinitdisplaymode (glu_rgba | glu_double ); gluinitwindowposition (200,200); gluinitwindowsize (width, height); glucreatewindow ("OpenGL light Demo"); gludisplayfunc (& mydisplay); glutidlefunc (& myidle); glumainloop (); return 0 ;}
Result: