fps. Потім, коли ви додаєте ще одну нову деталь, система вже не може намалювати все це протягом 1/60 частки секунди, і анімація різко сповільнюється - з 60 fps до 30 fps, оскільки вона пропускає перший можливий момент зміни буферів. Аналогічна ситуація відбувається, коли час малювання одного кадру стає більше, ніж 1/30 частка секунди - швидкість передачі кадрів анімації стрибком зменшується від 30 fps до 20 fps.
Якщо складність сцени така, що час її малювання виявляється близько до будь-якого із цих "чарівних" інтервалів часу (1/60 частка секунди, 2/60 частки секунди, 3/60 частки секунди і т. д. в розглянутому прикладі), то через наявність випадкової зміни деякі кадри будуть йти трохи швидше, а деякі - трохи повільніше. У результаті швидкість передачі кадрів стає непостійною, що візуально може бути неприємно. У цьому випадку, якщо ви не можете спростити сцену так,
щоб всі кадри малювалися досить швидко, можливо, краще було б навмисно додати крихітну затримку для того, щоб мати впевненість, що всі кадри пропущені, задаючи у своїй постійну, більш повільну швидкість передачі кадрів. Якщо ж кадри мають істотно відрізняється ступінь складності, тоді, можливо, вам буде потрібно більш складний підхід до вирішення цієї проблеми.
Рух = Перемальовування зображення + Перестановка буферів
Структура реальних програм анімації не надто відрізняється від приведеного опису. Зазвичай простіше перемалювати буфер цілком з чистого аркуша для кожного кадру, ніж з'ясовувати, які частини кадру вимагають зміни. Це положення особливо справедливо для таких прикладних програм, як тривимірні імітатори польоту, де найменше зміна орієнтації літака змінює позицію всього виду з вікна пілотської кабіни.
У переважно видів анімації об'єкти на сцені просто перемальовував з різними перетвореннями: переміщається точка спостереження глядача або автомобіль трохи проїжджає по дорозі, або який-небудь об'єкт повертається на невеликий кут. Якщо для операцій, не пов'язаних з малюванням, потрібно істотний обсяг повторних обчислень, то досяжна швидкість передачі кадрів часто уповільнюється. Варто мати на увазі, однак, що для виконання таких обчислень після виконання підпрограми поменять_буфери_местамі () часто може використовуватися час простою.
Бібліотека OpenGL не має у своєму складі команди типу "поменять_буфери_-місцями ()", оскільки така функціональна можливість могла б бути доступна не для всіх апаратних засобів і, в кожному разі, її реалізація істотно залежить від використовуваної віконної системи. Наприклад, якщо ви використовуєте оболонку X Window System і звертаєтеся до неї безпосередньо, то можна було б скористатися наступній підпрограмою з бібліотеки GLX:
void glXSwapBuffers (Display * dpy, Window window);
(Еквівалентні підпрограми для інших віконних систем наведені у Додатку С.)
Якщо ви використовуєте бібліотеку GLUT, то ви, можливо, забажаєте викликати наступну підпрограму:
void glutSwapBuffers (void);
Приклад 3 ілюструє використання підпрограми glutSwapBuffers () для малювання обертового квадрата, як це показано на малюнку 3. Цей приклад також демонструє те, як слід використовувати бібліотеку GLUT для контролю стану пристрої введення даних, а також для включення і виключення функції простою. У приведеному прикладі кнопки миші включають і відключають обертання квадрата.
В
Приклад 3 Програма з використанням подвійної буферизації: double.c
# include # include
static GLfloat spin = 0.0;
void init (void)
{
glClearColor (0.0, 0.0, 0.0, 0.0);
glShadeModel (GL_FLAT); } Void display (void)
{
glClear (GL_COLOR_BUFFER_BIT);
glPushMatrix ();
glRotatef (spin, 0.0, 0.0, 1.0);
glColor3f (1.0, 1.0, 1.0);
glRectf (-25.0, -25.0, 25.0, 25.0);
glPopMatrix () ; p> glutSwapBuffers ();) p> void spinDisplay (void)
{
spin = spin +2.0; p> if (spin> 360.0)
spin = spin - 360.0;
glutPostRedisplay (); } p> void reshape (Int w, int h)
{
glViewport (0, 0, (GLsizei) w, (GLsizei) h);
glMatrixMode (GL_PROJECTION);
glLoadldentity ();
glOrtho (-50.0, 50.0, -50.0, 50.0, -1.0, 1.0);
glMatrixMode (GL_MODELVIEW);
glLoadldentity ();
void mouse (int button, int state, int x, int y) {
switch (button) {p> case GLUT_LEFT_BUTTON:
if (state == GLUT_DOWN)
glutldleFunc (spinDisplay); break; case GLUT_MIDDLE_BUTTON:
if (state == GLUT_DOWN)
glutldleFunc (NULL); break; default:
break;}}
/*
Запросити режим відображення з подвійною буферизацією.
Зареєструвати функції зворотного виклику з введення даних від миші */
int main (int argc, char ** argv) {
glutlnit (Sargc, argv);
glutInitDisplayMode (GLUT_DOUB...