Nehe OpenGL tutorial (9)

Source: Internet
Author: User

Lesson 1

Moving Images in 3D space:

You want to know how to move objects in 3D space, how to draw an image on the screen, and make the background color transparent, you want to have a simple animation. This lesson will teach you everything. The previous course covers the basic OpenGL, and each course is created on the basis of the previous lesson. This course is a combination of the previous knowledge. When you are studying this lesson, make sure that you have mastered the previous knowledge.

Welcome to Lesson 9. So far, you should have a good understanding of OpenGL. "Cker: if not, it must be the sin of my translation ......』. You have learned how to set every detail of an OpenGL window. Learn to map and place light and mix colors (transparency) on Rotated objects. This course should be regarded as the first intermediate course. You will learn the following knowledge: Move the bitmap in 3D scenarios and remove the black pixels on the bitmap (using mixed colors ). Next, color the black and white textures. Finally, you will learn to create rich colors and mix the textures of different colors to get a simple animation effect.
We modify the code based on the first lesson. Add several variables at the beginning of the program source code. For clarity, I have rewritten the entire code segment.

# Include <stdio. h> // standard input/output library header file
# Include <Glaux. h> // header file of the Glaux Library

The following lines are newly added. Twinkle and TP are Boolean variables, indicating that they can only be set to true or false. Twinkle is used to track whether the flickering effect is enabled. TP is used to check whether the 'T' key is pressed or released. (TP = true when pressed, TP = false when released ).

Bool twinkle; // the twinkling stars
Bool TP; // isn't it pressed?

Num tracks the number of stars drawn on the screen. This number is defined as a constant. This means that it cannot be modified in future code. This is because you cannot redefine an array. Therefore, if we define an array of 50 stars and then increase num to 51, the error "cker: array out of bounds" will occur 』. However, you can (or only) modify the number on this line at will. However, do not change the num value later unless you want to see a disaster.

Const num = 50; // number of stars drawn
 
Create a structure. The word structure sounds a little scary, but not actually. A structure uses a set of simple types of data (and variables) to express a large combination of similar data. We know that we are keeping track of the stars. You can see that the seventh row below is stars, and each star has three integer color values. The third row contains three integers: int R, G, and B. A red (R), a green (G), and a blue (B ). in addition, each star is different from the center of the screen, and can be an angle of any 360 degrees from the center of the screen. If you look at the fourth row below, we will find that we use a floating point number called DIST to keep track of the distance. the fifth line uses a floating point number called angle to keep track of the angle value of the stars.
Therefore, we use a set of data to describe the color, distance, and angle of the stars on the screen. Unfortunately, we track more than one star. However, you only need to create an array star instead of creating 50 red values, 50 green values, 50 Blue values, 50 distance values, and 50 angle values. Each element of the star array is of the stars type, which stores all the data describing the stars. The star array is created in the eighth row below. The eighth line looks like this: Stars star [num]. The array type is stars structure. The array can store information of all stars structures. The array name is star. The array size is [num]. Elements in the stars structure are stored in the array. the trace structure elements are much easier than the variables separated by the tracing. however, this is also very stupid, because we cannot change the constant num to increase or decrease the number of stars.

Typedef struct // create a structure for the stars
{
Int R, G, B; // star color
Glfloat Dist; // distance from the stars to the center
Glfloat angle; // The angle of the current star
}
Stars; // The structure is named stars.
Stars star [num]; // use the 'stars' structure to generate a 'star' array containing 'num' Elements

Next we will set several tracking variables: the distance variable between the stars and the observer (zoom), the angle of the stars we see (tilt ), and the variable spin that allows the flickering stars to rotate around the Z axis.
The loop variable is used to draw 50 stars. Texture [1] is used to store a black-and-white texture. If you need more textures, you should increase the size of the texture array to the number of textures you decide to use.

Glfloat zoom =-15.0f; // distance between the stars and the observer
Glfloat tilt = 90.0f; // star dip
Glfloat spin; // the rotation of the flickering stars

Gluint loop; // global Loop Variable
Gluint texture [1]; // stores a texture

The above code is the code we use to load the texture. I don't want to explain this code in detail. This is exactly the same as the code we used in Lesson 6, 7, and 8. The uploaded map is star.bmp. Here we use glgentextures (1, & texture [0]) to generate a texture. The texture is linearly filtered.

Aux_rgbimagerec * loadbmp (char * filename) // load the bitmap file
{
File * file = NULL; // file handle

If (! Filename) // confirm that the file name has been given
{
Return NULL; // if no value is returned, null is returned.
}

File = fopen (filename, "R"); // check whether the file exists

If (File) // does the file exist?
{
Fclose (File); // close the file handle
Return auxdibimageload (filename); // load the bitmap and return the pointer
}
Return NULL; // If loading fails, null is returned.
}

The following code (call the code above) loads the bitmap and converts it to a texture. The variable is used to track whether the texture has been loaded and created.

Int loadgltextures () // load bitmap and convert it to texture
{
Int status = false; // Status Indicator

Aux_rgbimagerec * textureimage [1]; // allocate storage space for textures

Memset (textureimage, 0, sizeof (void *) * 1); // set the pointer to null

// Load the bitmap. Check the error. Exit if the bitmap file is not found.
If (textureimage [0] = loadbmp ("Data/star.bmp "))
{
Status = true; // set status to true

Glgentextures (1, & texture [0]); // create a texture

// Create a linear filter texture
Glbindtexture (gl_texture_2d, texture [0]);
Gltexparameteri (gl_texture_2d, gl_texture_mag_filter, gl_linear );
Gltexparameteri (gl_texture_2d, gl_texture_min_filter, gl_linear );
Glteximage2d (gl_texture_2d, 0, 3, textureimage [0]-> sizex, textureimage [0]-> sizey, 0, gl_rgb, gl_unsigned_byte, textureimage [0]-> data );
}

If (textureimage [0]) // If the texture exists
{
If (textureimage [0]-> data) // If the texture image exists
{
Free (textureimage [0]-> data); // release the memory occupied by the texture image
}

Free (textureimage [0]); // release the image structure
}

Return status; // return the value of status.
}


Now set the OpenGL rendering method. Here we do not plan to use deep testing. If you use the code in Lesson 1, check whether gldepthfunc (gl_lequal); and glable (gl_depth_test); are removed. Otherwise, the effect you see will be messy. Texture ing is used here, so make sure you have added the code that is not included in the first lesson. You will notice that we have enabled texture ing through blending.

Int initgl (glvoid) // All OpenGL settings are started here
{
If (! Loadgltextures () // call the texture loading subroutine
{
Return false; // If loading fails, false is returned.
}

Glable (gl_texture_2d); // enable texture ing
Glshademodel (gl_smooth); // enables shadow smoothing.
Glclearcolor (0.0f, 0.0f, 0.0f, 0.5f); // black background
Glcleardepth (1.0f); // sets the depth cache.
Glhint (gl_perspective_correction_hint, gl_nicest); // truly fine-grained perspective correction
Glblendfunc (gl_src_alpha, gl_one); // sets the color mixing function to achieve translucent effect.
Glable (gl_blend); // enable mixed colors

The following is the new code. Set the start angle, distance, and color of each star. You will notice how easy it is to modify the structure attributes. All 50 stars are cyclically set. All we need to do to change the angle of star [1] is star [1]. angle = {A value}; that's that simple!

For (loop = 0; loop <num; loop ++) // create a loop to set all stars
{
Star [loop]. angle = 0.0f; // all stars start from the zero angle.

The distance between the second loop stars and the center is to divide the value of the loop by the total number of stars, and then multiply the value by 5.0f. Basically, this makes the next star a little farther away from the center than the previous one. In this way, when the loop is 50 (the last star), the loop divided by num is exactly 1.0f. Multiply by 5.0f because 1.0f * 5.0f is 5.0f. 「 Cker: Nonsense! How is this foreigner like Kong Yiji! :) "5.0f is very close to the screen edge. I don't want stars to fly out of the screen. 5.0f is the best choice. Of course, if you set the scene to more in-depth on the screen, you may be able to use a value greater than 5.0f, but the stars look smaller (because of perspective ).
You will also notice that the color of each star ranges from 0 ~ A random number between 255. You may wonder why the color value range here is not OpenGL's usual 0.0f ~ Between 1.0f. The color setting function we use here is glcolor4ub, rather than the previous glcolor4f. UB indicates that the parameter is of the unsigned byte type. The value range of a byte is 0 ~ 255. Here, using the byte value to obtain a random integer seems easier than taking a random number at a floating point.

Star [loop]. Dist = (float (loop)/num) * 5.0f; // calculates the distance between the stars and the center.
Star [loop]. r = rand () % 256; // set random red weight for star [loop]
Star [loop]. G = rand () % 256; // set random red weight for star [loop]
Star [loop]. B = rand () % 256; // set random red weight for star [loop]
}
Return true; // initialize everything OK
}

The code for Resize is also the same. Now we transfer the drawing code. If you use the code of Lesson 1 and delete the old drawglscene code, just copy the following code. In fact, there are only two lines of code in the first lesson, so there is not much to delete.

Int drawglscene (glvoid) // This process includes all the drawing code
{
Glclear (gl_color_buffer_bit | gl_depth_buffer_bit); // clear the screen and depth Cache
Glbindtexture (gl_texture_2d, texture [0]); // select the texture

For (loop = 0; loop <num; loop ++) // cyclically set all stars
{
Glloadidentity (); // reset the model observation matrix before drawing each star.
Gltranslatef (0.0f, 0.0f, zoom); // go deep into the screen
Glrotatef (tilt, 1.0f, 0.0f, 0.0f); // skewed Angle of View

Now let's move the stars. The stars start at the center of the screen. The first thing we need to do is to rotate the scene along the Y axis. If we rotate 90 degrees, the x-axis is no longer from left to right, and it will go inside and out of the screen. For example. Suppose you are standing in the middle of the house. Suppose the wall on the left is "-X", the wall on the front is "-z", and the wall on the right is "+ X". The wall on the back is "+ z. Add the entire house and turn right 90 degrees, but you are not moving, then the front wall will be-X instead of-Z. All other walls also move. -Z appears on the right, + z appears on the left, and + x appears on your back. Nervous system disorder? Through the rotation scenario, we changed the direction of x and zplane.
The second line of code moves a positive value along the X axis. Usually, the positive value on the X axis represents moving to the right side of the screen (that is, the normal positive value on the X axis), but because we rotate the coordinate system around the Y axis, the positive value of the X axis can be any direction. If we turn to 180 degrees, the image is reversed on the left and right of the screen. Therefore, when we move forward along the X axis, it may be left, right, forward or backward.

Glrotatef (Star [loop]. angle, 0.0f, 1.0f, 0.0f); // rotate to the angle of the currently painted star
Gltranslatef (Star [loop]. Dist, 0.0f, 0.0f); // move forward along the X axis

The subsequent code has some tips. A star is actually a plane texture. Now you have drawn a quadrilateral in the center of the screen and attached the texture, which looks good. Everything is as you think. However, when you convert the texture along the Y axis to 90 degrees, there are only two sides on the right and left to you on the screen. It looks like a thin line. This is not what we want. We want the stars to always face us, regardless of how the screen is rotated or skewed.
We achieve this by offsetting any rotation of the stars before drawing them. You can use reverse order to offset the rotation. When we tilt the screen, we actually rotate the stars from the current angle. Through Reverse Order, We "reverse rotate" the stars from the current angle. It is to rotate the stars with the negative value of the current angle. That is to say, if we rotate the stars for 10 degrees, we rotate them for another 10 degrees so that the stars can face the screen again on that axis. The first line below offsets the Rotation along the Y axis. Then, we also need to offset the screen skew along the X axis. To do this, we only need to rotate the screen-tilt. After the rotation of X and Y axes is offset, the stars face us completely.

Glrotatef (-star [loop]. angle, 0.0f, 1.0f, 0.0f); // cancel the angle of the current star
Glrotatef (-tilt, 1.0f, 0.0f, 0.0f); // cancel screen skew

If twinkle is true, first draw a non-rotating star on the screen: subtract the total number of stars (Num) from the current number of Stars (loop) And then subtract 1, to extract the different colors of each star (this is because the cycle ranges from 0 to num-1 ). For example, when the result is 10, we use the color of star 10. In this way, the colors of adjacent stars are always different. This is not a good method, but it is very effective. The last value is the alpha channel component. The smaller the value, the darker the star.
Because twinkle is enabled, each star is finally drawn twice. The program runs slowly, depending on the performance of your machine. However, the colors of the stars that are drawn twice are combined to produce great results. At the same time, because the first time the stars are not rotated, the stars after twinkle is enabled seem to have an animation effect. (If you cannot understand it here, check the running effect of the program .)
It is worth noting that it is easy to color textures. Although the texture itself is black and white, the texture will become any color we choose before drawing it. In addition, it is worth noting that the color value we use here is byte type, rather than the usual floating point number. This is even true for alpha-channel components.

If (Twinkle) // enable the flickering Effect
{
// Specify a color using a byte value
Glcolor4ub (Star [(Num-loop)-1]. r, star [(Num-loop)-1]. g, star [(Num-loop)-1]. (B, 255 );
Glbegin (gl_quads); // starts to draw the Quadrilateral mapped to the texture.
Gltexcoord2f (0.0f, 0.0f); glvertex3f (-1.0f,-1.0f, 0.0f );
Gltexcoord2f (1.0f, 0.0f); glvertex3f (1.0f,-1.0f, 0.0f );
Gltexcoord2f (1.0f, 1.0f); glvertex3f (1.0f, 1.0f, 0.0f );
Gltexcoord2f (0.0f, 1.0f); glvertex3f (-1.0f, 1.0f, 0.0f );
Glend (); // The End Of The quadrilateral plot.
}

Now draw the second time of the stars. The only difference from the previous Code is that the stars will be drawn this time, and the stars will rotate around the Z axis this time.

Glrotatef (spin, 0.0f, 0.0f, 1.0f); // rotate the stars around the Z axis
// Specify a color using a byte value
Glcolor4ub (Star [loop]. R, star [loop]. G, star [loop]. B, 255 );
Glbegin (gl_quads); // starts to draw the Quadrilateral mapped to the texture.
Gltexcoord2f (0.0f, 0.0f); glvertex3f (-1.0f,-1.0f, 0.0f );
Gltexcoord2f (1.0f, 0.0f); glvertex3f (1.0f,-1.0f, 0.0f );
Gltexcoord2f (1.0f, 1.0f); glvertex3f (1.0f, 1.0f, 0.0f );
Gltexcoord2f (0.0f, 1.0f); glvertex3f (-1.0f, 1.0f, 0.0f );
Glend (); // The End Of The quadrilateral plot.

The following code represents the movements of stars. We increase the spin value to rotate all the stars (in public rotation ). Then, the rotation angle of each star is increased by loop/num. This allows the stars farther away from the center to become faster. At last, the distance between each star and the center of the screen is reduced. In this way, the stars seem to be constantly sucked into the center of the screen.

Spin + = 0.01f; // public rotation of the stars
Star [loop]. Angle + = float (loop)/num; // you can change the Rotation Angle of a star.
Star [loop]. dist-= 0.01f; // Changes the distance between the stars and the center.


Then, check several rows to see if the stars have touched the center of the screen. When a star hits the center of the screen, we assign it a new color and then move 5 units away. The star will embark on its journey to return to the center of the screen.

If (Star [loop]. Dist <0.0f) // does the star arrive at the center?
{
Star [loop]. Dist + = 5.0f; // move 5 units out
Star [loop]. r = rand () % 256; // assign a new red weight
Star [loop]. G = rand () % 256; // assign a new green weight
Star [loop]. B = rand () % 256; // assign a new blue weight
}
}
Return true; // everything is normal
}

Now let's add the monitoring keyboard code. Move down to winmain (). Find a row of swapbuffers (HDC. We will add the keyboard monitoring code behind this line.
The code checks whether the T key is pressed. If the T key is pressed and released again, the code in the IF block will be executed. If twinkle is set to false, it is set to true. And vice versa. As long as the T key is pressed, TP becomes true. This prevents code in the block from being repeatedly executed if you keep pressing the T key.
Swapbuffers (HDC); // switch the buffer
If (Keys ['T'] &! TP) // whether the T key has been pressed and the TP value is false
{
TP = true; // If yes, set TP to true
Twinkle =! Twinkle; // The value of twinkle.
}

The following code checks whether the T key is released. If yes, make TP = false. Unless the value of TP is false, nothing will happen when the T key is pressed. So this line of code is very important.

If (! Keys ['T']) // has the T key been released?
{
TP = false; // If yes, TP is false
}

The remaining code checks whether the up and down arrow keys are pressed.

If (Keys [vk_up]) // has the arrow key been pressed?
{
Tilt-= 0.5f; // the screen is tilted up.
}

If (Keys [vk_down]) // is the arrow key down?
{
Tilt + = 0.5f; // the screen is tilted down.
}

If (Keys [vk_prior]) // is the page up key pressed?
{
Zoom-= 0.2f; // zoom out
}

If (Keys [vk_next]) // is the page flip key down?
{
Zoom + = 0.2f; // zoom in
}

As before, confirm that the title of the window is correct.

If (Keys [vk_f1]) // is the F1 key pressed?
{
Keys [vk_f1] = false; // If yes, set the value in the corresponding key array to false.
Killglwindow (); // destroy the current window
Fullscreen =! Fullscreen; // switch to full screen/window mode
// Recreate the OpenGL window
If (! Createglwindow ("nehe's transparent texture instance", 640,480, 16, fullscreen ))
{
Return 0; // exit the program if the window cannot be created
}
}
}
}

In this lesson, I try my best to explain how to load a grayscale bitmap texture, remove its background color, color it, and finally let it move in 3D scenarios. I have shown you how to create beautiful colors and animated effects. The implementation principle is to overlap a bitmap copy on the original bitmap. So far, as long as you fully understand what I have taught you, you should be able to make your own 3D demo without any problem. All basic knowledge is included!

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.