Анимация
Анимация
На примере многочисленных хранителей экрана (screen-saver) вы видели, как гладко работает анимация в OpenGL. OpenGL использует два буфера памяти (front and back). Первый (front-буфер) отображается на экране, второй в это время может обрабатываться процессором. Когда обработка закончится, то есть очередная сцена будет готова, вы можете произвести быстрое переключение буферов (swap), обеспечивая тем самым гладкую анимацию изображения. При обмене копирование массивов не происходит, изменяется лишь значение указателя (адреса) отображаемого блока памяти. Отметьте, что процесс рисования в back-буфер происходит быстрее, чем в front, так как большинство видеокарт запрещают редактировать изображение в момент вертикальной развертки, а это происходит 60-90 раз в секунду.
Рассмотрим основную схему алгоритма анимации, используемого в OpenGL-при-ложениях. В кино эффект движения достигается тем, что каждый кадр проецируется на экран в течение короткого промежутка времени, затем шторка проектора моментально закрывается, пленка продвигается на один кадр, вновь открывается шторка и цикл повторяется. Период цикла равен 1/24 с или даже 1/48 с в современных кинопроекторах. Современные компьютеры допускают смену кадра (refresh rate) до 120 раз в секунду. Рассмотренный алгоритм можно записать так в цикле по всем кадрам:
- сотри старое изображение;
- создай новое изображение;
- задержи изображение на какое-то время.
Если реализовать анимацию по такой схеме, то эффект будет тем более удручающим, чем ближе к 1/24 с подходит время создания изображения, так как полное изображение существует на экране лишь долю периода. Большую часть периода мы видим процесс рисования.
OpenGL предоставляет возможность двойной буферизации (аппаратной или программной — зависит от видеокарты). Алгоритм анимации в этом случае таков: пока проецируется первый кадр, создается второй. Переключение кадров происходит только после того, как закончится формирование второго кадра. Пользователь никогда не видит незавершенный кадр. Эту схему можно представить в виде проектора с двумя кадрами пленки. В момент демонстрации первого второй стирается и вновь рисуется. Новый алгоритм можно записать в цикле по кадрам:
- Сотри старое изображение в back-буфере.
- Создай в нем новое изображение.
- Переключи буферы (front-back).
Последний шаг алгоритма не начнет выполняться, пока не закончится предыдущий шаг — создание нового кадра в back-буфере. Ожидание этого события (конец рисования в невидимый буфер) дополняется ожиданием завершения цикла прямого хода развертки экрана. Поэтому самая большая частота смены изображений равна текущему значению частоты кадров дисплея. Допустим, что эта частота равна 60 Гц, тогда частота смены изображений будет 60 fps (frames per second — кадров в секунду). Если время рисования занимает немногим более 1/60 с (пусть 1/45 с), то один и тот же кадр будет проецироваться два такта цикла развертки и частота смены изображений реально будет 30 fps. Промежуток времени между 1/30 с и 1/45 с процессор простаивает (is idle). Если время подготовки невидимого кадра нестабильно (плавает), то частота смены изображений может измениться скачком, что воспринимается как неприятная помеха. Для сглаживания этого эффекта иногда искусственно добавляют небольшую задержку, с тем чтобы немного снизить частоту, но сделать ее стабильной. Отметьте, что OpenGL не имеет команды переключения буферов, так как такая команда всегда зависит от платформы. Мы будем пользоваться функцией SwapBuf f ers(HDC hdc), входящей в состав Windows API.