Демка на основе спирографа

Тема в разделе "WASM.GUI", создана пользователем Intro, 28 окт 2024.

Метки:
  1. Intro

    Intro Active Member

    Публикаций:
    0
    Регистрация:
    29 авг 2009
    Сообщения:
    638
    Вот код пока не окончательный, нет кнопок сворачивания и закрытия. Закрыть можно панели задач и Alt+F4
    Сделал на основе:

    Там же в архиве версия и для браузера.
     

    Вложения:

    alex_dz нравится это.
  2. Intro

    Intro Active Member

    Публикаций:
    0
    Регистрация:
    29 авг 2009
    Сообщения:
    638
    Демка не только демка, просто как демка проще версия для браузера. В общем, хотелось сделать шаблон кода для разных демок в том числе версии демок для дос. Использую GdipBitmapSetPixel, нарисовать пиксель в буфере, всё ничего, вот только эта функция весьма тяжёлая, от 1 до 3 тысяч тактов выполняется, если нам надо отрисовать каждый пиксель сцены то тут уже никакой динамики не получиться, 1-2 млн * 1..3 тыс = 0.2..1 сек. Варианты есть, если получить доступ непосредственно к массиву пикселей, то рисовать пиксели можно на скорости несколько тактов, ну ладно 10-20 тактов. Всё равно у нас буфер в ОЗУ, а не в видеопамяти.
    Я как понял, доступ к буферу можно получить GdipBitmapLockBits, но пока не понятно дели реализации. Кстати, сам код UpdateScene без GdipBitmapSetPixel выполняет несколько сот тактов, может чуть больше 1000, оптимизировать можно синусы если флагами задать минимальную точность float/real4.
     
  3. Thetrik

    Thetrik UA6527P

    Публикаций:
    0
    Регистрация:
    25 июл 2011
    Сообщения:
    888
    Используй буфер и создавай битмап через GdipCreateBitmapFromScan0. Также быстрее будет использовать DIB-секцию, либо просто буфер и выводить его через SetDiBitsToDevice.
     
  4. Intro

    Intro Active Member

    Публикаций:
    0
    Регистрация:
    29 авг 2009
    Сообщения:
    638
    Thetrik, а может лучше использовать SetDIBits? Параметров надо вводить меньше. Пока не получается создать локальный буфер, как то сложно сделано. SetBitmapBits не работает как надо.
     
  5. Intro

    Intro Active Member

    Публикаций:
    0
    Регистрация:
    29 авг 2009
    Сообщения:
    638
    В общем заработало, ошибки были в неожиданном месте, например в макросе mrm. Так же надо было настроить структуру BITMAPINFO
    Код (ASM):
    1. mov    scene.bmiBuff, GlobalAlloc(GPTR, sizeof_BITMAPINFO)
    2. ASSUME ecx:ptr BITMAPINFO
    3. mov    ecx, eax
    4. mov    [ecx].bmiHeader.biSize, sizeof BITMAPINFOHEADER
    5. mrm    [ecx].bmiHeader.biWidth, scene.iBuffWidth
    6. mov    eax, scene.iBuffHeight
    7. neg    eax
    8. mov    [ecx].bmiHeader.biHeight, eax
    9. mov    [ecx].bmiHeader.biPlanes, 1
    10. mov    [ecx].bmiHeader.biBitCount, 32
    11. mov    [ecx].bmiHeader.biCompression, BI_RGB
    12. mrm    [ecx].bmiHeader.biSizeImage, scene.iSizeBuff
    13. ASSUME ecx:nothing
    14. ....
    15. UpdateTexture MACRO scene:req
    16.     SetDIBits(scene.hdcBuffForm, scene.bmBuff, 0, scene.iBuffHeight, scene.lpvBuffBits, scene.bmiBuff, DIB_RGB_COLORS)
    17.     EXITM <>
    18. ENDM
    Заполняем наш локальный массив пикселей и копируем его UpdateTexture в буфер, который затем рисуем в окно. На очень дохлом ПК фэпес без рендера анимации 262, а было один, да один ФПС. ПэКа: проц Core 2 Duo E7500 2.93 ГГц, видео интегрированное очень слабое. В общем нашёл в мусорке на работе.
     
    Последнее редактирование: 2 апр 2025 в 10:16
  6. Thetrik

    Thetrik UA6527P

    Публикаций:
    0
    Регистрация:
    25 июл 2011
    Сообщения:
    888
    SetDIBits и SetBitmapBits обновляют данные в битмапе, но остается еще операция вывода на экран - т.е. получаем 2 действия.
    При использовании GdipCreateBitmapFromScan0 у нас уже есть буфер и мы рисуем в него как обычно и нам нужно только обновлять на экран - 1 операция.
    При использовании DIB-секции, мы также имеем буфер и выводим как обычно - 1 операция.
    При использовании SetDiBitsToDevice у нас также есть буфер который мы сразу выводим на экран - 1 операция.

    SetDIBits и SetBitmapBits - мы сначала копируем буфер в другой буфер (HBITMAP/DIBSECTION) - 1-я операция, а потом еще этот 2-й буфер выводим на экран (BitBlt/StretchBlt) - 2-я операция. Итого 2 операции вместо 1 и лишний буфер.
     
  7. Intro

    Intro Active Member

    Публикаций:
    0
    Регистрация:
    29 авг 2009
    Сообщения:
    638
    Thetrik, ну может так и быстрей. Я же говорю, я отключил генерацию сцены в буфер, т.е. гоняю пустой локальный буфер, экран чёрный, т.к. в локальном буфере нули, чёрный пиксели. И ФПС получаю 262-264, это очень много для такого драндулета(Intel GMA X4500), и на практике не нужно. Хотя вероятно с GdipCreateBitmapFromScan0 будет ещё быстрей, но это уже класс GDIplus, он у меня отделён от простого GDI, потом сделаю и с GDIplus. Главное у меня демка заработала, не эта, а с мандельбротом, и там ФПС всего 5.5, значит заморачиваться с оптимизацией рендера не имеет смысла, надо оптимизировать сам код мандельброта. А то медленновато что-то. А так же надо отрефакторить код, и сам классы, у меня типа ООП.
    --- Сообщение объединено, 2 апр 2025 в 16:39 ---
    Кстати, чего я стал использовать буфер, я так боролся с мерцанием, если что-то рисовать сразу в окно, то наблюдается мерцание. Хотя с локальным буфером может и не будет мерцание, но тогда я не смогу рисовать поверх что-то, типа текста или ещё чего.
     
    Последнее редактирование: 2 апр 2025 в 16:06