OpenGL note 6

Source: Internet
Author: User

Today we will talk about animation production, which may be a favorite of everyone. In addition to teaching knowledge, we will also let the "sun, Earth, and Moon" pictures of yesterday move. Ease the boring atmosphere.
In this course, we will enter the exciting computer animation world.
I think everyone knows how movies and animations work? Yes, it quickly presents seemingly continuous pictures in front of people. Once more than 24 images are displayed every second, people may mistakenly think that the images are continuous.
We usually watch a TV with 25 or 30 screenshots per second. But for a computer, it can play more pictures to achieve smoother results. If the speed is too slow, the screen is not smooth enough. If the speed is too high, the human eye may not be able to respond. For a normal person, 60 to 60 seconds ~ 120 pictures are suitable. The specific values vary from person to person.
Assume that an animation has n images. The procedure is as follows:
Display 1st images, and wait for a short period of time until the next 1/24 seconds
Display 2nd images, and wait for a short period of time until the next 1/24 seconds
......
Display the nth image, and wait for a short period of time until the next 1/24 seconds
End
To describe this process using the pseudocode in C language, it is:
For (I = 0; I <n; ++ I)
{
DrawScene (I );
Wait ();
}

1. Dual-buffer technology
The animation on the computer is somewhat different from the actual animation: the actual animation is painted first, and it can be displayed directly during playback. Computer animation is to draw one, take one, then draw another, and then take it out. If the image to be drawn is very simple, it is no problem. However, once the drawing is complex and takes a long time to draw, the problem becomes more prominent.
Let's think of a computer as a person who draws pictures quickly. If he draws pictures directly on the screen, the pictures are complicated, it is possible that he will be seen by the audience when he only draws half of a certain image. Although he completed the painting later, the audience's eyes did not respond, and they stayed on the incomplete picture. That is to say, sometimes the audience sees the complete image, but sometimes only the incomplete image, which causes the screen to flash.
How can this problem be solved? We imagine that there were two artboards. The drawing was painted by the person next to them. After the painting was finished, the drawing board in his hand was exchanged with the drawing board hanging on the screen. In this way, the audience will not see incomplete pictures. This technology is applied to computer graphics and is called the dual-buffer technology. That is, two areas are opened in the memory (probably display memory), one is used as the data sent to the display, the other is used as the painting area, and they are exchanged as appropriate. Because only two pointers are required to swap two memory areas, this method is very efficient and widely used.
Note: Although most platforms support double buffering technology, this technology is not included in the OpenGL standard. To ensure better portability, OpenGL allows you not to use double buffering technology during implementation. Of course, our commonly used PCs support dual-buffer technology.
The simplest way to enable the dual-buffer function is to use the GLUT toolkit. We previously wrote in the main function:
Fig );
In this example, the value of "glu_single" indicates a single buffer. If it is changed to "glu_double", the double buffer is used.
Of course, there is something to change-every time the painting is complete, we need to swap two buffers and use the drawn information for screen display (otherwise, no matter how it is drawn or nothing ). If you use the GLUT toolkit, you can easily complete this job, as long as you simply call the gluswapbuffers function when the painting is complete.

2. Achieve continuous animation
There seems to be no doubt. We should write the animation code as below:
For (I = 0; I <n; ++ I)
{
DrawScene (I );
Gluswapbuffers ();
Wait ();
}
But in fact, this is not in line with the window system program design ideas. Remember our first OpenGL program? In the main function, we write: Maid (& myDisplay );
If you need to draw a window, call the myDisplay function. Why do we not directly call myDisplay, but adopt this seemingly "seeking for distance" approach? The reason is that our own program cannot determine when to draw a window. Generally, Windows and X Windows systems support displaying multiple Windows at the same time. If your program window happens to be covered by another window, and then the user moves the originally hidden window, then you need to redraw the window. Unfortunately, you cannot know the specific time of the event. Therefore, we have to entrust the operating system to handle all this.
Now let's look at the loop above. Since DrawScene can be handed over to the operating system for handling, can the work that makes the entire loop run be handed over to the operating system? The answer is yes. Our previous thought was: draw, and wait for a while; then draw, and then wait for a while. However, if the waiting time is removed, it turns into a plot, a plot ,......, Keep drawing. -- Of course, resources are public resources. Do anti-virus software always work? My download cannot be stopped, right? My mp3 player cannot be delayed. We can't stop other jobs because of our animations. Therefore, we need to plot it when the CPU is idle.
The "drawing when the CPU is idle" here is similar to the "drawing when drawing is needed" mentioned in the first lesson. It is "doing XX at XX time ", the GLUT toolkit also provides a similar function: glutIdleFunc, which means to call a function when the CPU is idle. In fact, GLUT also provides some other functions, such as "doing something when the keyboard is pressed.

Now, we can start making animations. Okay, let's start with the last "sun, Earth and Moon" program to let the Earth and the moon move themselves.

# Include <GL/glut. h> // The Sun, Earth, and Moon. // assume that each month is 30 days. // 12 months a year. The total number is 360 days. static int day = 200. // The change of day: from 0 to 359 void myDisplay (void) {/************************************** * ************* the content here is copied from the previous lesson, because dual buffering is used, complete the final sentence ************************************ * ***************/fig ();} void myIdle (void) {/* The new function is called when it is idle. The function is to move the date one day later and re-draw it to achieve the animation effect */++ day; if (day> = 360) day = 0; myDisplay () ;}int main (int argc, char * argv []) {gluinit (& argc, argv ); gluinitdisplaymode (glu_rgb | glu_double); // The parameter is changed to glu_double gluinitwindowposition (100,100); gluinitwindowsize (400,400); glucreatewindow ("Sun, Earth and Moon "); // changed the window Title: gludisplayfunc (& myDisplay); glutIdleFunc (& myIdle); // added the new keyword: glumainloop (); return 0 ;}


3. About vertical synchronization
The code is well written, but I believe you still have questions. Some friends may find that although the CPU is used almost, the speed is very fast and cannot be clearly seen. Others find that the CPU usage is very low during running, the free time is not fully utilized at all. But for the above code, these phenomena are reasonable. Vertical synchronization is involved here.
We all know that the display refreshing rate is relatively limited, generally 60 ~ 120Hz, that is, refresh 60 ~ in one second ~ 120 times. However, if a computer is called to draw a simple image, for example, with only one triangle, thousands of images can be drawn in one second. Therefore, if you use the processing power of the computer to draw a lot of pictures, but the refresh speed of the display cannot keep up, this will not only cause a waste of performance, it may also have some negative effects (for example, when the display is refreshed to half, the content to be drawn changes, because the display is refreshed row by row, therefore, the upper half and lower half of the monitor actually come from two pictures ). Vertical synchronization technology can solve this problem. That is, the drawn image is transmitted for display only when the display is refreshed. In this way, the computer does not have to draw a large number of images that are simply not used. If the update rate of the monitor is 85Hz, it is sufficient for the computer to draw 85 images in one second. If the scenario is simple enough, a lot of CPU will be idle.
Almost all graphics cards support vertical synchronization.
Vertical synchronization also has problems. If the refresh frequency is 60Hz, it takes a long time to draw a picture in a simple scenario. The frame speed can be constant at 60 fps (that is, 60 frames/second ). If the scenario becomes complex and the time for drawing a picture exceeds 1/60 seconds, the frame speed will decrease sharply.
If the time for drawing a picture is 1/50, the display needs to be refreshed in the first 1/60 seconds. However, since the new picture is not properly painted, the display can only display the original one, the new image will not be displayed until the next 1/60 seconds. Therefore, it takes 1/30 seconds to display a picture, and the frame speed is 30FPS. (If vertical synchronization is not used, the frame speed should be 50 fps)
If a picture is drawn for a longer period of time, the downgrading trend is tiered: 60FPS, 30FPS, 20FPS ,...... (60/1, 60/2, 60/3 ,......)
If the complexity of each picture is different, and the time required to draw the picture is above or below 1/60. The frame speed is 60FPS when painting is completed within 1/60 time, and 30FPS when the frame speed is not completed at 1/60 time, which causes the frame speed to beat. This is a very troublesome task. You need to avoid it-either try to simplify the painting time of each painting, or delay a short period of time for unification.
Let's look back at the previous problem. If you use a large number of CPUs and the speed is too fast to see clearly, enabling vertical synchronization can solve this problem. If you think that vertical synchronization has such disadvantages, you can also disable it. -- As for how to enable and disable it, the operating system is different. Please search for the specific steps by yourself.
Of course, there are other ways to control the animation frame rate, or try to make the animation speed irrelevant to the frame rate. However, many of the content here is closely related to the operating system, and they have little to do with OpenGL. I will not introduce it here.

4. Calculate the frame rate
I don't know if you have used the 3D Mark software. It can run various scenarios, measure the frame rate, and rate your system. Here I also introduce a method for calculating the frame rate.
According to definition, the frame rate is the number of frames played in one second (FPS ). We can measure the time t between the two pictures and calculate its reciprocal. If t = 0.05 s, the FPS value is 1/0. 05 = 20.
In theory, how can we get this time? Generally, the time function in C language is accurate to only one second. The clock function is about 10 ms, which is not enough. Because when the FPS is 60 and the FPS is 100, the t value is dozens of milliseconds.
Do you know how to measure the thickness of a piece of paper? A rough method is to use a lot of sheets of paper to stack them together to measure the thickness, so you can calculate the average value. We can also do this here. Measure the time t required to draw 50 images (including the waiting time of factors such as vertical synchronization ', FPS = 1/t = 50/t is easily obtained from t' = t * 50'
The following code calculates the call frequency of the function itself (the principle is as mentioned above). The program is not complex and does not belong to OpenGL, so I am not going to detail it.

# Include <time. h> double CalFrequency () {static int count; static double save; static clock_t last, current; double timegap; ++ count; if (count <= 50) return save; count = 0; last = current; current = clock (); timegap = (current-last)/(double) CLK_TCK; save = 50.0/timegap; return save ;}

Finally, we need to display the calculated frame rate, but we have not learned how to use OpenGL to display text on the screen. -- But don't forget, there is a command line window behind our graphic window ~ Using the printf function, you can easily output text.

# Include <stdio. h> double FPS = CalFrequency (); printf ("FPS = % f \ n", FPS );

The last step is also solved by us-although the practice is not elegant, it doesn't matter, we will improve it in the future.

It takes too long. Every time a program is given, some friends may have problems.
Now, I will provide a complete program for your reference.

# Include <GL/glut. h> # include <stdio. h> # include <time. h> // The Sun, Earth, and Moon are assumed to be 12 days a month. // 12 months a year, a total of 360 days of static int day = 200; // The change of day: from 0 to 359 double CalFrequency () {static int count; static double save; static clock_t last, current; double timegap; ++ count; if (count <= 50) return save; count = 0; last = current; current = clock (); timegap = (current-last)/(double) CLK_TCK; save = 50.0/timegap; return save ;} void myDisplay (void) {double FPS = CalFrequency (); printf ("FPS = % f \ n", FPS); glable (GL_DEPTH_TEST); glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); glMatrixMode (GL_PROJECTION); glLoadIdentity (); gluPerspective (75, 1, 1, 400000000); glMatrixMode (GL_MODELVIEW); glLoadIdentity (); gluLookAt (0,-200000000,200 000000, 0, 0, 0, 0, 0, 1); // draw the red "sun" glColor3f (1.0f, 0.0f, 0.0f); fig (69600000, 20, 20 ); // draw the blue "Earth" glColor3f (0.0f, 0.0f, 1.0f); glRotatef (day/360.0*360.0, 0.0f, 0.0f,-1.0f); glTranslatef (150000000, 0.0f, 0.0f); maid (15945000, 20, 20); // draw the yellow "moon" glColor3f (1.0f, 1.0f, 0.0f ); glRotatef (day/30.0*360.0-day/360.0*360.0, 0.0f, 0.0f,-1.0f); glTranslatef (38000000, 0.0f, 0.0f); glrotatsphere (4345000, 20, 20 ); glFlush (); fig ();} void myIdle (void) {+ + day; if (day> = 360) day = 0; myDisplay ();} int main (int argc, char * argv []) {gluinit (& argc, argv); gluinitdisplaymode (glu_rgb | glu_double); gluinitwindowposition (100,100); gluinitwindowsize (400,400 ); glucreatewindow ("Sun, Earth and Moon"); gludisplayfunc (& myDisplay); glutIdleFunc (& myIdle); glumainloop (); return 0 ;}

Summary:
OpenGL is similar to traditional animations. It presents a picture in front of the audience. Once the screen changes quickly, the audience will think that the screen is continuous.
Double buffering technology is a widely used technology in computer graphics. Most OpenGL implementations support double buffering technology.
It is usually used to draw an animation when the CPU is idle, but there can be other options.
This section describes the knowledge about vertical synchronization.
This article introduces a simple method for calculating frame rate (FPS.
Finally, we listed a complete list of celestial animation programs.

================================= Course 6 ====================== =====
================================= To be continued ======================== =====

OpenGL note 6

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.