Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[3.14.141.228] |
|
Сообщ.
#1
,
|
|
|
Нужно реализовать плавный гуишный процесс. Например, процесс игры, где что-то плавно движется и отображается в окне. Либо что-то рисуется.
Варианты: 1. Использовать таймер. 2. Использовать цикл с задержкой через Sleep (а обработку сообщений окна – через PeekMessage). 3. Какой-то другой(?) Проблема п.1 и 2 заключается в том, что сделать достаточно короткую задержку весьма проблематично. У меня (на 10-ке) Sleep(1) работает примерно как Sleep(2), а Sleep(4) – как Sleep(5). Использование таймера работает ещё хуже, там при установке интервалов в 1 мс процедура таймера вызывается раз в 10-20 мс или что-то в этом духе. Вариант задержки через цикл с GetTickCount (или через QueryPerformanceCounter) вместо использования Sleep – отличный вариант, но грузит процессор по самое не хочу. Sleep(0), естественно, тут не помогает. Что можно сделать в данной ситуации. Может, с оконной функцией можно как-то поиграться? Как это вообще делается обычно? |
Сообщ.
#2
,
|
|
|
Цитата Jin X @ Как это вообще делается обычно? Обычно -- вечным циклом и ожиданием мультимедийного таймера. Впрочем, задача изначально решается у тебя не тем инструментарием. |
Сообщ.
#3
,
|
|
|
Пока почитайте про игры
https://m.habrahabr.ru/post/136878/ А про таймеры сейчас напишу. Добавлено Цитата Jin X @ 2. Использовать цикл с задержкой через Sleep (а обработку сообщений окна – через PeekMessage). В побочном потоке sleep в 2 раза быстрее, чем в главном потоке! Цитата Jin X @ 1. Использовать таймер. Есть специальный мультимедийный таймер. uses mmsystem; timeBeginPeriod(1); // Устанавливаем частоту срабатывания мультимедийного таймера в 1 мс. Установка глобально и распространяется на все программы в ОС, так что всякие там СУБД и медиаплееры уже могли его выставить. MMTimer1 := timeSetEvent(1,1,@MyTimerCallBackProg,100,TIME_PERIODIC); Для gpGPU нужно точность меньше 1 мс. Некоторые писали о том, что на SetWaitableTimer им удалось добиться 250 мкс (на win 10). |
Сообщ.
#4
,
|
|
|
Есть ещё NtDelayExecution, он работает поточнее, чем Sleep, но всё равно не фонтан (точность 1 мс примерно).
Добавлено Цитата B.V. @ Под вечный циклом ты имеешь в виду цикл обработки сообщений или что? Обычно -- вечным циклом и ожиданием мультимедийного таймера. |
Сообщ.
#5
,
|
|
|
Цитата Jin X @ Под вечный циклом ты имеешь в виду цикл обработки сообщений или что? Нет, я имею ввиду while(!exit_event) {} Впрочем, Pavia выше уже привёл неплохую ссылочку |
Сообщ.
#6
,
|
|
|
Цитата Jin X @ Есть ещё NtDelayExecution, он работает поточнее, чем Sleep, но всё равно не фонтан (точность 1 мс примерно). Точность 0.5 мс (обычно), только надо сначала установить эту точность: ULONG minRes, maxRes, curRes, oldRes; NtQueryTimerResolution(&minRes, &maxRes, &curRes); NtSetTimerResolution(maxRes, true, &oldRes); Добавлено Цитата Jin X @ Например, процесс игры, где что-то плавно движется и отображается в окне. Тут не таймер нужен, а VSync. Как именно его делать, зависит от используемого для отрисовки API (DirectX/OpenGL/что-то другое). |
Сообщ.
#7
,
|
|
|
Цитата Pacific @ GDI VSync. Как именно его делать, зависит от используемого для отрисовки API Добавлено Цитата Pacific @ Огонь! Так и есть, 5000 Точность 0.5 мс (обычно), только надо сначала установить эту точность |
Сообщ.
#8
,
|
|
|
Цитата Pacific @ Тут не таймер нужен, а VSync. Как именно его делать, зависит от используемого для отрисовки API (DirectX/OpenGL/что-то другое). Зачем? В современных видео-картах есть двойная и тройная буферизация. VSync нужен только для WinXp, а эта ОС уже отжила своё. А Win10 буферизация по умолчанию включена. |
Сообщ.
#9
,
|
|
|
Цитата B.V. @ Обычно -- вечным циклом и ожиданием мультимедийного таймера. Цитата Pavia @ Там всё равно разрешение 1 мс.MMTimer1 := timeSetEvent(1,1,@MyTimerCallBackProg,100,TIME_PERIODIC); А вообще (мне тут намекнули в другом месте), поскольку частота обновления всё равно не бывает выше 240 Гц, можно делать задержки по 4 мс и просто отрисовывать больше за раз Но тема минимальных задержек всё равно интересна... Добавлено Цитата B.V. @ Ну это явно проц не разгрузит (вопрос был, в первую очередь, об этом).while(!exit_event) {} Посмотрю, спасибо! |
Сообщ.
#10
,
|
|
|
Цитата Jin X @ А вообще (мне тут намекнули в другом месте), поскольку частота обновления всё равно не бывает выше 240 Гц, можно делать задержки по 4 мс и просто отрисовывать больше за раз Но тема минимальных задержек всё равно интересна... Человеческий глаз не видит мельканий, если частота выше 48 герц. (Пусть 50 для ровного счёта.) Значит, период обновления 20 [мс] уже устроит. Добавлено Цитата Jin X @ Может, с оконной функцией можно как-то поиграться? Попробуй оконную функцию оставить только для вывода, а рабочий поток - для рисования. И работать только по событиям. Например, сработало событие-таймер. Проснулись, нарисовали, передали главному потоку, заснули. Главный поток вывел и успокоился. И.т.д. |
Сообщ.
#11
,
|
|
|
Цитата ЫукпШ @ Это всё очень условно и старо. Разве не видно мерцания обычной лампочки 50 Гц, по крайней мере, если смотреть чуть мимо? И это с учётом того, что вольфрамовая нить остывает не мгновенно, а гораздо медленнее, чем ЖК.Человеческий глаз не видит мельканий, если частота выше 48 герц. (Пусть 50 для ровного счёта.) Значит, период обновления 20 [мс] уже устроит. Я сделал движение с интервалом 20 мс – видно дёргание картинки (даже при смещении на 1 пиксель). На 10-15 уже плавно. В принципе да, 70-100 Гц достаточно. Если очень хочется – 200-250 Гц Цитата ЫукпШ @ Так и есть.Попробуй оконную функцию оставить только для вывода, а рабочий поток - для рисования. Я про то, что, может, можно использовать оконную функцию для частого вывода. Например, в конце отрисовки посылать UpdateWindow в конце отрисовки. Но я так уже попробовал – результат с загрузкой процессора тот же. Поэтому подумал, что, может, как-то ещё можно сделать... |
Сообщ.
#12
,
|
|
|
Цитата ЫукпШ @ Человеческий глаз не видит мельканий, если частота выше 48 герц. Это миф. Частота фильмов 24 связано с тем что на плёнке параллельно шёл звук и его надо было синхронизировать. А так как плёнка была одна то и получилось 24 кадра или 24 КГц. С глазом это не связано. Что касается мозг и глаз я уже писал цифры, Реакция мозга 115-150 мс. Реакция глаза 9 мс. Цитата Jin X @ Я сделал движение с интервалом 20 мс – видно дёргание картинки (даже при смещении на 1 пиксель). Глаз меряет скорость довольно точно. А вот таймер может плавать достаточно сильно. Дело в том что ОС многозадачная и вашу программу могут прерывать и на 10 и даже на 100 мс. Поэтому обязательно нужно рассчитывать интервал между срабатыванием таймеров и рассчитывать скорость перемещения, а не каждый раз на 1 пиксель смещать. |
Сообщ.
#13
,
|
|
|
Цитата Jin X @ Глаз (не только у человека) устроен так, что центральная часть поля зрения отвечает за распознавание предметов, для чего требуется высокая чёткость, без необходимости реагировать на быстрые изменения, а периферия отвечает за безопасность владельца глаза, для чего чёткость не нужна, зато нужно очень быстро реагировать на малейшие изменения. Поэтому там и мерцание лучше обнаруживается. Некоторые боковым зрением мерцание ЖК мониторов видят (60 Гц). Там ещё и реакция быстрее.Разве не видно мерцания обычной лампочки 50 Гц, по крайней мере, если смотреть чуть мимо? Цитата Jin X @ Частота развёртки какая? Строго говоря, картинка на экране обновляется только при его перерисовке с частотой 60 Гц. Поэтому обновление кадра, если отношение частоты времени отрисовки к периоду развёртки где-то между 0.5 и 2 обычно лучше привязать к кадровой развёртке. Это не имеет значения на мониторах с высокой частотой кадров. Я сделал движение с интервалом 20 мс – видно дёргание картинки |
Сообщ.
#14
,
|
|
|
Цитата Pavia @ Это всё понятно, но есть ещё один нюанс.Поэтому обязательно нужно рассчитывать интервал между срабатыванием таймеров и рассчитывать скорость перемещения, а не каждый раз на 1 пиксель смещать. Допустим, нам нужно смещать картинку на 1 пиксель каждые 10 мс. Исходные условия: время = 0. ИТЕРАЦИЯ ОТРИСОВКИ 0. 1. Мы отрисовали стартовую картинку и вывели её. 2. Замеряем время, получили 10 мс. ИТЕРАЦИЯ ОТРИСОВКИ 1. 3. Рисуем на 1 пиксель дальше, выводим картинку. 4. Замеряем время, получили 20 мс. 5. Произошла незапланированная задержка на 30 мс. ИТЕРАЦИЯ ОТРИСОВКИ 2. 6. Рисуем на 1 пиксель дальше, выводим картинку (хотя по факту прошло уже 40 мс). 7. Замеряем время, получили 60 мс. ИТЕРАЦИЯ ОТРИСОВКИ 3. 8. Рисуем на 4 пикселя дальше, выводим картинку (хотя по факту прошло 10 мс). На 2 и 3 итерациях отрисовки произошло неверное перемещение: в первом случае задержка была больше, чем рассчитано, во втором – меньше. Всё равно картинка дёрнулась. Цитата amk @ 60 Гц. Частота развёртки какая? |
Сообщ.
#15
,
|
|
|
Цитата amk @ Я совсем боковым вижу и 70 Гц-мерцание на ЭЛТ монике. Некоторые боковым зрением мерцание ЖК мониторов видят (60 Гц). Там ещё и реакция быстрее. |
Сообщ.
#16
,
|
|
|
Цитата Славян @ Похоже у тебя хорошо развито определение движения. Большинство 70Гц уже не воспринимают даже самым краем глаза. Впрочем, некоторые уже за пределами градусов 60 от центра похоже вообще ничего не воспринимают, кроме яркости.Я совсем боковым вижу и 70 Гц-мерцание на ЭЛТ монике. Я 75 Гц ставил, на 70 через пару часов подташнивать начинало. Похоже наводки от сети в развёртку пробивались и этого пятигерцового покачивания картинки хватало. Хотя я морской болезнью вроде не страдаю. |
Сообщ.
#17
,
|
|
|
Цитата Славян @ Цитата amk @ Я совсем боковым вижу и 70 Гц-мерцание на ЭЛТ монике. Некоторые боковым зрением мерцание ЖК мониторов видят (60 Гц). Там ещё и реакция быстрее. я думаю, что это ошибка. --- Эдак я и килогерцовое мелькание видел. На 7-ми сегментном индикаторе с динамической индикацией 1000 гц. Этот эффект возникает, когда мелькание изображения с одной частотой, освещают внешним светом с другой частотой. Те при внешнем электрическом освещении от сети переменного тока вообще. Между частотами возникают "биения" (могут возникнуть). Если частота биений будет меньше 48 [гц], можно увидеть "мелькания" и другие эффекты. Особенно при быстром движении головы. Причину этого усиления заметности движением я не знаю. Добавлено Цитата Pavia @ Цитата ЫукпШ @ Человеческий глаз не видит мельканий, если частота выше 48 герц. Это миф. Частота фильмов 24 связано с тем что на плёнке параллельно шёл звук и его надо было синхронизировать. А так как плёнка была одна то и получилось 24 кадра или 24 КГц. Скрытый текст Товарищ ! Соблюдай аккуратность и бдительность ! Не путай герцы с килогерцами Иначе однажды больно и мучительно Остановится твоё сердце Необходимо точно и правильно величин порядки считать Перепутав киловольты с вольтами не сможешь даже закричать.. Неверные представления. Частота протягивания плёнки - 24 кадра в секунду. Это ограничения было вызвано техническими возможностями протяга плёнки вообще. Такое мелькание хорошо было бы заметно. Чтобы не было видно мельканий каджый кадр "показывают два раза". К звуку это не имеет никакого отношения. У меня в детстве был домашний кинопроектор - показывал кино без звука. Скорость можно было регулировать вручную, и сразу визуально видна была граница, когда мелькания становились не заметны. --- Частота развёртки ТВ - 50 гц (20 мс). Кстати, меняется только половина кадра - развётка черезстрочная. Мельканий мы не видим. Однако, при "быстром движении головы" на быстрых изменениях сюжета можно увидеть некие "видеоэффекты". Добавлено Цитата Jin X @ Я сделал движение с интервалом 20 мс – видно дёргание картинки (даже при смещении на 1 пиксель). На 10-15 уже плавно. В принципе да, 70-100 Гц достаточно. Если очень хочется – 200-250 Гц Дёргание картинки и частота обновления экрана - разные вещи. Очевидно, любое резкое изменения сюжета будет заметно при любой частоте обновления. Вратарь неподвижно стоит в воротах.. и тут шайба пулей влетает в сетку, её и увидеть то трудно. Так и должно быть. Добавлено Цитата Jin X @ Цитата ЫукпШ @ Это всё очень условно и старо. Разве не видно мерцания обычной лампочки 50 Гц, по крайней мере, если смотреть чуть мимо?Человеческий глаз не видит мельканий, если частота выше 48 герц. (Пусть 50 для ровного счёта.) Значит, период обновления 20 [мс] уже устроит. я вообще не понимаю про "старо". Если посмотреть на график напряжения (и тока конечно) через лампочку, тогда мы увидем 2 пика тока за период 50 гц. Это значит, что лампочка "мигает" 2 раза за период, те с частотой 100 гц. Значит, частоты мелькания 100 гц тоже не достаточно ? |
Сообщ.
#18
,
|
|
|
Цитата ЫукпШ @ У меня в детстве был домашний кинопроектор - показывал кино без звука. Скорость можно было регулировать вручную, и сразу визуально видна была граница, когда мелькания становились не заметны. Это строб-эффект, в проекторе есть забыл слово. Есть сепаратор который разделяет кадры - вентилятор когда вы уменьшали частоту то уменьшалась частота плёнки но не сепаратора из-за чего возникал строб-эффект поэтому и казалось что кадры начинают "моргать". Возьмите не старый проектор, а обычный монитор и повторите свой эксперимент вы можете поставить воспроизведение на 10-15 кадров в секунду и картинка будет двигаться плавна без рывков. Всё потому что рефлексы мозга не превышает 115 мс = 8٫6 кадрос/с. |
Сообщ.
#19
,
|
|
|
Цитата ЫукпШ @ В простых проекторах, типа "Украины", что в школе использовался. В кинотеатрах протяжка немного быстрее, а кадр мелькает аж три раза. Получается 72 вспышки в секунду. Подавляющее большинство людей такую частоту вспышек не воспринимают даже боковым зрением.Чтобы не было видно мельканий каджый кадр "показывают два раза". В "Украине" при просмотре старых плёнок, снятых с частотой 16 кадров в секунду, тоже можно было поменять протяжку и обтюратор, чтобы делать по три вспышки на кадр и получить 48 вспышек в секунду. Имело смысл, так как 32 вспышки видны как мерцание, даже при небольшом отведении глаз. А некоторые видят их даже глядя прямо. Цитата Pavia @ Эта штука называется обтюратор. Диск с прорезями. Это строб-эффект, в проекторе есть забыл слово. |
Сообщ.
#20
,
|
|
|
Цитата ЫукпШ @ Я ж говорю - смещение на 1 пиксель, где тут резкое?Очевидно, любое резкое изменения сюжета будет заметно при любой частоте обновления. Ставлю 20 мс - рывки, 10-15 - нет их. |