Модераторы: Snowy, Alexeis, MetalFan

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> GDI+, Direct2D, firemonkey и все все все 
:(
    Опции темы
gonzales
Дата 29.5.2013, 16:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 241
Регистрация: 13.3.2006

Репутация: 1
Всего: 2



Доброго времени суток, уважаемые форумчане!
Вопрос выбора технологии для отрисовки 2D графики. 
Необходимые функции
1. отрисовка растров с прозрачностью
2. возможность работы в альфаканалом: использовать для изображения альфаканал из стороннего файла
3. антиалайсинг
4. слои
5. поддержка windows xp

Сейчас проект реализован на GDI+, но все работает достаточно медлено. Например пересчет изображения с учетом полупрозрачной маски уменьшает производительность с 94 до 43 fps, но это полбеды. Эта отрисовка происходит во внутренний буфер, а когда я делаю repain, то есть вывожу содержимое буфера на экран, fps падает до 7-10, а это уже очень критично. 

Вопросов собственно несколько, может кто-то сталкивался.
1. можно ли выводить битмап на канву быстрее чем 
Код

graphicsGDIPlus := TGPGraphics.Create(canvas.Handle);
 graphicsGDIPlus.DrawImage(bmpcrop, TGPRectf.Create(r1.X, r1.Y, bmpcrop.GetWidth, bmpcrop.GetHeight),
            // destination rectangle
            0, 0, // upper-left corner of source rectangle
            bmpcrop.GetWidth, // width of source rectangle
            bmpcrop.GetHeight, // height of source rectangle
            UnitPixel, ImageAttributes);
repaint;


2. Можно ли каким-то образом прикрутить к GDI+ аппаратную акселерацию.

3. Можно ли использовать D2D для вывода, а GDI+ для обработки изображения одновременно

В общем, задача несколько размыта, надеюсь на Ваши мысли
Заранее спасибо
--------------------
- мастер, мастер, запорол..., все четыре запорол!!!- я ж тебе только три давал!!!???- да я и образец запорол!!!!
PM MAIL   Вверх
Beltar
Дата 29.5.2013, 17:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 627
Регистрация: 11.1.2006

Репутация: 1
Всего: 7



GLScene, Asphyre Sphinx или иной движок. Сфинкс поддерживает даже DX11, а я на нем недавно вариацию Lines сделал, на полностью заполненном поле из 240 клеток с 4-хцетными градиентными шарами у меня 200+ fps тянуло, но на днях автор объявил о закрытии проекта, ссылаясь на занятость, так что неясно что с ним будет. :( D2D под XP не работает. Вообще.
Слои, я так понимаю, та же прозрачность? В Corel Photo Paint, например, такого понятия как слой вообще нет, есть просто объекты, которыые от фотошоповых слоев неотличимы.


--------------------
Опытный программист на C++ легко решает любые не существующие в Паскале проблемы. smile(с) я, хотя может и нет
Пищущий на C++ мужик. Даже если это мужик сидит в написанном на Delphi и жрущем паскалевскую библиотеку билдере.
PM MAIL   Вверх
gonzales
Дата 29.5.2013, 21:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 241
Регистрация: 13.3.2006

Репутация: 1
Всего: 2



спасибо, покопаюсь.
а есть ли какая инфа по d2d? я так понял, что firemonkey приложения по умолчанию d2d используют.

Добавлено @ 21:43
еще вопросик, по сфинксу можете что-нибудь посоветовать, литературу, примеры
заранее спасибо
кстати, написанные приложения работают на xp?

Это сообщение отредактировал(а) gonzales - 29.5.2013, 21:47
--------------------
- мастер, мастер, запорол..., все четыре запорол!!!- я ж тебе только три давал!!!???- да я и образец запорол!!!!
PM MAIL   Вверх
Beltar
Дата 29.5.2013, 22:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 627
Регистрация: 11.1.2006

Репутация: 1
Всего: 7



D2D это DirectX. Fire Monkey принципиально OpenGL иначе никакой кроссплатформенности не будет. Литература есть по DirectX, гугл решает.

По сфинксу литературы я не видел. Однако там сами исходники очень грамотно написаны и откомментированы. В простейшем случае просто берешь какой-нибудь из примеров, идущих с ним, выкидываешь, оттуда рисовку, загружаешь свои ресурсы (помимо графики он поддерживает создание упакованных ресурных и сеть) и просто вызываешь в ProcessEvent свою обработку логики, а в RenderEvent свою отрисовку. Таймер с синхронизацией там уже готовый. Если игровой подход, когда игра просто шпарит кадры насколько может, периодически вызывая обсчет логики не устраивает, то можно предельный fps ограничить и в принципе я так понимаю, просто отключить таймер и вызывать рисовку, как в GDI Refresh. Само 2D-рисование в принципе такое же, как в GDI, даже в чем-то проще, т. к. не надо 100500 свойств у канваса задавать и всякие буферные битмепы юзать, базовые примитивы есть, только есть тонкости, связанные со сбросом кеша рендеринга и просадкой fps. По крайней мере, это то, что я в простейшем 2D проекте заметил.

По GLScene ничего не скажу, но у нее есть русскоязычное сообщество.


--------------------
Опытный программист на C++ легко решает любые не существующие в Паскале проблемы. smile(с) я, хотя может и нет
Пищущий на C++ мужик. Даже если это мужик сидит в написанном на Delphi и жрущем паскалевскую библиотеку билдере.
PM MAIL   Вверх
Alexeis
Дата 30.5.2013, 08:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Амеба
Group Icon


Профиль
Группа: Админ
Сообщений: 11743
Регистрация: 12.10.2005
Где: Зеленоград

Репутация: 55
Всего: 459



Цитата(gonzales @  29.5.2013,  17:56 Найти цитируемый пост)
3. Можно ли использовать D2D для вывода, а GDI+ для обработки изображения одновременно

  D2D это будет Windows Vista+ . В XP эта технология не поддерживается официально.

Цитата(gonzales @  29.5.2013,  17:56 Найти цитируемый пост)
2. Можно ли каким-то образом прикрутить к GDI+ аппаратную акселерацию.

  Она и так там есть, как и в GDI, другое дело, какой уровень оптимизации. 

 Можно и на OpenGL сделать такой вывод, но там удобных средств нет, придется поизучать хорошо и своих преобразований чуток сделать. Зато OpenGL позволит рисовать на векторном контексте с гибким масштабированием. Но вообще и у OpenGL работа с растрами не на высоком уровне. 


--------------------
Vit вечная память.

Обсуждение действий администрации форума производятся только в этом форуме

гениальность идеи состоит в том, что ее невозможно придумать
PM ICQ Skype   Вверх
gonzales
Дата 30.5.2013, 11:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 241
Регистрация: 13.3.2006

Репутация: 1
Всего: 2



Beltar, спасибо!!!
буду пробывать


Alexeis, я писал в топике про просадку фпс при вызове repaint. Какая оптимизация еще может быть?
вот что пишут официально про d2d
Цитата

Direct2D is a hardware-accelerated, immediate-mode 2-D graphics API that provides high performance and high-quality rendering for 2-D geometry, bitmaps, and text. The Direct2D API is designed to interoperate with existing code that uses GDI, GDI+, or Direct3D.

то есть получается, что на вин7 автоматически уже используют новую систему рендеринга Direct2D, или же это надо дополнительно подключать в самом приложении и выводить уже явно через Direct2D. К сожалению такой инфы я не нашел

Это сообщение отредактировал(а) gonzales - 30.5.2013, 11:19
--------------------
- мастер, мастер, запорол..., все четыре запорол!!!- я ж тебе только три давал!!!???- да я и образец запорол!!!!
PM MAIL   Вверх
Beltar
Дата 30.5.2013, 12:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 627
Регистрация: 11.1.2006

Репутация: 1
Всего: 7



Мне года 3 назад советовали GDI+. Я попробовал, оказалось, что даже медленнее, чем GDI, по крайней мере на моей задаче. DirectX и, насколько я понимаю, OpenGL напрямую для 2D-графики использовать попахивает мазохизмом, т. к. они работают с вершинами и треугольниками, а базовых примитивов для 2D-графики там нет. Т. е. или сам их делай, или юзай готовый движок.

Я так понимаю, что D2D и есть такой движок, работал бы на XP, думаю, никто бы уже на GDI не писал.

Цитата

я писал в топике про просадку фпс при вызове repaint. Какая оптимизация еще может быть?


В случае Repaint ИМХО некорректно говорить об fps. Оно ведь рисуется 1 раз и потом может не перерисовываться сколь-угодно долго. Например, ты перетащишь форму, она не будет перерисована. Касательно тормозов и оптимизаций, то можно было код привести, что оптимизировать наверняка найдется.

Цитата

то есть получается, что на вин7 автоматически уже используют новую систему рендеринга Direct2D, или же это надо дополнительно подключать в самом приложении и выводить уже явно через Direct2D. К сожалению такой инфы я не нашел


Если приложение написано в эпоху Win9X и ничего кроме GDI не знает, то и юзать оно будет только GDI. От семерки тут ничего не зависит, она рисует каждое приложение так, как приложение запрашивает.


--------------------
Опытный программист на C++ легко решает любые не существующие в Паскале проблемы. smile(с) я, хотя может и нет
Пищущий на C++ мужик. Даже если это мужик сидит в написанном на Delphi и жрущем паскалевскую библиотеку билдере.
PM MAIL   Вверх
Alexeis
Дата 30.5.2013, 13:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Амеба
Group Icon


Профиль
Группа: Админ
Сообщений: 11743
Регистрация: 12.10.2005
Где: Зеленоград

Репутация: 55
Всего: 459



Цитата(gonzales @  30.5.2013,  12:15 Найти цитируемый пост)
Alexeis, я писал в топике про просадку фпс при вызове repaint. Какая оптимизация еще может быть?
вот что пишут официально про d2d

  Драйвера видео могут оптимизировать операции с растрами даже при использовании GDI . Насколько я помню самая быстрая GDI функция для обновления SetDIBitsToDevice . 


--------------------
Vit вечная память.

Обсуждение действий администрации форума производятся только в этом форуме

гениальность идеи состоит в том, что ее невозможно придумать
PM ICQ Skype   Вверх
gonzales
Дата 30.5.2013, 14:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 241
Регистрация: 13.3.2006

Репутация: 1
Всего: 2



Beltar, пробую юзать сфикса. с подгрузкой растров из файлов я разобрался, а вот со шрифтами какая-то лажа. Сфинкс позволяет юзать системные шрифты или только с подгрузкой имиджей из своего архива?

Цитата

В случае Repaint ИМХО некорректно говорить об fps. Оно ведь рисуется 1 раз и потом может не перерисовываться сколь-угодно долго. Например, ты перетащишь форму, она не будет перерисована. Касательно тормозов и оптимизаций, то можно было код привести, что оптимизировать наверняка найдется.

перерисовка произходит по mousemove с изменением параметров, поэтому приходится перерисовывать многократно.
код слишком громоздкий, поэтому не привожу


Alexeis, спасибо за наводку, буду пробывать.

--------------------
- мастер, мастер, запорол..., все четыре запорол!!!- я ж тебе только три давал!!!???- да я и образец запорол!!!!
PM MAIL   Вверх
Beltar
Дата 30.5.2013, 15:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 627
Регистрация: 11.1.2006

Репутация: 1
Всего: 7



Я так понял, что использует пререндеренные, утилита для их создания прилагается. Меня для игры вполне устроил шрифт из примера Shapes. Обычные я не пробовал.

Цитата

перерисовка произходит по mousemove с изменением параметров, поэтому приходится перерисовывать многократно.


В таких случаях часто можно разделить код на 2 части, рисование ресурсоемкой подложки (например сложное изображение, график и т. п., в общем основная часть) на битмепе, потом этот битмеп копируется на другой, а нем рисуются разного рода надписи, вспомогательные линии, и уже готовый рисунок копируется на канвас (ну можно и сразу на канвас копировать и по нему дорисовать, по обстановке). И соответствено в событиях мыши вызывается только быстрая дорисовка.


--------------------
Опытный программист на C++ легко решает любые не существующие в Паскале проблемы. smile(с) я, хотя может и нет
Пищущий на C++ мужик. Даже если это мужик сидит в написанном на Delphi и жрущем паскалевскую библиотеку билдере.
PM MAIL   Вверх
gonzales
Дата 30.5.2013, 17:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 241
Регистрация: 13.3.2006

Репутация: 1
Всего: 2



Цитата

В таких случаях часто можно разделить код на 2 части, рисование ресурсоемкой подложки (например сложное изображение, график и т. п., в общем основная часть) на битмепе, потом этот битмеп копируется на другой, а нем рисуются разного рода надписи, вспомогательные линии, и уже готовый рисунок копируется на канвас (ну можно и сразу на канвас копировать и по нему дорисовать, по обстановке). И соответствено в событиях мыши вызывается только быстрая дорисовка.


так тоже пробывал, создаю битмеп, на нем отрисовываю, потом копирую на canvas. Но все равно приходится вызывать repaint, иначе не перерисовывается. Может это из-за doublebuffer:=true? Или из-за того, что отрисовка происходит не в onPaint?
Код

  bufbtm:=TBitmap.Create;
  bufbtm.Width:=width;
  bufbtm.Height:=height;
  graphicsGDIPlus := TGPGraphics.Create(bufbtm.canvas.Handle);

//отрисовка на канве битмэпа

  bitblt(canvas.Handle,0,0,width,height,bufbtm.Canvas.Handle,0,0,SrcCopy);
  bufbtm.Free;
  repaint;





Это сообщение отредактировал(а) gonzales - 30.5.2013, 17:07
--------------------
- мастер, мастер, запорол..., все четыре запорол!!!- я ж тебе только три давал!!!???- да я и образец запорол!!!!
PM MAIL   Вверх
Beltar
Дата 30.5.2013, 17:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 627
Регистрация: 11.1.2006

Репутация: 1
Всего: 7



Я уже не помню, когда рисовал сразу по форме или чему-то еще, обычно делал свой контрол и у него просто перекрывал Paint. Repaint руками по идее вызывать не нужно, она сама вызывается при, например, Refresh.


--------------------
Опытный программист на C++ легко решает любые не существующие в Паскале проблемы. smile(с) я, хотя может и нет
Пищущий на C++ мужик. Даже если это мужик сидит в написанном на Delphi и жрущем паскалевскую библиотеку билдере.
PM MAIL   Вверх
Alexeis
Дата 30.5.2013, 18:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Амеба
Group Icon


Профиль
Группа: Админ
Сообщений: 11743
Регистрация: 12.10.2005
Где: Зеленоград

Репутация: 55
Всего: 459



Цитата(gonzales @  30.5.2013,  18:03 Найти цитируемый пост)
 Но все равно приходится вызывать repaint, иначе не перерисовывается. Может это из-за doublebuffer:=true? Или из-за того, что отрисовка происходит не в onPaint?

  Вполне вероятно. Лучше, если указать винде, что кусок области стал невалидным при помощи функции InvalidateRect , при этом желательно отключить очистку фона у окна. После вызова InvalidateRect винда сама вызовет OnPaint . Далее при помощи BeginPaint в обработчике OnPaint мы можем узнать какой же прямоугольник требует обновления и обновить только его. 


--------------------
Vit вечная память.

Обсуждение действий администрации форума производятся только в этом форуме

гениальность идеи состоит в том, что ее невозможно придумать
PM ICQ Skype   Вверх
gonzales
Дата 30.5.2013, 21:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 241
Регистрация: 13.3.2006

Репутация: 1
Всего: 2



Цитата

Я уже не помню, когда рисовал сразу по форме или чему-то еще, обычно делал свой контрол и у него просто перекрывал Paint. Repaint руками по идее вызывать не нужно, она сама вызывается при, например, Refresh.

конечно я тоже сделал свой)) наследник TImage. Но я не перекрывал paint а сделал свою процедуру DrawImage которую вызываю по MouseMove. Repaint или Refrash в данном случае значения не имеет. Подскажите, принципиально перекрывать Paint, есть какое-то кардинальное отличие от любой другой процедуры вызываемой  руками?
Как в таком случае должен выглядеть алгоритм перерисовки
OnMouseMove -> InvalidateRect -> OnPaint -> {отрисовка битмапа} -> SetDIBitsToDevice 

 
Цитата

Лучше, если указать винде, что кусок области стал невалидным при помощи функции InvalidateRect , при этом желательно отключить очистку фона у окна. После вызова InvalidateRect винда сама вызовет OnPaint

я правильно понимаю, что я должен вызвать InvalidateRect для всей области моего контрола и тем самым вызвать OnPaint?

Буду пробывать!

Кстати, SetDIBitsToDevice предполагает конвертацию из TBitmap в DIB, не даст ли это обратный эффект (ухудшения оптимизации)?

ЗЫ. Комрады, в любом случае спасибо, очень приятно обсуждать вопросы с нормальными людьми, ВинГрад один из немногих форумов, где можно получить реальную помощь  smile 
--------------------
- мастер, мастер, запорол..., все четыре запорол!!!- я ж тебе только три давал!!!???- да я и образец запорол!!!!
PM MAIL   Вверх
Beltar
Дата 30.5.2013, 23:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 627
Регистрация: 11.1.2006

Репутация: 1
Всего: 7



Ну я примерно вот так делал. Проект на XE3, но там бэкапы файла проекта для 2007 и XE лежат, а сам компонент будет работать даже в D7, если все inline убрать.

Производительность довольно высокая. У меня на Core Duo 2.66 даже в Debug версии строит график по 10 сериям с 1 728 010 точками примерно за 0.3 сек. Это полная отрисовка с примерно 148000 вызовами LineTo для 1920х1080. А так можно возить по нему мышкой, подлагивает, но не сильно, если зона рисования меньше, то лага может и не быть. Первый вариант Lines на GDI с 240 клетками у меня без лага полностью перерисовывался по MouseMove. Ты что-то не так, похоже, делаешь.



Присоединённый файл ( Кол-во скачиваний: 14 )
Присоединённый файл  AvgChart___копия.rar 22,54 Kb


--------------------
Опытный программист на C++ легко решает любые не существующие в Паскале проблемы. smile(с) я, хотя может и нет
Пищущий на C++ мужик. Даже если это мужик сидит в написанном на Delphi и жрущем паскалевскую библиотеку билдере.
PM MAIL   Вверх
Alexeis
Дата 31.5.2013, 10:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Амеба
Group Icon


Профиль
Группа: Админ
Сообщений: 11743
Регистрация: 12.10.2005
Где: Зеленоград

Репутация: 55
Всего: 459



Цитата(gonzales @  30.5.2013,  22:37 Найти цитируемый пост)
я правильно понимаю, что я должен вызвать InvalidateRect для всей области моего контрола и тем самым вызвать OnPaint?


  Неа, только для области под курсором. Если можно перерисовывать не все то желательно так и делать. 
Цитата(gonzales @  30.5.2013,  22:37 Найти цитируемый пост)
Кстати, SetDIBitsToDevice предполагает конвертацию из TBitmap в DIB, не даст ли это обратный эффект

  Эмм.. насколько я понимаю TBitmap это и есть DIB . По крайней мере TBitmap может быть DIB если ему установить PixelFormat . По идее, получается прямое рисование DIB на контекст безо всякого копирования.


--------------------
Vit вечная память.

Обсуждение действий администрации форума производятся только в этом форуме

гениальность идеи состоит в том, что ее невозможно придумать
PM ICQ Skype   Вверх
gonzales
Дата 31.5.2013, 16:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 241
Регистрация: 13.3.2006

Репутация: 1
Всего: 2



что то я совсем запутался, окончательно и бесповоротно((((((((
сделал я SetDIBitsToDevice все одно, пока repaint или refrash не вызову, изображение на экране не перерисовывается. 
перекрыл событие Paint для моего наследника TImage, написал банальное
Код

procedure TFrameImage.Paint;
begin
 inherited;
 showmessage('1');
end;

получаю 4 мессаджбокса, хотя процедура перерисовки DrawImage вызывалась 1 раз. Это может быть из-за того, что во время перерисовки на экране появляется вторая форма, частично закрывающая мой контрол?

Если я пишу 
Код

procedure TFrameImage.Paint;
begin
 inherited;
 DrawImage;
end;


то все навеки зависает.

Может я свойство какое у TImage не заполняю, что он так себя ведет?

Практически все реализовано как в примере AvgChart. Только там используется TCustomControl, а у меня TImage. 

убираю из функции DrawImage repaint и fps на уровне 50, но отрисовка идет не плавно а большими рывками, ставлю repaint, fps падает до 7 но отрисовка гораздо плавнее.(((




--------------------
- мастер, мастер, запорол..., все четыре запорол!!!- я ж тебе только три давал!!!???- да я и образец запорол!!!!
PM MAIL   Вверх
Beltar
Дата 31.5.2013, 20:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 627
Регистрация: 11.1.2006

Репутация: 1
Всего: 7



Между TImage и TCustomControl есть одно отличие, TImage не имеет дескриптора. Я, правда, не помню сейчас, почему я использовал именно TCustomControl, а не TGraphicControl, но что-то меня там не устроило. В принципе есть еще и компонент TPaintBox, Но это тоже GraphicControl. Попробуй тоже TCustomControl заюзать.

Paint должен вызываться автоматически при любой перерисовке, разворачивание окна, закрытие его части и т. п. Я не вижу смысла вызывать методы перерисовки кроме Refresh вручную.

Как ты fps мерял? В играх средне fps измеряется из-за непрерывности цикла отрисовки, тут-то цикла нету.

Это сообщение отредактировал(а) Beltar - 31.5.2013, 20:09


--------------------
Опытный программист на C++ легко решает любые не существующие в Паскале проблемы. smile(с) я, хотя может и нет
Пищущий на C++ мужик. Даже если это мужик сидит в написанном на Delphi и жрущем паскалевскую библиотеку билдере.
PM MAIL   Вверх
gonzales
Дата 1.6.2013, 12:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 241
Регистрация: 13.3.2006

Репутация: 1
Всего: 2



а у tcustomcontrol у меня возникли проблемы с прозрачным canvas. Изначально я и хотел сделать из TCustomControl контейнер, в который положить несколько TImage, которые будут как бы слоями с изображениями, но не смог добиться прозрачного фона. TImage уже предполагает работу с прозрачностью, поэтому я его и выбрал.
А fps меряю просто. Замеряю кол-во тактов в начале процедуры и в конце, делю на частоту процессора, получаю время работы процедуры. Ну а fps - это будет 1/время. Это конечно не средне-статистическое значение, но приблизительное представление оно дает, по крайней мере порядок величины.

Добавлено через 5 минут и 48 секунд
Цитата

Я не вижу смысла вызывать методы перерисовки кроме Refresh вручную.

как раз приходится вызывать вручную, чтобы избежать ненужных прорисовок объектов, когда из например частично перекрывают другие объекты. если я запихну процедуру отрисовки объекта в Paint то при любом перекрытии объекта он будет перерисован, хотя с ним никаких изменений не происводилось. 
--------------------
- мастер, мастер, запорол..., все четыре запорол!!!- я ж тебе только три давал!!!???- да я и образец запорол!!!!
PM MAIL   Вверх
Beltar
Дата 1.6.2013, 13:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 627
Регистрация: 11.1.2006

Репутация: 1
Всего: 7



Как-то слишком сложно. Если у тебя там нет непрерывной анимации, то для замера времени будет достаточно GetTickCount. Можно Stopwatch, т. к. GetTickCount дает значения с шагом 16. Но если у тебя рисуется за 100 мс, то тебе и этой точности хватит для оценки лага. Если есть анимация, то лучше заюзать Сфинкса и не думать о таймерах, 2D-графику он тебе даже на нетбуке, скорее всего, вытащит. Избыточные вычисления, если на сотни fps шпарить будет, забирая ядро целиком можно подавить ограничением fps. Да и фотошопы вроде уже давно за счет аппаратной отрисовки живут.

Заблокировать отрисовку можно просто добавив какое-то условие в ф-ию отрисовки, или в Paint перед ее вызовом. Сам вызов Paint ты не можешь контролировать, если приложение свернули, а затем развернули, то Paint будет вызван. Но вот само условие блокировки рисовки будет весьма нетривиальным. У меня в AvgChart ручной вызов перерисовки делается только в том случае, если были изменены данные и то можно с помощью BeginUpdate перекрыть это дело.

Опиши лучше, что рисуешь и в каком порядке. Не исключено, что и саму Paint можно свести к тупому вызову BitBlt, или как она там на канвасе, Draw вроде, а сложную часть запоминать на битмепе и уже ее перерисовывать вручную, если, например, добавился объект, или был сделан ресайз контрола.


--------------------
Опытный программист на C++ легко решает любые не существующие в Паскале проблемы. smile(с) я, хотя может и нет
Пищущий на C++ мужик. Даже если это мужик сидит в написанном на Delphi и жрущем паскалевскую библиотеку билдере.
PM MAIL   Вверх
Alexeis
Дата 1.6.2013, 14:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Амеба
Group Icon


Профиль
Группа: Админ
Сообщений: 11743
Регистрация: 12.10.2005
Где: Зеленоград

Репутация: 55
Всего: 459



Цитата(gonzales @  31.5.2013,  17:30 Найти цитируемый пост)
Может я свойство какое у TImage не заполняю, что он так себя ведет?

  TImage лучше совсем не трогать по вопросам сообщений. Надежнее обращаться к окну которое лежит ниже. Я бы вообще не использовал TImage. Этот класс предназначен для статических изображений. Эффективнее выводить графику прям на окно. 


--------------------
Vit вечная память.

Обсуждение действий администрации форума производятся только в этом форуме

гениальность идеи состоит в том, что ее невозможно придумать
PM ICQ Skype   Вверх
gonzales
Дата 3.6.2013, 13:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 241
Регистрация: 13.3.2006

Репутация: 1
Всего: 2



заменил repaint на paint, отрисовка заработала на несколько порядков быстрей, НО Paint не стирает содержимое а рисует поверх. Как в перекрытом методе Paint заставить его стереть изображение?

Рисую графический фрейм для изображения. см рисунок.
создаю его на основе TImage. прописал функции mousedown, mousemove, mouseup и drawimage.

По событиям мыши производятся все координатные вычисления, затем вызывается drawimage.


Код

constructor TFrameImage.Create(aowner: Tcomponent); // конструктор
begin
inherited Create(aowner);
//создаю буферный битмап
  bufbtm:=TBitmap.Create;
  bufbtm.PixelFormat:=pf32bit;
  bufbtm.Width:=width;
  bufbtm.Height:=height;
end;

procedure TFrameImage.FrameImageMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: integer);
begin
//вычисляю в какую точку фрейма ткнул пользователь
//присваиваю флаг
mouseclickflag:= 
end;

procedure TFrameImage.FrameImageMouseMove(Sender: TObject; Shift: TShiftState; X, Y: integer);
begin
//вычисляю новую геометрию фрейма
DrawImage;
end;

procedure TFrameImage.FrameImageMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: integer);
begin
 mouseclickflag := clno;
 DrawImage(true, Fdpi_limit);
end;

procedure TFrameImage.DrawImage;
begin
//рисую на канве контрола или на канве буферного битмапа
graphicsGDIPlus := TGPGraphics.Create({bufbtm.}canvas.Handle);
//-----
//--функции отрисовки---
//-----
// далее необходимо обновить контрол, чтобы изображение из буфера видеокарты отобразилось на экране
Repaint; //---> просадка fps
Paint; //----> зависает
end;

procedure TFrameImage.Paint;
begin
 inherited;
 canvas.Draw(0,0,bufbtm);  //если рисую на канве буферного битмапа вывожу его на экран.
end;







Присоединённый файл ( Кол-во скачиваний: 9 )
Присоединённый файл  Снимок.JPG 38,22 Kb
--------------------
- мастер, мастер, запорол..., все четыре запорол!!!- я ж тебе только три давал!!!???- да я и образец запорол!!!!
PM MAIL   Вверх
gonzales
Дата 3.6.2013, 13:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 241
Регистрация: 13.3.2006

Репутация: 1
Всего: 2



пробую внедрить флаг перерисовки, все равно канва не очищается
Код

procedure TFrameImage.Paint;
begin

 if paintflag=true then
  begin
 InValidateRect(Canvas.Handle,nil,true);
 Canvas.FillRect(Canvas.ClipRect);
 canvas.Draw(0,0,bufbtm);
 paintflag:=false;
  end;
 inherited;
end;


Это сообщение отредактировал(а) gonzales - 3.6.2013, 13:45
--------------------
- мастер, мастер, запорол..., все четыре запорол!!!- я ж тебе только три давал!!!???- да я и образец запорол!!!!
PM MAIL   Вверх
Beltar
Дата 3.6.2013, 14:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 627
Регистрация: 11.1.2006

Репутация: 1
Всего: 7



А она и не будет очищаться, просто залей ее цветом фона перед рисованием.

Код

Paint; //----> зависает


Говорю же, Paint вызывается автоматически.

Должно быть

Код

procedure Paint;
begin
inherited;
DrawImage;
end;


Ты сейчас все запутываешь только. В DrawImage должно быть описано как рисовать, а не когда. Для этого программа сама когда нужно Paint вызовет.

Вот у тебя на картинке рамка, ты за нее явно тянешь. У тебя только рамка тянется или само изображение тут же перерисовывается? Если только рамка, то кто мешает хранить изображение на битмепе, перерисовывая только разметку, как у меня с графиком и делается?


--------------------
Опытный программист на C++ легко решает любые не существующие в Паскале проблемы. smile(с) я, хотя может и нет
Пищущий на C++ мужик. Даже если это мужик сидит в написанном на Delphi и жрущем паскалевскую библиотеку билдере.
PM MAIL   Вверх
gonzales
Дата 3.6.2013, 15:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 241
Регистрация: 13.3.2006

Репутация: 1
Всего: 2



Код

Вот у тебя на картинке рамка, ты за нее явно тянешь. У тебя только рамка тянется или само изображение тут же перерисовывается? 

изображение тоже пееррисовывается.

Цитата

Ты сейчас все запутываешь только. В DrawImage должно быть описано как рисовать, а не когда.

Так у меня и описано. А когда перерисовывать решают события мыши. 

Я убрал явный вызов drawImage из событий мыши и написал
Код

procedure Paint;
begin
inherited;
DrawImage;
 Canvas.FillRect(Canvas.ClipRect);
 canvas.CopyRect(rect(0,0,width,height),bufbtm.Canvas,rect(0,0,width,height));
end;


и получил висяк, у меня бесконечно вызывается Paint, что вообще логично, получается рекурсия. 

Цитата

А она и не будет очищаться, просто залей ее цветом фона перед рисованием.

так я заливаю
Canvas.FillRect(Canvas.ClipRect);
и все равно не очищается.

--------------------
- мастер, мастер, запорол..., все четыре запорол!!!- я ж тебе только три давал!!!???- да я и образец запорол!!!!
PM MAIL   Вверх
gonzales
Дата 3.6.2013, 17:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 241
Регистрация: 13.3.2006

Репутация: 1
Всего: 2



я не понимаю как у тебя в примере все работает
Код

procedure TAvgChart.Paint;
begin
  inherited;
Draw;  // рисование
end;

procedure TAvgChart.Draw;
var T:Cardinal;
begin
if BlockPaint then Exit;
DoBeforeReapint;
T:=GetTickCount;
DeltaX:=FMaxXValue-FMinXValue;//глобальный DeltaX, для ValueToPoint
DrawZoneX:=Width-LeftBorder-RightBorder;
DrawZoneY:=Height-TopBorder-BottomBorder;
DrawTrends;
FastRepaint;//Дорисовка
FDrawTime:=GetTickCount-T;
DoAfterRepaint;
end;

procedure TAvgChart.FastRepaint;
begin
if BlockPaint then Exit;
Canvas.Pen.Mode:=pmCopy;
if Assigned(Bmp1) then Bmp1.Free;
Bmp1:=TBitmap.Create;
Bmp1.Width:=Width;
Bmp1.Height:=Height;
Bmp1.Canvas.Draw(0,0,Bmp);
if FSetsRectangles then DrawRectangles;
DrawAxes;
DrawValueLines;
if FInSelection then DrawSelection;
Canvas.Draw(0,0,Bmp1);
end;



у тебя по paint вызывается draw, в котором сидит fastrepaint, в котором изменяется канва Canvas.Draw(0,0,Bmp1);
соответственно опять должно автоматически вызваться Paint и опять же рекурсия. Но я так понимаю, этого не происходит. Можешь объяснить, почему?
--------------------
- мастер, мастер, запорол..., все четыре запорол!!!- я ж тебе только три давал!!!???- да я и образец запорол!!!!
PM MAIL   Вверх
Beltar
Дата 3.6.2013, 19:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 627
Регистрация: 11.1.2006

Репутация: 1
Всего: 7



Зачем? Paint вызывается или автоматом, когда контролу надо перерисоваться (типичный случай, разворот приложения, или изменение размеров контрола), или если контролу был сделан принудительный Refresh. Но к низкоуровневым функциям, которые переводят байты канваса в пиксели монитора она никакого отношения не имеет. У TCustomControl Paint ЕМНИП вообще пустая. Обработка мыши у меня прописана в самом контроле и вызывает только быструю упрощенную прорисовку. Попросту Paint это метод, который должен осуществлять полную прорисовку по умолчанию.

В твоем случае рисование тоже разделяется на 2 части: сами картинки и пользовательская разметка.

http://biblioteka.cc/index.php?newsid=30955 стр 75. ЕМНИП Repaint как раз и вызывает Paint.


--------------------
Опытный программист на C++ легко решает любые не существующие в Паскале проблемы. smile(с) я, хотя может и нет
Пищущий на C++ мужик. Даже если это мужик сидит в написанном на Delphi и жрущем паскалевскую библиотеку билдере.
PM MAIL   Вверх
gonzales
Дата 5.6.2013, 13:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 241
Регистрация: 13.3.2006

Репутация: 1
Всего: 2



Цитата

Но к низкоуровневым функциям, которые переводят байты канваса в пиксели монитора она никакого отношения не имеет.

если не имеет, то я не понимаю, почему у меня все время вызывается paint, если я использую 
Код

procedure Paint;
begin
inherited;
DrawImage;
end;


получается у меня где-то в drawimage вызывается paint?
--------------------
- мастер, мастер, запорол..., все четыре запорол!!!- я ж тебе только три давал!!!???- да я и образец запорол!!!!
PM MAIL   Вверх
gonzales
Дата 5.6.2013, 13:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 241
Регистрация: 13.3.2006

Репутация: 1
Всего: 2



НАШЕЛ!!!
методом научного тыка выяснил
функция Canvas.FillRect(Canvas.ClipRect); в DrawImage вызывает Paint
осталось понять, как очистить канву не используя FillRect


--------------------
- мастер, мастер, запорол..., все четыре запорол!!!- я ж тебе только три давал!!!???- да я и образец запорол!!!!
PM MAIL   Вверх
Beltar
Дата 5.6.2013, 15:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 627
Регистрация: 11.1.2006

Репутация: 1
Всего: 7



А ты там брейкпойнт не ставишь, так что приложение переключается нна IDE, а потом обратно и снова рисуется?


--------------------
Опытный программист на C++ легко решает любые не существующие в Паскале проблемы. smile(с) я, хотя может и нет
Пищущий на C++ мужик. Даже если это мужик сидит в написанном на Delphi и жрущем паскалевскую библиотеку билдере.
PM MAIL   Вверх
gonzales
Дата 5.6.2013, 16:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 241
Регистрация: 13.3.2006

Репутация: 1
Всего: 2



у меня два экрана, я вижу, что оно Paint постоянно вызывается
Код

procedure TFrameImage.Paint;
begin
 inherited Paint;
 Canvas.Brush.Style := bsClear;
 Canvas.FillRect(ClientRect);
end;

вот такой код приводит к цикличности. 

Это сообщение отредактировал(а) gonzales - 5.6.2013, 16:06
--------------------
- мастер, мастер, запорол..., все четыре запорол!!!- я ж тебе только три давал!!!???- да я и образец запорол!!!!
PM MAIL   Вверх
Beltar
Дата 5.6.2013, 18:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 627
Регистрация: 11.1.2006

Репутация: 1
Всего: 7



Это проблема не заливки, а базового класса, у меня все работает именно потому что TCustomControl. При наследовании от TImage тоже загрузка проца в 100% вечным циклом. Попробуй унаследоваться от TGraphicControl, который обычно и юзают для своих компонентов, которым не надо оконного дескриптора, с ним у меня все правильно работает и ничего не виснет, а что там у TImage уже сделано смотреть надо.


--------------------
Опытный программист на C++ легко решает любые не существующие в Паскале проблемы. smile(с) я, хотя может и нет
Пищущий на C++ мужик. Даже если это мужик сидит в написанном на Delphi и жрущем паскалевскую библиотеку билдере.
PM MAIL   Вверх
gonzales
Дата 6.6.2013, 10:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 241
Регистрация: 13.3.2006

Репутация: 1
Всего: 2



Beltar, спасибо большое! В общем и целом понятно. Буду пробывать TGraphicControl
--------------------
- мастер, мастер, запорол..., все четыре запорол!!!- я ж тебе только три давал!!!???- да я и образец запорол!!!!
PM MAIL   Вверх
gonzales
Дата 5.7.2013, 15:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 241
Регистрация: 13.3.2006

Репутация: 1
Всего: 2



Beltar, прошу помощи. 
Я переделал компонент на TGraphicControl, соответственно 
Код

procedure TFrameImage.Paint;
  begin
    inherited Paint;
    DrawImage;
  end;


но заметил одну особенность, если у меня на форме несколько компонентов TFrameImage, то при изменении одного, перерисовываются все, то есть Paint срабатывает для всех, даже если они не перекрываются. Соответственно при сложных перерисовках и большом кол-ве компонентов опять имею тормоза. Как заставить перерисовываться только компонент, с которым сейчас производятся манипуляции? 
пробывал внедрять флаг needrepaint
Код

procedure TFrameImage.Paint;
  begin
    inherited Paint;
    if needrepaint=true then
    DrawImage(true, 1);
    needrepaint:=false;
  end;

но получаю следующее: компонент с которым работаю перерисовывается, а все остальные при этом пропадают, становятся прозрачными.







--------------------
- мастер, мастер, запорол..., все четыре запорол!!!- я ж тебе только три давал!!!???- да я и образец запорол!!!!
PM MAIL   Вверх
Gwire
Дата 29.7.2013, 09:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 216
Регистрация: 7.8.2007
Где: Николаев

Репутация: 1
Всего: 4



gonzales, я на GDI+ делал стрелочный индикатор.
И заметил интересную особенность если перерисовывать на холсте TWinControl (скажем TPanel) c размером, подогнанным под то, что собираешься рисовать,
то производительность заметно увеличивается (в сравнении, если рисовать прямо на холсте TForm)

По поводу оптимизации подумай, что у тебя статичное и рисуй его в на холсте буферного TBitmap.
B момент перерисовки просто "печатай" с помощью BitBlt(), а после дорисуй динамические элементы.
Например: В Индикаторе шкала ёмкая но статичная. Стрелка динамическая но она одна =)

Если я правильно понял у тебя графические объекты которые нужно перемещать по форме.
Здесь есть "захваченный" и "остальные". Так вот "остальные" - это статика. В TBitmap рисуешь все кроме "захваченного".
А захваченный рисуешь уже на TWinControl.

По другому еще можно  для каждого графического объекта сделать "обертку" на основе TGraphicControl, 
тогда - что и когда перерисовывать будет "думать" система. 

- - - - - -
PS: Если конечно графические объекты у тебя сами не "шевелятся".
Хотя я думаю и там можно найти статику. smile

- - - - - -
PPS: Не увидел вторые станицы, на которой рассмотрены некоторые моменты smile

Это сообщение отредактировал(а) Gwire - 29.7.2013, 09:26
PM MAIL   Вверх
Beltar
Дата 12.10.2013, 22:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 627
Регистрация: 11.1.2006

Репутация: 1
Всего: 7



Хм-м. Похоже, что из-за TGraphicControl и перерисовка всех, он ведь своей канвы не имеет и рисуется поверх винконтрола на котором лежит. Т. е. нужен все-таки кто-то с дескриптором вроде TCustomControl.


--------------------
Опытный программист на C++ легко решает любые не существующие в Паскале проблемы. smile(с) я, хотя может и нет
Пищущий на C++ мужик. Даже если это мужик сидит в написанном на Delphi и жрущем паскалевскую библиотеку билдере.
PM MAIL   Вверх
Страницы: (3) [Все] 1 2 3 
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: Звук, графика и видео"
Girder
Snowy
Alexeis

Запрещено:

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делится вскрытыми компонентами

  • Литературу по Дельфи обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Дельфи
  • По вопросам разработки игр стоит заглянуть сюда

FAQ раздела лежит здесь!


Если Вам помогли и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, Girder, Snowy.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Delphi: Звук, графика и видео | Следующая тема »


 




[ Время генерации скрипта: 0.1549 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.