Russian Qt Forum

Qt => 2D и 3D графика => Тема начата: Vladimir от Апрель 22, 2013, 12:21



Название: Помогите с архитектурой графической части приложения
Отправлено: Vladimir от Апрель 22, 2013, 12:21
Доброго дня! Подскажите, какими средствами Qt можно добиться максимально быстрой скорости отрисовки следующей информации:
1.   матрицы данных (2400х4096, которая обновляется с периодичностью в 12 ms, т.е. по индексу от 0 до 4096 приходит массив новых данных размером 2400). Отрисовывать можно и нужно конечно реже.
2.   Сетки, которая меняется только при изменении масштаба.
3.   10-ки тыс.!!! меток в виде простых точек
4.   Сектора, полигоны, простые значки (квадратики, кружочки). В сумме пару 10ков.  
+ масштабирование, панорамирование.
Как пробовал реализовывать:
1.   На QGraphicsScene рисовать матрицу в отдельный items или drawBackground() в QImage и выводить painter->drawImage(). Заполнял QImage по индексу setPixel(). Заполняется/рисуется довольно шустро, пока не начинаешь рисовать метки..
2.   Рисовать каждую метку в отдельным item оказалось вообще не вариант, начинает тормозить уже после пару тысяч объектов. Метку рисовал drawPoint(). Сделать один item на всю сцену и в нем циклом рисовать по нужным координатам все точки, тоже начинает тормозить, но уже после 10 тыс точек.. медленно.
Следующий вариант был рисовать поверх матрицы картинку QImage::Format_ARGB32_Premultiplied и в ней подсвечивать нужные пиксели имитирую метку… такой вариант как наиболее быстрый и предлагался в google по моей задаче. НО как только делался scale() QGraphicsView, то все останавливалось и именно из-за прозрачности картинки… без нее масштабируется все шустро!

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

3.   Естественно не обошел и OpenGL, пока на нем и остановился. Но пробовал выводить опять же в сцене на QGLWidget. В плане вывода меток да, рисует быстрее. Если в drawForeground() выводить 52 441 точек таким образом, то масштабирование осуществляется приемлемо
Код:
 
   for(double i = -80.0; i < 80; i+= 0.7)
          for(double j = -80.0; j < 80; j+= 0.7)
          {
                glColor3f(0.0,0.0,1.0);
                glPointSize(3);
                glBegin(GL_POINTS);
                    glVertex2f(i,j);
                glEnd();
          }
           но здесь возникает вопрос как вывести матрицу.. т.е. нужно как-то рисовать           картинку на QGLWidget. painter->drawImage() не пойдет потому что тормозит дико.. Пробовал выводить функцией glDrawPixels(), но не очень получилось.. вроде картинка рисовалась но в каких-то непонятных масштабах и непонятно как располагалась на сцене.  Может кто сведущ в OpenGL и может помочь?
Либо есть еще способы или я что-то делал не так. Буду рад любому совету! Прикреплю файл с последним тестовым проектом с OpenGL.
 


Название: Re: Помогите с архитектурой графической час&#
Отправлено: _OLEGator_ от Апрель 22, 2013, 12:31
Порекомендовал бы задействовать фильтрацию видимой информации. На маленьких масштабах точки могут сливаться и рисовать их всех не имеет смысла, нужно прореживать. Соответственно на больших масштабах не вся информация попадает на экран и фильтровать надо данные, попадающие за экран.


Название: Re: Помогите с архитектурой графической части приложения
Отправлено: Vladimir от Апрель 22, 2013, 12:39
Порекомендовал бы задействовать фильтрацию видимой информации. На маленьких масштабах точки могут сливаться и рисовать их всех не имеет смысла, нужно прореживать. Соответственно на больших масштабах не вся информация попадает на экран и фильтровать надо точки, попадающие за экран.

Согласен. Это правильно. Но какими средствами рисовать эти точки и матрицу? При максимальном масштабе (скорее минимальном, когда видна вся область отрисовки) спокойно отображется более 10 тыс точек.. в облати видимости размером 900х900, это без секторов, зон и т.д. и уже начинает тормозить, если рисовать отдельными items на сцене.


Название: Re: Помогите с архитектурой графической части приложения
Отправлено: _OLEGator_ от Апрель 22, 2013, 12:43
Одним элементом рисовать все точки.
Я пока не понимаю необходимости использования QGraphicsScene. Я бы переопределил отрисовку QWidget (QGLWidget), а манипуляции с масштабом и перемещением делаются легко.


Название: Re: Помогите с архитектурой графической части приложения
Отправлено: Vladimir от Апрель 22, 2013, 12:57
Одним элементом рисовать все точки.
Я пока не понимаю необходимости использования QGraphicsScene. Я бы переопределил отрисовку QWidget (QGLWidget), а манипуляции с масштабом и перемещением делаются легко.

Так а есть принципиальная разница, ведь в  QGraphicsScene тоже контекст рисования QGLWidget?! ну может и так попробовать, тогда как быстрее всего отрисовать матрицу на QGLWidget? Понятно, что точки  glVertex2f рисуются быстро.. но OpenGL капризная штука, в зависимости от установленных дров на видеокарту.. даже qt-е 40 000 чипов очень по разному рисуются на разных машинах в режиме OpenGL, поэтому склонялся больше к QGraphicsScene.


Название: Re: Помогите с архитектурой графической части приложения
Отправлено: _OLEGator_ от Апрель 22, 2013, 15:31
QGraphicsScene массивный слишком, если не требуется его функциональности, кроме как отрисовать, передвинуть, масштабировать - я бы воспользовался ручной отрисовкой. На счет QGLWidget все верно, это скорее не от видеокарты зависит - сейчас они вполне мощные даже встроенные. Зависит от дров, потому что на винде под OpenGL стоят самые простейшие, из-за которых все медленно.
Я проводил тесты - на QGLWidget'e простой QPainter рисует быстрее, при условии обновленных дров под OpenGL.
Данные то какие у тебя? Матрица это что такое, просто сетка, таблица?
Прикрепил бы скрин чтоли, чтобы понятнее было.


Название: Re: Помогите с архитектурой графической части приложения
Отправлено: Vladimir от Апрель 22, 2013, 16:16
QGraphicsScene массивный слишком, если не требуется его функциональности, кроме как отрисовать, передвинуть, масштабировать - я бы воспользовался ручной отрисовкой. На счет QGLWidget все верно, это скорее не от видеокарты зависит - сейчас они вполне мощные даже встроенные. Зависит от дров, потому что на винде под OpenGL стоят самые простейшие, из-за которых все медленно.
Я проводил тесты - на QGLWidget'e простой QPainter рисует быстрее, при условии обновленных дров под OpenGL.
Данные то какие у тебя? Матрица это что такое, просто сетка, таблица?
Прикрепил бы скрин чтоли, чтобы понятнее было.

В том то и дело, что программу предполагается юзать под двумя ОС Linux и Win и как обстоят дела с настройкой дров под Linux под максимальную производительность OpenGL я малопредставляю. Но это нужно тестить и проверять, для начала хотелось бы сделать кросплатформенный метод отрисовки вышеописанного.
Что касается матрицы, то это массив цветовых значений по ширине 4096 и высотой 2400, каждые 12 ms приходят данные data[2400] и заполняют постепенно весь прямоугольник от 0 до 4096. На скрине данные заполняются рандомом(по яркости) зеленым цветом. Эти данные нужно писать в некий битмап (либо еще как-то..) и раз в 50-60 ms отрисовывать на экране в виде подложки.. как это реализовать на QGLWidget'e?

Как было описано, я пробовал рисовать в QImage(2400,4096), а потом сценой масштабировать данную подложку.. сначала уменьшал, чтобы она влазила в область просмотра, а если нужно уточнить данные приближал(увеличивал)! И сцена делает это достаточно шустро без отрисовки всего остального, тобишь меток.. с выводом меток все начинает тормозить! :(


Название: Re: Помогите с архитектурой графической части приложения
Отправлено: _OLEGator_ от Апрель 22, 2013, 16:23
Все равно эти данные в картинку преобразовывать надо (возможно в потоке, чтобы не морозить интерфейс). Либо вручную, либо напрямую:
Код
C++ (Qt)
QImage::fromData( ... )
QPixmap::loadFromData( ... )
А дальше рисуй, картинка QPainter'ом рисуется быстро, 30 fps должна держать.
По поводу QGLWIdget'a еще раз повторю - та же самая отрисовка QPainter'ом на QGLWidget'e идет с аппаратным ускорением, т.е. это не тоже самое что рисовать на QWidget. Условие - что дрова стоят не самые древние и примитивные, на винде по умолчанию идут древние дрова.


Название: Re: Помогите с архитектурой графической части приложения
Отправлено: Vladimir от Апрель 22, 2013, 16:30
Все равно эти данные в картинку преобразовывать надо (возможно в потоке, чтобы не морозить интерфейс). Либо вручную, либо напрямую:
Код
C++ (Qt)
QImage::fromData( ... )
QPixmap::loadFromData( ... )
А дальше рисуй, картинка QPainter'ом рисуется быстро, 30 fps должна держать.
По поводу QGLWIdget'a еще раз повторю - та же самая отрисовка QPainter'ом на QGLWidget'e идет с аппаратным ускорением, т.е. это не тоже самое что рисовать на QWidget. Условие - что дрова стоят не самые древние и примитивные, на винде по умолчанию идут древние дрова.

Т.е. Вы предлагаете на QGLWIdget данную матрицу отрисовывать painter->drawImage(), а метки рисовать glVertex2f(i,j); как точка? Это все можно отрисовывать в paintGL()?


Название: Re: Помогите с архитектурой графической части приложения
Отправлено: _OLEGator_ от Апрель 22, 2013, 16:43
Нет, я для начала предлагаю отрисовать все с помощью QPainter на QWidget с фильтрацией, потом посмотреть на скорость. Просто изменить с QWidget на QGLWidget и посмотреть скорость. Механизм отрисовки не изменяется, вообще после фильтрации должно все быстро рисоваться, вся загвоздка в избыточном количестве точек на экране.


Название: Re: Помогите с архитектурой графической части приложения
Отправлено: Vladimir от Апрель 22, 2013, 17:02
Нет, я для начала предлагаю отрисовать все с помощью QPainter на QWidget с фильтрацией, потом посмотреть на скорость. Просто изменить с QWidget на QGLWidget и посмотреть скорость. Механизм отрисовки не изменяется, вообще после фильтрации должно все быстро рисоваться, вся загвоздка в избыточном количестве точек на экране.

Так их действительно много и они вполне могут не перекрываться. Точки образуют трассы, которые могут рисоваться разными зигзагами и вполне не перекрывать друг друга. Понятно, что 50 000 это перебор и его нужно фильтровать, но отрисовка даже 10 тыс на минимальном масштабе вполне может быть.. это потенциально возрастающий цикл + проверка на нужно/ненужно рисовать.
Понятно, что нужно тестировать смотреть. И не последний момент какими средствами отрисовывать в paintEvent(): drawPoint() и drawImage(), какими методами рисовать быстрее?


Название: Re: Помогите с архитектурой графической части приложения
Отправлено: _OLEGator_ от Апрель 22, 2013, 17:11
Точки гарантированно поверх матрицы попадают?


Название: Re: Помогите с архитектурой графической части приложения
Отправлено: Vladimir от Апрель 22, 2013, 17:19
Точки гарантированно поверх матрицы попадают?

Да. Матрица меняется/заполняется данными(заполняет весь прямоугольник, затем сначала пишет новые данные), точки появляются удаляются над этой подложкой(матрицей).


Название: Re: Помогите с архитектурой графической части приложения
Отправлено: _OLEGator_ от Апрель 22, 2013, 17:23
У меня больше идей нету. Разумным кажется рисовать матрицу через картинку, только я бы заполнял картинку напрямую из сырых данных, а не через setPixel и также точки через картинку.
Прикрепи минимальный проект с такой реализацией, чтобы погонять и посмотреть что там за тормоза при масштабировании.


Название: Re: Помогите с архитектурой графической части приложения
Отправлено: Vladimir от Апрель 22, 2013, 17:27
У меня больше идей нету. Разумным кажется рисовать матрицу через картинку, только я бы заполнял картинку напрямую из сырых данных, а не через setPixel и также точки через картинку.
Прикрепи минимальный проект с такой реализацией, чтобы погонять и посмотреть что там за тормоза при масштабировании.

Хорошо повырезаю все лишнее и сегодня/завтра скину проект, чтобы было более нагляднее! Спасибо, что откликнулся :)


Название: Re: Помогите с архитектурой графической части приложения
Отправлено: Vladimir от Апрель 22, 2013, 18:45
Прикреплю грубый тестовый пример с круговой и прямоугольной матрицей вывода. На круговой матрице вывода метки ставятся по всей области вывода, но должны только по матрице, но это пока не суть. на прямоугольном ставится везде. Еще один момент, который не совсем понятен это работа таймера, который имитирует приход данных, в реальном приложении данные приходят по сети, а здесь я сымитировал по таймеру, но как-то он странно работает.. как будто накапливает события timeout() это хорошо видно, как отрисовка ускоряется/замедляется. ну + тормаза при масштабировании! область вывода 700х700, вообще планируется сделать в зависимости от резрешения экрана. но на рабочей машине будет порядка 900х900. в общем гляньте и подскажите пожалуйста куда копать дальше..


Название: Re: Помогите с архитектурой графической части приложения
Отправлено: Disa от Апрель 22, 2013, 22:44
Ближе к вечеру читал тему по диагонали, и сразу возник вопрос, если так важна скорость отрисовки, то какой нафиг glVertex, когда для большого количества данных пересылаемых за раз есть VBO и VAO, да и вообще glBegin/glEnd являются deprecated года с 2005-2006.


Название: Re: Помогите с архитектурой графической части приложения
Отправлено: Vladimir от Апрель 22, 2013, 23:49
Ближе к вечеру читал тему по диагонали, и сразу возник вопрос, если так важна скорость отрисовки, то какой нафиг glVertex, когда для большого количества данных пересылаемых за раз есть VBO и VAO, да и вообще glBegin/glEnd являются deprecated года с 2005-2006.

Ну в OpenGL мне еще разбираться и разбираться.. на другом форуме посоветовали юзать glDrawArrays() ну это видимо и есть по теме VBO. Но вопрос остается как отрисовывать матрицу с возможностью масштабирования?


Название: Re: Помогите с архитектурой графической части приложения
Отправлено: Igors от Апрель 23, 2013, 07:28
Ближе к вечеру читал тему по диагонали, и сразу возник вопрос, если так важна скорость отрисовки, то какой нафиг glVertex, когда для большого количества данных пересылаемых за раз есть VBO и VAO, да и вообще glBegin/glEnd являются deprecated года с 2005-2006.
Подтверждаю. Недавно закончил изменения связанные с VBO. Прирост с 8 fps до 30 и даже до 60 (на др карте). Это при том что изначально юзались glDrawElements и glDrawArrays. А glBegin/glEnd конечно позавчерашний день


Название: Re: Помогите с архитектурой графической части приложения
Отправлено: Vladimir от Апрель 24, 2013, 12:10
Ближе к вечеру читал тему по диагонали, и сразу возник вопрос, если так важна скорость отрисовки, то какой нафиг glVertex, когда для большого количества данных пересылаемых за раз есть VBO и VAO, да и вообще glBegin/glEnd являются deprecated года с 2005-2006.
Подтверждаю. Недавно закончил изменения связанные с VBO. Прирост с 8 fps до 30 и даже до 60 (на др карте). Это при том что изначально юзались glDrawElements и glDrawArrays. А glBegin/glEnd конечно позавчерашний день

Пробую выводить как вы советуете через glDrawArrays, но почему-то вместо, скажем, 15 точек выводит только 5, остальные в левом верхнем углу видимо одна на одну накладываются.. что не так? Прикреплю тестовый пример.. это, что касается вывода меток, но как на GL виджете мне вывести вышеописанную матрицу?! И еще вопрос можно ли как-то совместить рисование средствами OpenGL и QPainter в одном проекте?


Название: Re: Помогите с архитектурой графической части приложения
Отправлено: Vladimir от Апрель 24, 2013, 12:35
С метками разобрался, там просто заполнение было не правильное! Насколько все это быстро нужно посмотреть вместе с отрисовкой матрицы, вопрос остается как быстро отрисовывать картинку на QGLWidget-е?!!!!