Как устранить отрывание анимации?

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

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

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

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

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

6
задан MusiGenesis 15 March 2010 в 17:06
поделиться

5 ответов

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

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

3
ответ дан 17 December 2019 в 04:45
поделиться

Двойная буферизация.

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

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

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

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

0
ответ дан 17 December 2019 в 04:45
поделиться

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

0
ответ дан 17 December 2019 в 04:45
поделиться

Для таких задач лучше использовать directx (или opengl). Но если вы хотите использовать только winforms, используйте свойство DoubleBuffered.

0
ответ дан 17 December 2019 в 04:45
поделиться

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

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

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

2
ответ дан 17 December 2019 в 04:45
поделиться
Другие вопросы по тегам:

Похожие вопросы: