Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[3.14.83.223] |
|
Страницы: (2) [1] 2 все ( Перейти к последнему сообщению ) |
Сообщ.
#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 Гц). Там ещё и реакция быстрее. |