Lighting and keyboard control:
In this lesson, we will add lighting and keyboard control to make the program look more beautiful.
This lesson will teach you how to use three different texture filtering methods. It also teaches you how to use a keyboard to move objects in a scenario and how to use simple light in an OpenGL scenario. This course contains a lot of content. If you have any questions about the previous course, first review it. Before entering the code below, it is very important to have a good understanding of the basic knowledge.
We still modify the code in Lesson 1. Unlike the previous one, I will write the entire code segment as long as there are any major changes. At the beginning of the program, we add several new variables.
The following lines are new. We add three Boolean variables. Light Variable to track whether the light is on. The LP and FP variables are used to store whether the 'l' and 'F' keys are pressed. I will explain the importance of these variables later. Now, put it aside.
Bool light; // the on/off bool LP of the light source; // is the L key pressed? Bool FP; // is the F key pressed?
Now, set five variables to control the step size of the rotation angle around the X and Y axes, as well as the rotation speed around the X and Y axes. In addition, a Z variable is created to control the distance to the depth of the screen.
Glfloat xrot; // X rotating glfloat yrot; // y rotating glfloat xspeed; // X rotating speed glfloat yspeed; // y rotating speed glfloat Z =-5.0f; // The distance from the deep Screen
Set the array used to create the light source. We will use two different types of light. The first type is environmental light. The environment comes from all directions. Objects in all scenarios are under ambient light. The second type of light source is diffuse light. Diffuse Light is produced by a specific light source and reflected on the surface of an object in your scenario. The surface of any object that is directly illuminated by diffuse light becomes brighter, and the area that is almost invisible is darker. In this way, the edge of the wooden board box we created will produce a very good shadow effect.
The process of creating a light source is exactly the same as that of creating a color source. The first three parameters are RGB three-color components, and the last one is the alpha channel parameter.
Therefore, what we get from the following code is the white ambient light of the semi-bright (0.5f. If there is no ambient light, the area where the light is not diffuse will become very dark.
Glfloat lightambient [] = {0.5f, 0.5f, 0.5f, 1.0f}; // ambient light Parameters
The next line of code generates the brightest diffuse light. All parameter values are obtained as the maximum value 1.0f. It will shine in front of our wooden panel and looks good.
Glfloat lightdiffuse [] = {1.0f, 1.0f, 1.0f, 1.0f}; // diffuse light Parameter
Finally, we save the position of the light source. The first three parameters are the same as those in gltranslate. They are the displacement on the XYZ axis in turn. Since we want the light to shine directly on the front of the wooden box, the displacement on the XY axis is 0.0f. The third value is the displacement on the Z axis. To ensure that the light is always in front of the wooden box, we place the light source toward the observer (that is where you are .) Remove the screen. We usually call the position of the Screen Glass, that is, the 0.0f point of the Z axis. So the displacement on the Z axis is finally set to 2.0f. If you can see the light source, it will float in front of your monitor. Of course, if the wooden box is not behind the screen glass of the monitor, you will not be able to see the box. Note: I really appreciate the patience of nehe. To be honest, sometimes I get bored. Why is it that simple? But if everything is clear, will you still go through such a page to see it ?』
The last parameter is 1.0f. This will tell OpenGL that the coordinates specified here are the position of the light source. I will explain more in the future.
Glfloat lightposition [] = {0.0f, 0.0f, 2.0f, 1.0f}; // Light Source Position
The texture type used when the filter variable is tracked and displayed. The first texture (texture 0) is constructed using gl_nearest (not smooth) filtering. The second texture (texture 1) uses gl_linear (linear filtering) to make the image closer to the screen smooth. The third texture (texture 2) uses the mipmapped filtering method, which creates a texture with excellent appearance. Based on our usage type, the values of the filter variables are equal to 0, 1, or 2. Next we start with the first texture.
Gluint texture [3] allocates storage space for three different textures. They are located in texture [0], texture [1], and texture [2] respectively.
Gluint filter; // storage space of the filter type gluint texture [3]; // three textures
Now load a bitmap and use it to create three different textures. This course uses the Glaux auxiliary library to load bitmap, so you should check whether the Glaux library is included during compilation. I know that both Delphi and VC ++ contain the Glaux library, but other languages cannot be guaranteed. Note: Glaux is an OpenGL auxiliary library. According to the cross-platform features of OpenGL, Code on all platforms should be universal. However, the auxiliary library is not a formal OpenGL standard library and does not appear on all platforms. But it is available on the Win32 platform. Of course, BCB is okay .』 Here I only annotate the newly added code. If you have any questions about a line of code, please refer to tutorial 6. That lesson explains in detail how to load and create textures.
The following code is added after the previous Code and before resizeglscene. This is almost the same as the code for loading bitmap in Lesson 6.
This Code calls the previous code to load the bitmap and convert it into three textures. The status variable tracks whether the texture is loaded and created.
Int loadgltextures () // load the bitmap and convert it to the texture {int status = false; // Status Indicator aux_rgbimagerec * textureimage [1]; // create a texture storage space memset (textureimage, 0, sizeof (void *) * 1); // set the pointer to null
Now load the bitmap and convert it to a texture. Textureimage [0] = loadbmp ("Data/crate.bmp") calls our loadbmp () function. The crate.bmp file in the datafile will be loaded. If everything works, the image data is stored in textureimage [0]. The status variable is set to true. We will start to create the texture.
// Load the bitmap. If the check is incorrect or the bitmap does not exist, exit if (textureimage [0] = loadbmp ("Data/crate.bmp") {status = true; // The status is set to true.
Now we have loaded image data into textureimage [0]. We will use it to create three textures. The following lines tell OpenGL that we want to create three textures, which will be stored in texture [0], texture [1], and texture [2.
Glgentextures (3, & texture [0]); // create a texture
In Lesson 6, we use linear filtered texture maps. This requires machines with high processing capabilities, but they look good. In this lesson, we will create the first texture using the gl_nearest method. In principle, this method does not actually implement filtering. It only occupies a small amount of processing capability and looks very bad. The only benefit is that our project can run normally on both very fast and very slow machines.
You will notice that gl_nearest is used in both Min and Mag. You can use gl_nearest and gl_linear together. Texture looks better, but we are more concerned about speed, so we use low quality textures. Min_filter is used when the image is drawn less than the original size of the texture. Mag_filter is used when the image is drawn much larger than the original size of the texture.
// Create the nearest filter texture glbindtexture (gradient, texture [0]); gltexparameteri (gradient, gradient, gl_nearest); gltexparameteri (gradient, gradient, gl_nearest); glteximage2d (cost, 0, 3. textureimage [0]-> sizex, textureimage [0]-> sizey, 0, gl_rgb, gl_unsigned_byte, textureimage [0]-> data );
The next texture we build is the same type of texture we used in tutorial six. linear filtered. the only thing that has changed is that we are storing this texture in texture [1] instead of texture [0] because it's our second texture. if we stored it in texture [0] Like above, it wocould overwrite the gl_nearest texture (the first texture ).
// Create glbindtexture (linear, texture [1]); gltexparameteri (linear, linear, gl_linear); gltexparameteri (gl_texture_2d, linear, gl_linear); glteximage2d (linear, 0, 3. textureimage [0]-> sizex, textureimage [0]-> sizey, 0, gl_rgb, gl_unsigned_byte, textureimage [0]-> data );
The following is a new method for creating a texture. Mipmapping! "NOTE: I cannot translate the Chinese character of this word, but it does not matter. After reading this section, you will know the meaning is the most important .』 You may notice that when the image becomes small on the screen, many details will be lost. The pattern that was pretty good just now has become very ugly. After you tell OpenGL to create a mipmapped texture, OpenGL will try to create high-quality textures of different sizes. When you draw a mipmapped texture to the screen, OpenGL will select the best texture (with more details) it has created to draw, instead of simply scaling the original image (this will cause loss of details ).
I once said that there is a way to bypass OpenGL's limitations on Texture width and height-64, 128, 256, and so on. The solution is glubuild2dmipmaps. According to my findings, you can use any bitmap to create a texture. OpenGL automatically scales it to a normal size.
Because it is the third texture, we store it in texture [2]. In this case, all three textures are created.
// Create the mipmapped texture glbindtexture (gl_texture_2d, texture [2]); gltexparameteri (gl_texture_2d, callback, gl_linear); gltexparameteri (gl_texture_2d, callback, callback );
The following line generates the mipmapped texture. We use three colors (red, green, and blue) to generate a 2D texture. Textureimage [0]-> sizex is the bitmap width, and extureimage [0]-> sizey is the bitmap height. gl_rgb means that RGB colors are used in sequence. Gl_unsigned_byte indicates that the unit of texture data is byte. Textureimage [0]-> data points to the bitmap used for texture creation.
gluBuild2DMipmaps(GL_TEXTURE_2D, 3, TextureImage[0]->sizeX, TextureImage[0]->sizeY, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[0]->data); }
Now, the memory used to store bitmap data is released. First, check whether the bitmap data is stored in textureimage [0]. If yes, delete it. Then release the bitmap structure to ensure that the memory is released.
If (textureimage [0]) // whether the texture exists {If (textureimage [0]-> data) // check whether the texture image exists {free (textureimage [0]-> data); // release the memory occupied by the texture image} Free (textureimage [0]); // release the image structure}
Finally, the status variable is returned. If everything is OK, the value of the status variable is true. Otherwise, the value is false.
Return status; // return the status variable}
Next we should load the texture and initialize the OpenGL settings. The first line of the initgl function uses the above Code to load the texture. After creating the texture, we call
Glenable (gl_texture_2d) enables 2D Texture ing. The shadow mode is set to smooth shading ). The background color is set to black. We enable deep testing and then enable optimized perspective computing.
Set the light source. The following line sets the ambient light volume. The light source starts to emit light at light1. At the beginning of this lesson, we stored the ambient light in the lightambient array. Now we use this array (half-brightness ambient light ). Add the following code to the int initgl (glvoid) function.
Gllightfv (gl_light1, gl_ambient, lightambient); // sets the ambient light.
Next, we will set the light volume of the diffuse light. It is stored in the lightdiffuse array (white light with full brightness ).
Gllightfv (gl_light1, gl_diffuse, lightdiffuse); // sets the diffuse light.
Set the position of the light source. Location is stored in the lightposition array (right in the center of the front of the wooden box, X-0.0f, Y-0.0f, z direction to the observer 2 units <located outside the screen> ).
Gllightfv (gl_light1, gl_position, lightposition); // you can specify the position of the light source.
Finally, we enable the No. 1 light source. We have not enabled gl_lighting, so you cannot see any light. Remember: Only setting, locating, or even enabling the light source will not work. Unless we enable gl_lighting.
Glable (gl_light1); // enable light source 1
Lesson 07th OpenGL lighting and keyboard (1)