На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
Обратите внимание:
1. Прежде чем начать новую тему или отправить сообщение, убедитесь, что вы не нарушаете правил форума!
2. Обязательно воспользуйтесь поиском. Возможно, Ваш вопрос уже обсуждали. Полезные ссылки приведены ниже.
3. Темы с просьбой выполнить какую-либо работу за автора в этом разделе не обсуждаются.
4. Используйте теги [ code=cpp ] ...текст программы... [ /code ] для выделения текста программы подсветкой.
5. Помните, здесь телепатов нет. Старайтесь формулировать свой вопрос максимально грамотно и чётко: Как правильно задавать вопросы
6. Запрещено отвечать в темы месячной и более давности без веских на то причин.

Полезные ссылки:
user posted image FAQ Сайта (C++) user posted image FAQ Форума user posted image Наши Исходники user posted image Поиск по Разделу user posted image MSDN Library Online (Windows Driver Kit) user posted image Google

Ваше мнение о модераторах: user posted image B.V.
Модераторы: B.V.
Страницы: (2) [1] 2  все  ( Перейти к последнему сообщению )  
> Плавный гуишный процесс , без загрузок
    Нужно реализовать плавный гуишный процесс. Например, процесс игры, где что-то плавно движется и отображается в окне. Либо что-то рисуется.
    Варианты:
    1. Использовать таймер.
    2. Использовать цикл с задержкой через Sleep (а обработку сообщений окна – через PeekMessage).
    3. Какой-то другой(?)

    Проблема п.1 и 2 заключается в том, что сделать достаточно короткую задержку весьма проблематично. У меня (на 10-ке) Sleep(1) работает примерно как Sleep(2), а Sleep(4) – как Sleep(5).
    Использование таймера работает ещё хуже, там при установке интервалов в 1 мс процедура таймера вызывается раз в 10-20 мс или что-то в этом духе.
    Вариант задержки через цикл с GetTickCount (или через QueryPerformanceCounter) вместо использования Sleep – отличный вариант, но грузит процессор по самое не хочу. Sleep(0), естественно, тут не помогает.

    Что можно сделать в данной ситуации. Может, с оконной функцией можно как-то поиграться?
    Как это вообще делается обычно?
      Цитата Jin X @
      Как это вообще делается обычно?

      Обычно -- вечным циклом и ожиданием мультимедийного таймера. Впрочем, задача изначально решается у тебя не тем инструментарием.
        Пока почитайте про игры
        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).
          Есть ещё NtDelayExecution, он работает поточнее, чем Sleep, но всё равно не фонтан (точность 1 мс примерно).

          Добавлено
          Цитата B.V. @
          Обычно -- вечным циклом и ожиданием мультимедийного таймера.
          Под вечный циклом ты имеешь в виду цикл обработки сообщений или что?
            Цитата Jin X @
            Под вечный циклом ты имеешь в виду цикл обработки сообщений или что?

            Нет, я имею ввиду
            ExpandedWrap disabled
              while(!exit_event) {}

            Впрочем, Pavia выше уже привёл неплохую ссылочку
              Цитата Jin X @
              Есть ещё NtDelayExecution, он работает поточнее, чем Sleep, но всё равно не фонтан (точность 1 мс примерно).

              Точность 0.5 мс (обычно), только надо сначала установить эту точность:
              ExpandedWrap disabled
                ULONG minRes, maxRes, curRes, oldRes;
                NtQueryTimerResolution(&minRes, &maxRes, &curRes);
                NtSetTimerResolution(maxRes, true, &oldRes);


              Добавлено
              Цитата Jin X @
              Например, процесс игры, где что-то плавно движется и отображается в окне.

              Тут не таймер нужен, а VSync. Как именно его делать, зависит от используемого для отрисовки API (DirectX/OpenGL/что-то другое).
                Цитата Pacific @
                VSync. Как именно его делать, зависит от используемого для отрисовки API
                GDI :P

                Добавлено
                Цитата Pacific @
                Точность 0.5 мс (обычно), только надо сначала установить эту точность
                Огонь! Так и есть, 5000 :good:
                  Цитата Pacific @
                  Тут не таймер нужен, а VSync. Как именно его делать, зависит от используемого для отрисовки API (DirectX/OpenGL/что-то другое).

                  Зачем? В современных видео-картах есть двойная и тройная буферизация. VSync нужен только для WinXp, а эта ОС уже отжила своё. А Win10 буферизация по умолчанию включена.
                    Цитата B.V. @
                    Обычно -- вечным циклом и ожиданием мультимедийного таймера.
                    Цитата Pavia @
                    MMTimer1 := timeSetEvent(1,1,@MyTimerCallBackProg,100,TIME_PERIODIC);
                    Там всё равно разрешение 1 мс.
                    А вообще (мне тут намекнули в другом месте), поскольку частота обновления всё равно не бывает выше 240 Гц, можно делать задержки по 4 мс и просто отрисовывать больше за раз :)
                    Но тема минимальных задержек всё равно интересна... :)

                    Добавлено
                    Цитата B.V. @
                    while(!exit_event) {}
                    Ну это явно проц не разгрузит (вопрос был, в первую очередь, об этом).

                    Цитата Pavia @
                    Пока почитайте про игры
                    https://m.habrahabr.ru/post/136878/
                    Посмотрю, спасибо! :good:
                      Цитата Jin X @
                      А вообще (мне тут намекнули в другом месте), поскольку частота обновления всё равно не бывает выше 240 Гц, можно делать задержки по 4 мс и просто отрисовывать больше за раз :)
                      Но тема минимальных задержек всё равно интересна... :)

                      Человеческий глаз не видит мельканий, если частота выше 48 герц.
                      (Пусть 50 для ровного счёта.)
                      Значит, период обновления 20 [мс] уже устроит.

                      Добавлено
                      Цитата Jin X @
                      Может, с оконной функцией можно как-то поиграться?

                      Попробуй оконную функцию оставить только для вывода, а рабочий поток - для рисования.
                      И работать только по событиям.
                      Например, сработало событие-таймер.
                      Проснулись, нарисовали, передали главному потоку, заснули.
                      Главный поток вывел и успокоился.
                      И.т.д.
                        Цитата ЫукпШ @
                        Человеческий глаз не видит мельканий, если частота выше 48 герц.
                        (Пусть 50 для ровного счёта.)
                        Значит, период обновления 20 [мс] уже устроит.
                        Это всё очень условно и старо. Разве не видно мерцания обычной лампочки 50 Гц, по крайней мере, если смотреть чуть мимо? И это с учётом того, что вольфрамовая нить остывает не мгновенно, а гораздо медленнее, чем ЖК.
                        Я сделал движение с интервалом 20 мс – видно дёргание картинки (даже при смещении на 1 пиксель). На 10-15 уже плавно. В принципе да, 70-100 Гц достаточно. Если очень хочется – 200-250 Гц :)

                        Цитата ЫукпШ @
                        Попробуй оконную функцию оставить только для вывода, а рабочий поток - для рисования.
                        Так и есть.
                        Я про то, что, может, можно использовать оконную функцию для частого вывода.
                        Например, в конце отрисовки посылать UpdateWindow в конце отрисовки. Но я так уже попробовал – результат с загрузкой процессора тот же.
                        Поэтому подумал, что, может, как-то ещё можно сделать...
                          Цитата ЫукпШ @
                          Человеческий глаз не видит мельканий, если частота выше 48 герц.

                          Это миф. Частота фильмов 24 связано с тем что на плёнке параллельно шёл звук и его надо было синхронизировать. А так как плёнка была одна то и получилось 24 кадра или 24 КГц.
                          С глазом это не связано.
                          Что касается мозг и глаз я уже писал цифры,
                          Реакция мозга 115-150 мс.
                          Реакция глаза 9 мс.

                          Цитата Jin X @
                          Я сделал движение с интервалом 20 мс – видно дёргание картинки (даже при смещении на 1 пиксель).

                          Глаз меряет скорость довольно точно. А вот таймер может плавать достаточно сильно. Дело в том что ОС многозадачная и вашу программу могут прерывать и на 10 и даже на 100 мс.
                          Поэтому обязательно нужно рассчитывать интервал между срабатыванием таймеров и рассчитывать скорость перемещения, а не каждый раз на 1 пиксель смещать.
                            Цитата Jin X @
                            Разве не видно мерцания обычной лампочки 50 Гц, по крайней мере, если смотреть чуть мимо?
                            Глаз (не только у человека) устроен так, что центральная часть поля зрения отвечает за распознавание предметов, для чего требуется высокая чёткость, без необходимости реагировать на быстрые изменения, а периферия отвечает за безопасность владельца глаза, для чего чёткость не нужна, зато нужно очень быстро реагировать на малейшие изменения. Поэтому там и мерцание лучше обнаруживается. Некоторые боковым зрением мерцание ЖК мониторов видят (60 Гц). Там ещё и реакция быстрее.
                            Цитата Jin X @
                            Я сделал движение с интервалом 20 мс – видно дёргание картинки
                            Частота развёртки какая? Строго говоря, картинка на экране обновляется только при его перерисовке с частотой 60 Гц. Поэтому обновление кадра, если отношение частоты времени отрисовки к периоду развёртки где-то между 0.5 и 2 обычно лучше привязать к кадровой развёртке. Это не имеет значения на мониторах с высокой частотой кадров.
                              Цитата 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 Гц.
                                Цитата amk @
                                Некоторые боковым зрением мерцание ЖК мониторов видят (60 Гц). Там ещё и реакция быстрее.
                                Я совсем боковым вижу и 70 Гц-мерцание на ЭЛТ монике. :blush:
                                0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                0 пользователей:


                                Рейтинг@Mail.ru
                                [ Script execution time: 0,0464 ]   [ 18 queries used ]   [ Generated: 28.03.24, 16:51 GMT ]