Qt OpenGL VS "чистый openGL"
    , оценка производительности
  ![]()  | 
Наши проекты:
 Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту  | 
|
| ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS | 
| [216.73.216.5] | 
 
 | 
		
  | 
    Правила раздела *nix / gcc / Eclipse / Qt / wxWidgets / GTK+
  
    Qt OpenGL VS "чистый openGL"
    , оценка производительности
  | 
         | 
    |
| 
         | 
      
          Добрый вечер. Вашему вниманию новая серия моих приключений в чудном мире WinCE.  
        
      Кратко опишу задачу: на вход передается массив точек для отображения трека заданной и фиксированной ширины средствами OpenGL, конкретно нужно строить этот трек средствами TRIANGLE_STRIP. А чтобы жизнь не казалась сказкой этот трек нужно вращать в произвольном направлении (вокруг произвольно заданной оси вращения, со всеми вытекающими преобразованиями координат), масштабировать, перемещать, про такие мелочи как изменение цвета, ширины пера я умалчиваю. Ну и для полного счастья и максимального использования возможностей openGL будем применять шейдеры. Правда что это такое я узнал чуть более недели назад. Ладно, это не суть. В чем вопрос: имеется "эталонная программа", написанная на "голом openGL", демонстрирующая следующие результаты: ![]() ![]() 10k - 48 fps 50k - 35 fps 300k - 13 fps (масштаб по умолчанию), 8-9 fps масштаб, при котором все точки находятся в видимой области для 10k/50k масштаб значения не имеет Я предпринял две попытки реализации поставленной задачи на Qt. 1) в QGraphicsView подсунул QGLWidget, в котором трек рисовал обычным QPainter в PaintGL. Для этого случая у меня все хорошо с построением самого трека, а также дополнительными плюшками, которые дает использование QGraphicsView/QGraphicsScene, но очень плохо с производительностью, возможно я избрал не самый верный подход - я брал несчастный QGraphicsPolygonItem и пихал в него силой все 300 000 точек. От чего ему, естественно, плохело. Ну и о производительности говорить не приходилось в этом случае. Для чистоты эксперимента запрещено думать об интерполяции, построении вместо полигона на 100 точек, лежащих на одной прямой этой самой прямой по двум точкам (я проводил эксперимент, у меня вместо 300 000 точек получилось около 800, ну и производительность, естественно выросла до космических скоростей). Я сейчас не понимаю что я курил, когда писал этот код, но не суть. Выглядит он, примерно, так: ![]() ![]()     void SnowWindow::populateScene()     {         m_trackScene = new QGraphicsScene(this);         QString filename = QFileDialog::getOpenFileName(this, tr("open CSV data"), tr(""), tr("*.csv"));         PointArray points = get_points(filename);         // Populate scene         QGraphicsPolygonItem *polygon_item = new QGraphicsPolygonItem;         QPolygonF polygon;         QVector2D point;         int idx = 0;         foreach (point, points) {             if((++idx % 100) == 0) {                 QGraphicsSimpleTextItem *textItem = new QGraphicsSimpleTextItem;                 textItem->setText("T");                 textItem->setPos(point.toPointF());                 textItem->setZValue(0.35);                 m_trackScene->addItem(textItem);             }             polygon << point.toPointF();         }         polygon_item->setPolygon(polygon);         QPen pen;  // creates a default pen         pen.setStyle(Qt::SolidLine);         pen.setWidth(3);         pen.setBrush(QBrush(Qt::green, Qt::DiagCrossPattern));         polygon_item->setPen(pen);         polygon_item->setZValue(0.25);         m_trackScene->addItem(polygon_item);     } но на 300к точек выдает не более 4 fps. Есть ненулевая вероятность, что даже для этого варианта можно существенно повысить производительность, правда я не знаю как. Еще один вариант -уже с использованием шейдеров. Честно скажу, я долго курил этот мануал точнее весь курс, но видимо особых успехов не добился, ибо моя реализация выдает следующие результаты: 10 000 точек - 48-70 FPS; 50 000 - 17-25 FPS; 100 000 - 11-15 FPS; 200 000 - 7-11 FPS: 300 000 - 4-5 FPS - во всех случаях независимо от масштаба. Весь код приводить не буду, скажу только, что после заполнения вершинами метод draw выглядит так: ![]() ![]()     void SnowTrack::drawTrueData()     {         m_program->setAttributeArray(m_vertexAttr, m_trueVertices.data(), 3);         m_program->setAttributeArray(m_colorAttr, m_trueColors.data(), 3);         m_program->enableAttributeArray(m_vertexAttr);         m_program->enableAttributeArray(m_colorAttr);         glDrawArrays(GL_TRIANGLE_STRIP, 0, m_trueVertices.size() / 3);         m_program->disableAttributeArray(m_vertexAttr);         m_program->disableAttributeArray(m_colorAttr);     } а вершинный шейдер настолько примитивен, что даже самому грустно. ![]() ![]() attribute highp vec4 vertexAttr; uniform mediump mat4 matrix; attribute lowp vec4 colorAttr; varying lowp vec4 color; void main() {     gl_Position = matrix * vertexAttr;     color = colorAttr; } в "эталонной" программе он сильно другой, но я так понимаю, что это влияет на положение вершин в пространстве, но никак не на производительность. Если я не прав, то тогда все совсем плохо. Хотя может и наоборот - все хорошо и я смогу догнать и перегнать америку. ![]() ![]()     const char* pszFragmentShader = "\                                         precision mediump float;\                                         varying vec4 trifragmentColor;\                                         vec4 tricolor;\                                         void main()\                                         {\                                             gl_FragColor = trifragmentColor;\                                     }";     const char* pszVertexShader =   "\                                         attribute vec3 trianglePosition_modelspace;\                                         attribute vec3 triangleColor;\                                         varying vec4 trifragmentColor;\                                         uniform mat4 MVP;\                                         void main()\                                         {\                                             gl_Position = MVP * vec4(trianglePosition_modelspace, 1.0);\                                             trifragmentColor = vec4(triangleColor, 1.0);\                                     }"; Ну и отсюда вопрос к знающим людям: насколько реально получить средствами связки Qt OpenGL производительность аналогичную "голому OpenGL". По умолчанию предполагаем, что мой код, мягко говоря, не оптимален. Собственно для чего все это затевалось - показать, что средствами Qt можно обеспечить аналогичную производительность, а вместе с ней и все вкусности самого(ой?) Qt. Ибо писать на 03 стандарте меня не особо прельщает, да и сочинение очередной козы на лисапеде точно не добавит производительности приложению, будь оно даже на ассемблере написано. О скорости разработки и количестве багов даже подумать страшно. Но реалии таковы, что приходится выбирать. Сроки по доказательству производительности Qt стремительно мчатся к точке невозврата, а потому надеюсь на ваши мудрые советы, кои спасали меня здесь неоднократно.  | 
    
| 
         
         
         
          
           Сообщ.
           #2
          
          , 
          
         
         
        
       | 
    |
| 
         | 
      
          C qt5.4 вроде как с QGLWidget на QOpenGLWidget, QOpenGLWindow перекат был (сам мучился), https://doc.qt.io/archives/qt-5.5/examples-...ets-opengl.html https://doc.qt.io/qt-5.12/examples-widgets-opengl.html. 	  
        
       | 
    
| 
         
         
         
          
           Сообщ.
           #3
          
          , 
          
         
         
        
       | 
    |
| 
         | 
      
          в общем, как и предполагалось - дело было не в бобине. производительность удалось получить вполне вменяемую.   
        
       | 
    
| 
         
         
         
          
           Сообщ.
           #4
          
          , 
          
         
         
        
       | 
    |
| 
         | 
      
         Цитата kotmatroskin55 @  kotmatroskin55 Тема очень актуальная , подскажите ваше решение . Пробую QOpenGLWindow - Qt обрезает до 60 fps как не крути если через QGraphicsView/QGraphicsScene - тоже максимум 60 fps , но сильно падает при сложной отрисовке.  |