Конференция "Игры" » Быстрый канвас [Delphi, Windows, ХР]
 
  • DomiNickDark (20.03.09 13:44) [120]
    Интересный исходник от "Farbrausch" на Assembler'е:

    Http://DomiNickDark.Narod.Ru/DemoScenes/Farbrausch/Demos/fr-0.1-source.txt

    Никто не знает для какого он компилятора? (Tasm и Fasm не компилируют)
  • Вася (22.03.09 22:35) [121]
    >>> При тестировании (на 1024х1024) сбоку слева недорисовывалась часть битмапа... Белая полоска получалась...
    >>> Поменял "until x<=0;" на "until x<0;" - стало нормально... :)

    DomiNick, Pavia, я правильно понял что в "Procedure Draw2_7;" желательно чтоб "Bitmap.Width" было кратно 4-м?
    А то тогда снова та белая полоска сбоку появляется (даже при "until x<0;")...

    Меня тут на одном форуме программистов научили считать время выполнения кода... Меряю время  вот так:

    procedure TForm1.Button1Click(Sender: TObject);
    var i, iTick: Integer;
    begin
    SetThreadPriority(GetCurrentThread, THREAD_PRIORITY_TIME_CRITICAL);
    iTick:=GetTickCount;
    for i:=0 To 50 Do
       begin
       draw2_7;
       end;
    form1.caption:=inttostr(GetTickCount-iTick);
    SetThreadPriority(GetCurrentThread, THREAD_PRIORITY_NORMAL);
    end;

    Правильно?

    DomiNick, при
    BitBlt(Form1.Canvas.Handle, 0, 0, 1024, 1024, Bitmap.Canvas.Handle, 0, 0, SrcCopy);
    заместо
    Form1.Canvas.Draw(0, 0, Bitmap);
    это время как-то чаще "прыгает"... Но бывает и быстрее...

    Посоветуйте как лучше...
  • Pavia © (23.03.09 13:07) [122]

    > желательно чтоб "Bitmap.Width" было кратно 4-м?

    Обязательно. Если нужно можно переделать код вначале блоками по 4 потом то что в конце осталоь по 1-3.
    На данный момент он хвост просто не будет обробатывать. Ничего страшного. За исключением случая Bitmap.Width <4


    > Меня тут на одном форуме программистов научили считать время
    > выполнения кода... Меряю время  вот так:

    GetTickCount имеет не хорошую особенность. Его счетчик в среднем увеличивается раз в 16 мс и сразу на 16мс. те.
    Вместо
    01 02 03 04 ... 13 14 15 16 17 18 19 20 21 ... 31 32 33
    Будет
    00 00 00 00 ... 00 00 00 16 16 16 16 16 16 ... 16 32 32.
    Так что время измерения должно привышать 16мс, а точнее что бы такая ошибка довала 1% нужно 1,6 секунды

    А еще что-бы никто не перебивал нашу программу. Для этого ставим.
    SetPriorityClass( GetCurrentProcess,REALTIME_PRIORITY_CLASS);
    SetThreadPriority(GetCurrentThread,THREAD_PRIORITY_TIME_CRITICAL);

    При этом гарантированное время без перебойной работы состовляет 4с. Потом идет перепланирование которое может передать управление другому процессу. Ничего страшного в этом нет. Но лучшии показатели будут в приделах 1-4с.

    Я то мерию через

    function RDTSC: Int64; register;
    asm
    RDTSC
    end;


    Но тут нюансов больше зато точнее. Можно более короткии промяжутки мерить. И быстрее. Давно хочу написать стать по измерению времени на компьюторе. Как только данных наберу побольше.
  • Вася (24.03.09 04:46) [123]
    А насчёт "BitBlt(Form1.Canvas.Handle, 0, 0, 1024, 1024, Bitmap.Canvas.Handle, 0, 0, SrcCopy);" и "Form1.Canvas.Draw(0, 0, Bitmap);" ?
    Что лучше и в чём разница?
  • Б (24.03.09 08:21) [124]
    - BitBlt - быстрая функция блиттинга GDI, где последний флаг - режим блиттинга. Обычно SrcCopy - копирование.
    - Canvas - это просто удобная обёртка под GDI-функции (См. исходники). Например, чтобы нарисовать линию нужно просто указать  цвет пера и координаты концов отрезка и не надо мучаться с созданием пера, получение контекста устройства, его выделением... и т.д.
    Режим блиттинга устанавливается в CopyMode. (По умолчанию копирование).
    Если нужно воспользоваться только блиттингом, то BitBlt - быстрее.
    Есть ещё StretchBitBlt - только изображение уже масштабируется.
  • AutoBOT (25.03.09 21:55) [125]
    BitBlt() - это функция из библиотеки GDI, Виндовоз через нее отрисовывает. Работает просто:

    var DCs: HDC;
    ...
    // контекст главной формы
    DCs := GetDC(Form1.Handle);
    // отрисовка в форму
    BitBlt(DCs, 0, 0, Form1.Width, Form1.Height, {битмап}.Canvas.Handle, 0, 0, SRCCOPY);
    // освобождаем контекст, убиваем
    ReleaseDC(Form1.Handle, DCs);
    DeleteDC(DCs);



    Через BitBlt() готовый буферный кадр выводится прям на форму, 30 кадров в секунду обеспечивает всегда, у меня 64 кадра, ...скорость зависит от обработки в цикле...

    P.S.
    Кто знает, SetDIBitsToDevice() в реале быстрее отправит графические данные на форму чем BitBlt()? ...тесты что-то не показывают разницы, на моем компе одинаковая скорость...
  • antonn © (25.03.09 22:44) [126]
    обычно затык происходит не во время отображения буфера, а во время его формирования, bitblt очень быстрая вещь и искать быстрее смысла особого нет.
  • Вася (27.03.09 14:02) [127]
    DoniNick, этот код для Nasm'а... ;)

    >>> обычно затык происходит не во время отображения буфера, а во время его формирования, bitblt очень быстрая вещь и искать быстрее смысла особого нет

    Так я же и говорю - на моём компе разницы по скорости между "BitBlt(...)" и "Canvas.Draw(...)" практически нету... :(
    Может есть другие способы?

    А "SetDIBitsToDevice(...)" у меня что-то непонятное требует... Как им пользоваться-то?
  • antonn © (27.03.09 22:47) [128]

    > Так я же и говорю - на моём компе разницы по скорости между
    > "BitBlt(...)" и "Canvas.Draw(...)" практически нету... :
    > (
    > Может есть другие способы?

    Так вот я и говорю - а зачем еще быстрее, если обычно бутылочное горлышко не в выводе битмапа на канву? :)

    PS у канвы в реализации используется все тот же bitblt() (ну и для масштабирования аналогичная)
  • Вася (28.03.09 00:53) [129]
    Мда?..

    А помните я писал функцию для Делфи на Ассемблере для ускоренного вычисления синуса?..
    Никто не разобрался как она работает и можно ли увеличить точность выдаваемого значения?..
  • DomiNickDark (28.03.09 19:12) [130]
    > DoniNick, этот код для Nasm'а... ;)

    О_О...

    Пасибо.....

    > Давно хочу написать стать по измерению времени на компьюторе.
    >  Как только данных наберу побольше.


    Pavia, когда это свершится дадите ссылку на статью..? ;)
  • DomiNickDark (31.03.09 00:20) [131]
    >>>   >>> Даже если поставить Timer.Interval:=1; то он всё равно будет вызываться примерно раз в 55 миллисекунд, а не раз в 1
    >>> Так и есть, хотя для некоторых случаев 18-20 FPS хватает.
    >>> Если нужно быстрее - используй Application.OnIdle с Done = False (см. справку).

    Справка на англицком... Не смог разобраться... :(
    Делфи говорит неправильная процедура...

    А кстати если таймер максимум "примерно раз в 55 миллисекунд, а не раз в 1", то как будет себя вести этот "Application.OnIdle с Done = False"?
  • @!!ex © (31.03.09 07:25) [132]
    > [131] DomiNickDark   (31.03.09 00:20)
    > А кстати если таймер максимум "примерно раз в 55 миллисекунд,
    > а не раз в 1", то как будет себя вести этот "Application.OnIdle
    > с Done = False"?

    Эти две вещи не связаны.
    OnIdle - событие ничегонеделанья, не связано с таймером.
  • Xandr001 (31.03.09 08:03) [133]
    вот тут:

    URL:: http://heanet.dl.sourceforge.net/sourceforge/graphics32/graphics32-1-8-3.7z
    Размер:: 1,7 MБ (1 774 699 байт)

    Быстрый канвас. где-то в примере про спрайты есть проект где используется ОнИдл. Вообще библиотека избавляет от многих "рисовальных" проблем.
  • Б (31.03.09 15:14) [134]

    > Справка на англицком... Не смог разобраться... :(
    > Делфи говорит неправильная процедура...


    Например так:
    1) Обработчик TApplicationEvents.OnIdle.
    2) Типа такого:

    Procedure TForm1.Idle(Sender: TObject; var Done: boolean);
    begin
      // Анимация.
    End;

    Procedure TForm1.FormCreate(Sender: TObject);
    begin
     Application.OnIdle:= Idle;
    End;



    P.S. Выводит быстрее таймера, даже не видно как воспроизводится анимация.
  • DomiNickDark (31.03.09 21:06) [135]
    Благодарствую... Будем пробовать... :)

    > Эти две вещи не связаны.
    > OnIdle - событие ничегонеделанья, не связано с таймером.


    А как тогда объясняется срабатывание быстрее таймера? И известно ли насколько быстрее?

    З.Ы. Таймер умудряется работать как бы параллельно с основной прогой - он чтоли как бы отдельный поток для себя создаёт..?
  • Sapersky (31.03.09 22:57) [136]
    OnIdle - событие ничегонеделанья, не связано с таймером.

    На самом деле в TApplication.HandleMessage/ProcessMessage фактически аналог игрового цикла на PeekMessage:
    If PeekMessage then <обработать> else OnIdle;
    Если в OnIdle установить Done := True - Application "впадает в спячку" (WaitMessage), при Done := False будет крутиться постоянно.

    А кстати если таймер максимум "примерно раз в 55 миллисекунд, а не раз в 1", то как будет себя вести этот "Application.OnIdle с Done = False"?

    Крутиться с макс. доступной скоростью (и загрузкой процессора 100%), что обычно и требуется графическим демкам/играм. Правда, скорость анимации придётся подстраивать под текущий FPS.
    Если хочется "притормозить" - можно поставить Sleep (имеет смысл ставить c интервалом кратным 10 мс, оно всё равно округляется).

    З.Ы. Таймер умудряется работать как бы параллельно с основной прогой - он чтоли как бы отдельный поток для себя создаёт..?

    Обычный - не создаёт (шлёт сообщения WM_TIMER). Создаёт мультимедиа-таймер (и поэтому ему доступны интервалы меньше чем 50 мс). Но по-моему проще OnIdle со Sleep.
  • Sapersky (31.03.09 23:11) [137]
    Вообще есть способ повысить дискретность Sleep до 1 мс:
    http://www.dtf.ru/articles/read.php?id=39888&page=2
    но это, скажем так, способствует повышению общей тормознутости Windows, поскольку система будет в 10 раз чаще отвлекаться на системные задачи (читать в статье про quantum и прочее).
  • Б (01.04.09 06:35) [138]
    2 Sapersky
    > при Done := False будет крутиться постоянно.

    У меня почему то, анимация через некоторое время останавливается. Почему?

    > Если хочется "притормозить" - можно поставить Sleep

    Я не использую Sleep, это как то тупо. Он простанавливает работу всего потока? Программы?
    Лучше в OnIdle запоминайте системное время.
  • @!!ex © (01.04.09 09:48) [139]
    > [138] Б   (01.04.09 06:35)
    > У меня почему то, анимация через некоторое время останавливается.
    > Почему?

    Код кривой.


    > [138] Б   (01.04.09 06:35)
    > Я не использую Sleep, это как то тупо. Он простанавливает
    > работу всего потока? Программы?

    НЕ тупо. Позволит одновременно контролировать скорость рендера и при этом не жрать 100% проц времени.
    Останавливает работу потока в котором вызван.
 
Конференция "Игры" » Быстрый канвас [Delphi, Windows, ХР]
Есть новые Нет новых   [118764   +87][b:0.001][p:0.001]