Как устранить разрыв от анимации? - PullRequest
6 голосов
/ 15 марта 2010

Я запускаю анимацию в приложении WinForms со скоростью 18,66666 ... кадров в секунду (она синхронизируется с музыкой со скоростью 140 ударов в минуту, поэтому частота кадров странная). Каждый элемент анимации предварительно рассчитывается, и анимация управляется мультимедийным таймером высокого разрешения. Сама анимация плавная, но я вижу значительное количество «разрывов» или артефактов, возникающих в результате того, что клетки попадаются на полпути при обновлении экрана.

Когда я беру набор ячеек, отрисованный моей программой, и записываю их в файл AVI, а затем воспроизводю файл AVI в проигрывателе Windows Media, я вообще не вижу разрывов. Я предполагаю, что WMP воспроизводит файл гладко, потому что он использует DirectX (или что-то еще) и может синхронизировать рендеринг с обновлением экрана. Это не меняет частоту кадров, так как анимация синхронизируется со звуком.

Вот почему WMP может воспроизводить анимацию без разрывов или я что-то упустил? Можно ли каким-либо образом использовать DirectX (или что-то еще), чтобы моя программа могла знать, где находится текущая строка сканирования, и если да, то есть ли способ использовать эту информацию, чтобы исключить разрывы без фактического использования DirectX для отображения клеток? Или мне нужно полностью использовать DirectX для рендеринга, чтобы справиться с этой проблемой?

Обновление : забыл деталь. Мое приложение отображает каждую ячейку в PictureBox, используя Graphics.DrawImage. Является ли это значительно медленнее, чем использование BitBlt, чтобы я мог устранить хотя бы некоторые разрывы с помощью BitBlt?

Обновление 2 : эффект, который я вижу, определенно не мерцает (что отличается от разрыва). Моя панель имеет двойную буферизацию, устанавливает стили элементов управления для AllPaintingInWmPaint, UserPaint, OptimizedDoubleBuffer и т. Д., Переопределяет onPaintBackGround и так далее. Все это необходимо для устранения мерцания, но проблема разрыва остается. Это особенно заметно, когда анимация имеет очень быстро движущиеся объекты или объекты, которые очень быстро меняются от светлого к темному. Когда объекты движутся медленно и не меняют цвет быстро, эффект разрыва гораздо менее заметен (потому что последовательные клетки всегда очень похожи друг на друга).

Ответы [ 5 ]

3 голосов
/ 15 марта 2010

Разрыв происходит, когда обновление вашего изображения не синхронизировано с частотой обновления монитора. Монитор показывает часть предыдущего изображения, часть нового изображения. Когда объекты на изображении движутся быстро, эффект довольно заметен.

Это невозможно исправить в Windows Forms, вы не можете получить доступ к сигналу v-sync видеоадаптера. Вы можете в приложении DirectX .

2 голосов
/ 15 марта 2010

Я испробовал идею двойной буферизации в проекте, над которым я сейчас работаю, но у меня не получилось очень хороших результатов. В итоге я создал следующее:

  1. System.Drawing.Bitmap для моего внеэкранного буфера. Декодируйте анимацию в это растровое изображение.
  2. UserControl того же размера, что и изображение в (1), и где метод OnPaintBackground был пуст (без рисования, без вызова базового класса), а OnPaint сделал Graphics.DrawImage, чтобы скопировать изображение за пределы экрана на экран. 1006 *

Теперь у вас странная скорость анимации, поэтому разрыв почти наверняка связан с несоответствием между частотой обновления экрана и частотой обновления экрана. Вы обновляете экран посередине обновления экрана, чтобы экран рисовал старую рамку вверху экрана, а новую рамку внизу экрана. Если вы можете синхронизировать частоту кадров с частотой обновления дисплея, разрыв должен исчезнуть.

0 голосов
/ 16 марта 2010

Разрыв - это артефакт из рамки, нарисованной поверх другой. Единственные безопасные способы избежать этого - это а) ждать от vsync или б) рисовать за лучом (это довольно сложно). Один только двойной буфер не гарантирует от разрыва, так как вы можете иметь двойной буфер, но все равно отрисовывать, отключив vsync Некоторые карты также могут иметь опцию vsync wait «принудительное отключение». Вы должны проверить документацию относительно vsync и как проверить, где он находится. Это единственный безопасный способ сделать это. Кроме того, имейте в виду, что это заблокирует вашу частоту кадров.

0 голосов
/ 15 марта 2010

Двойной буфер это.

Вы можете включить двойную буферизацию, используя стили окон или, что, вероятно, проще, это нарисовать изображение с экрана и затем поменять его местами.

Если это не работает, то лучше всего использовать битовый бит и двойной буфер.

По сути, это то же самое.

Имеется ссылка на два растровых изображения, одно - экран, другое - буфер. Сначала вы рисуете в буфер, а затем перетаскиваете все это на экран. Таким образом, вы только когда-либо записываете живые данные в буфер. Сцена просто показывает то, что вы сделали ранее (стиль синего Питера)

0 голосов
/ 15 марта 2010

Вы бы лучше использовать DirectX (или OpenGL) для таких задач. Но если вы хотите использовать только winforms, используйте свойство DoubleBuffered.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...