Перейти к содержанию
    

Програмирование графики

Кто знает как по правильному реализовать гладкую анимацию(скроллинг)?

Только при помощи кадровой синхронизации. Если от видеокарты (или её низкоуровневого API) получите сигнал кадровой синхронизации, то сможете сделать.

Я в своё время находил такую опцию среди API DirectDraw, но уже точно не помню - или она не работала на моей карте или она там только в полноэкранном режиме работает.

Ну или должна быть какая-то функция в самом GDI API, которая копирует картинку в видеопамять синхронизируясь с кадровой развёрткой.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Что-то мне подсказывает, что кадровая развертка тут не при чем.... В тех-же играх даже можно её включать и выключать(VSync или вертикальная синхронизация это обычно называется).

Отсутствие синхронизации с кадровой разверткой приводит к тирингу, я уже писал об этом https://en.wikipedia.org/wiki/Screen_tearing это то ладно, это другой вопрос.

 

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Глянул пару исходничков тут.. В том числе Quake 3 даже.

Похоже нормальные пацаны для измерения времени c миллисекундной точностью используют timeGetTime() вместо GetTickCount();

И таки в самом начале они разгоняют таймер использую timeBeginPeriod(1), что в том числе благотворно сказывается и на Sleep();

 

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

http://pastebin.com/gAQqdrJ0

 

Кстати по скорости тоже я впечатлен. Скроллинг удалось разогнать до 680FPS!

 

В принципе учитывая, что TCanvas даёт нам свой DC - можно то-же самое реализовать и в C++ Builder и в Delphi.

И даже в случае чего завернуть это в отдельный компонент, чтоб можно было эти графики ложить на форму. Я так когда-то самодельный DBGrid делал с нестандартной раскраской )

Win32Project1_30FPS_Sleep___.zip

Win32Project1_maxFPS_.zip

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А чем вас DirectX кстати не устраивает? Ничего плавного и красивого на таймерах у вас не выйдет, не говоря уже про дурной стиль

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

 

В принципе полученным результатом лично я сейчас доволен. И по скорости и по плавности. Для типичных задач типичного эмбэддера очень достойно. Нам то не игры тут писать )

 

Обратите внимание сколько 30FPS версия моего тестового образца жрет процессора. Красота же!

 

ADD:

очень интересные эффекты наблюдаются если плавно менять FPS. Используйте стрелки влево-вправо.

те кратность развертке очень важна! 60фпс лучше чем 70

на 40 вообще как-то странно все это выглядт....

Win32Project1_tune_fps_.zip

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Адаптировать всё это для билдера пара пустяков.

Кстати для потоков там есть TThread, что в общем то позволит не лезть в API

Device Context у вас есть(TCanvas его даёт, как я уже гвоорил ранее). Немного пере компоновываете всё что я тут навоял и всё будет прекрасно работать!

 

Главный вывод моих экспериментов такой: BitBlt на экран нужно делать 60раз в сек(если конечно успевает проц). А саму отрисовку графики можно делать и с меньшей частотой, это не важно. Главное именно Blt в окно чтоб выполнялось 60fps. И тогда красота получается)

 

А билдер даже ставить не охота, систему засорять. Я в своё время вдоволь посидел на дэлфи, потом на билдере. Ну его нафиг, этот VCL!

Щас на Qt пересел и вам рекомендую! Раз уж всё равно осваивать почти с нуля, то ИМХО лучше сразу правильный фреймворк.

Кстати на Qt для быстрой прорисовки не приходится спускаться до самого Win API.

А если делать интерфейс на QML то и вовсе всё окно рендерится сразу в GL(прозрачно для программиста) позволяя делать всякие эффекты и приколы.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Главный вывод моих экспериментов такой: BitBlt на экран нужно делать 60раз в сек(если конечно успевает проц). А саму отрисовку графики можно делать и с меньшей частотой, это не важно. Главное именно Blt в окно чтоб выполнялось 60fps. И тогда красота получается)

И какой смысл? Перерисовывать 60раз/сек неизменяющуюся картинку?

Делать BitBlt из памяти на экран чаще чем частота обновления картинки - нет смысла. Видеопамять она не теряет предыдущую картинку, на то она и память.

Нарисовали картинку в памяти - копируете её BitBlt в видеоОЗУ. Можно даже параллельно (в другом thread) с отрисовкой новой картинки в памяти. Ещё лучше если сделать синхронизацию с кадровой развёрткой, для уменьшения всяких артефактов, типа дёрганья и искажения картинки из-за наложения частоты кадровой развёртки и частоты обновления картинки.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Ну или ладно, можно не изменяющуюся не копировать(сделать флажок какой-то, что картинка изменилась), но выводящий на экран цикл всё равно должен крутиться с частотой 60Гц.

 

Кто бы сказал как нам в венде синхронизировать свой Thread с VSync - цены бы не было этому человеку!

Только я так понял, что даже в GL и DirectX VSync включается отправкой запроса драйверу типа: "давай я буду рисовать как хочу, а ты там синхронизируй всё это с VSync". И драйвер видяхи еще и имеет право не выполнять просьбу. Например в панели управления NVidia можно выключить VSync и всё ) Или наоборот включить принудительно.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

но выводящий на экран цикл всё равно должен крутиться с частотой 60Гц.

Зачем?

 

Кто бы сказал как нам в венде синхронизировать свой Thread с VSync - цены бы не было этому человеку!

Только я так понял, что даже в GL и DirectX VSync включается отправкой запроса драйверу типа: "давай я буду рисовать как хочу, а ты там синхронизируй всё это с VSync". И драйвер видяхи еще и имеет право не выполнять просьбу. Например в панели управления NVidia можно выключить VSync и всё ) Или наоборот включить принудительно.

Там возможно другой механизм кадровой синхронизации есть. Например:

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

Не знаю есть ли такой механизм, но такой вариант возможен.

С таким механизмом не будет случаев, когда часть картинки отобразилась в одном кадре (успела нарисоваться), а другая часть - в следующем.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Зачем?

Уж не знаю, эксперимент показал, что на 60Гц таки всё двигается плавнее. У меня Win10

 

Кстати я в своих экспериментах не видел тиринга. Терзают меня догадки, что GDI уже синхронизирован с VSync где-то внутри....

А вот именно синхронизировать поток с VSync это было бы полезно. Ну чтоб вместо Sleep() было что-нибудь типа WaitForVSync().

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Подскажите еще допустим есть переменная 0-256, как вывести цвет точки так , чтобы при изменение переменной от 0 до 256 цвет менялся по спектру глаза те 0- фиолетовый, 128- желто-зеленый, 256- красный, долго думал пока не понял.

Цвет задается тремя цифрами (красный, зеленый синий ), но как их скомбинировать под эту задачу...

 

Те надо плавный спектр а не скажем (TColor)RGB(256-Col,128,Col); ;)

 

Те нужно знать весовые функции для каждого цвета в зависимости от переменной 0-256

Изменено пользователем whale_nik

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Подскажите еще допустим есть переменная 0-256, как вывести цвет точки так , чтобы при изменение переменной от 0 до 256 цвет менялся по спектру глаза те 0- фиолетовый, 128- желто-зеленый, 256- красный, долго думал пока не понял.

Цвет задается тремя цифрами (красный, зеленый синий ), но как их скомбинировать под эту задачу...

 

http://stackoverflow.com/questions/7706339...jet-color-scale

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...