Russian Qt Forum
Ноябрь 01, 2024, 12:25 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1] 2   Вниз
  Печать  
Автор Тема: Рисование множества точек с OpenGL  (Прочитано 17991 раз)
soaup
Гость
« : Июль 16, 2014, 06:00 »

Здравствуйте! Нужна помощь! Имеется виджет QGLWIdget. Рисую, с его помощью, через цикл, линию из массива множество точек. При этом массив для отрисовки поступает раз в пол-секунды примерно (данные приходят по сети). И я рисую сначало последнюю линию, а также все предыдущие, ниже чем текущую. Предыдущие массивы для отрисовки помещаю в контейнер QLinkedList, а потом в цикле отрисовываю все элементы из контейнера. Задал, чтобы максимум элементов в контейнере было 130 (так лучше видно всю картину).  Т.е. в итоге:
Код:
QLinkedList <QByteArray> B;

void glwindow::paintGL() {
    glClear(GL_COLOR_BUFFER_BIT| GL_DEPTH_BUFFER_BIT);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    int j = 0;
    QMutableLinkedListIterator <QByteArray> i(B);
    while (i.hasNext()) { //Для каждого элемента буфера
        drawLine(i.next(), j); //Функция рисования линии
        ++j;
    }

}

void glwindow::drawLine(QByteArray &bd, int y) {
    glPointSize(1*nSca);
    glBegin(GL_POINTS);
    for (int j = 0; j < bd.size(); ++j) { //Для каждой точки из пакета
        glColor3b(bd.at(j), bd.at(j), bd.at(j)); //Рисование точки, значение которой указывается как яркость
        glVertex2f(j, y); //Координаты точки
    }
    glEnd();
}

void glwindow::resizeGL(int nWidth, int nHeight) {
    glViewport(0, 0, (GLint)nWidth, (GLint)nHeight);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    GLfloat x = GLfloat(nWidth)/nHeight;
    glOrtho(0, 53248, 130, 0, -1, 1);
    glMatrixMode(GL_MODELVIEW);
}

Отправляю в виджет данные  для отрисовки вызовом фунции sendBD, которая выглядит вот так:
Код:
void glwindow::sendBD(QByteArray &bd) {
    ++i;
    B.prepend(bd); //Поместить пакет в начало буфера
    if (B.count() > 130)
        B.removeLast(); //Удалять последний если количество элементов в буфере больше нужного
    if (i > 10) { //Обновление изображения после получения второго пакета подряд
        updateGL();
        i = 0;
    }
}

Пакеты данных у меня очень обьемные - 53248 байтов в массиве QByteArray. Значение каждого байта принимается за цвет точки для рисования.
Когда придет примерно 50 пакетов, скорость работы снижается. Когда придут все пакеты, все это весьма тормозит. На OpenGL. Следовательно, вопрос - OpenGL для подобных целей (отрисовка больших обьемов данных) подходит лучше всего, если для меня принципиален вопрос скорости? Лучше paintEvent например? И можно ли это оптимизировать? У меня в планах находиться провести децимацию массива, но есть ли еще какие-нибудь способы чисто со стороны OpenGL?
« Последнее редактирование: Июль 16, 2014, 06:04 от soaup » Записан
Hrundel
Гость
« Ответ #1 : Июль 16, 2014, 09:49 »

Нужно передавать массив точек в функцию glDrawElements - будет быстрее
Код
C++ (Qt)
glDrawElements(GL_TRIANGLES, arrayV.length,  GL_UNSIGNED_INT, index);
Записан
Hrundel
Гость
« Ответ #2 : Июль 16, 2014, 09:55 »

и вот еще что

http://ru.wikipedia.org/wiki/Vertex_Buffer_Object
Записан
soaup
Гость
« Ответ #3 : Июль 16, 2014, 10:07 »

Натыкался на эту функцию, но не знал как ее применять. Функция применяется сразу для всего массива? И что писать в index?
Записан
navrocky
Гипер активный житель
*****
Offline Offline

Сообщений: 817


Погроммист


Просмотр профиля
« Ответ #4 : Июль 16, 2014, 10:17 »

А зачем тут вообще OpenGL ?
Записан

Гугль в помощь
soaup
Гость
« Ответ #5 : Июль 16, 2014, 10:22 »

Мне нужна максимальная скорость работы при большом объеме данных. Я слышал, что OpenGL обладает большой производительностью.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #6 : Июль 16, 2014, 10:27 »

Тюкать "точка за точкой" - эта техника устарела уже лет 10 назад. Конечно рисуется массивами. Индексов у Вас не видно, поэтому glDrawArrays
Код
C++ (Qt)
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, &points[0]);
 
glEnableClientState(GL_COLOR_ARRAY);
glColorPointer(1, GL_UNSIGNED_BYTE, 0, &colors[0]);
 
glDrawArrays(GL_POINTS, 0, points.size());
 
При этом points и colors должны быть линейными массивами (напр вектора). Спецификацию OpenGL читайте, этого никто не отменял
Записан
navrocky
Гипер активный житель
*****
Offline Offline

Сообщений: 817


Погроммист


Просмотр профиля
« Ответ #7 : Июль 16, 2014, 14:14 »

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

Не уверен, что в 2D будет какое-то преимущество, одна 2D-линия - это отрисовка двух треугольников. Во всяком случае, я не видел, чтобы программа ускорялась от перехода с растра на OpenGL. Ускорение обычно достигается за счет отрисовки масштабированных картинок.

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

Вот, к примеру, как это делается в QtQuick http://qt-project.org/doc/qt-5/qtquick-scenegraph-graph-example.html
« Последнее редактирование: Июль 16, 2014, 14:22 от navrocky » Записан

Гугль в помощь
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #8 : Июль 16, 2014, 17:28 »

Не уверен, что в 2D будет какое-то преимущество, одна 2D-линия - это отрисовка двух треугольников.
...
Ускорение обычно достигается за счет отрисовки масштабированных картинок.
Укажите первоисточник таких таинственных/мистических заявлений. Никогда не слышал о том что линия рисуется 2-мя треугольниками  Непонимающий

Во всяком случае, я не видел, чтобы программа ускорялась от перехода с растра на OpenGL.
Ожидаемое ускорение - на порядок и больше. Хотите проверим - выкладывайте простое растровое рисование точек/линий
Записан
navrocky
Гипер активный житель
*****
Offline Offline

Сообщений: 817


Погроммист


Просмотр профиля
« Ответ #9 : Июль 16, 2014, 20:32 »

Не уверен, что в 2D будет какое-то преимущество, одна 2D-линия - это отрисовка двух треугольников.
...
Ускорение обычно достигается за счет отрисовки масштабированных картинок.
Укажите первоисточник таких таинственных/мистических заявлений. Никогда не слышал о том что линия рисуется 2-мя треугольниками  Непонимающий

Во всяком случае, я не видел, чтобы программа ускорялась от перехода с растра на OpenGL.
Ожидаемое ускорение - на порядок и больше. Хотите проверим - выкладывайте простое растровое рисование точек/линий

По поводу тормознутости 2D в OpenGL я сужу по моим наблюдениям. Вот несколько:
1) Всегда в графических пакетах типа 3DMax, blender, wireframe отрисовывался ощутимо тормознее, чем залитая фигура. (включенное аппаратное ускорение)
2) В Qt-шных примерах есть примеры, с QPainter поверх QGLWidget, оно, не смотря на ускорение через OpenGL работает тормознее растра, что видно на глаз. Быстрее только картинки масштабируются, что вполне логично.
3) В нетах тоже периодически всплывают такие темы, вот например: http://www.gamedev.ru/code/forum/?id=176940

По логике вещей сейчас производители железа стремятся к быстрой отрисовки треугольников, т.к. это базовый элемент в 3D графике. И 2D ускорение никого сейчас уже не волнует, скорее всего его выкинули из железа и эмулируют программно в драйвере. Хотя я не отрицаю, что существует и аппаратная поддержка рисования 2D фигур, не зря существует линейка Quadro, которая предназначена для работы с профессиональными графическими пакетами.

Записан

Гугль в помощь
soaup
Гость
« Ответ #10 : Июль 17, 2014, 06:04 »

Igors Плохо понимаю что значит линейный массив, т.е. одномерный? или должен быть типа QVector?  Пытаюсь пробелать это с одним массивом байтов QByteArray, QT мне говорит: ошибка: taking address of temporary.
Записан
Hrundel
Гость
« Ответ #11 : Июль 17, 2014, 07:15 »

Одномерный массив, желательно определенный GL типом. Например, GLfloat как в следующем коде.

Код
C++ (Qt)
GLfloat vertices[] = {...};
...
// деффинировать указатель на массив
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, vertices);
 
// отрисовка
glDrawArrays(GL_TRIANGLES, 0, 36);
 
// деактивация массива
glDisableClientState(GL_VERTEX_ARRAY);
« Последнее редактирование: Июль 17, 2014, 07:21 от Hrundel » Записан
soaup
Гость
« Ответ #12 : Июль 17, 2014, 07:32 »

Ясно, спасибо! Вот еще вопрос, мне нужно получается если отправлять массив в котором значение каждого элемента это координата по y (x расставить автоматически по индексу элемента). А потом все точки с таким координатами отрисовать и соединить линиями. Такое можно сделать этим способом? 
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #13 : Июль 17, 2014, 08:01 »

Ясно, спасибо! Вот еще вопрос, мне нужно получается если отправлять массив в котором значение каждого элемента это координата по y (x расставить автоматически по индексу элемента). А потом все точки с таким координатами отрисовать и соединить линиями. Такое можно сделать этим способом?  
Так для этого есть специальный режим который сразу рисует линии последовательно по точкам
Код
C++ (Qt)
glDrawArrays(GL_LINE_STRIP, 0, points.size());
 

Одномерный массив, желательно определенный GL типом. Например, GLfloat как в следующем коде.
Код
C++ (Qt)
GLfloat vertices[] = {...};
 
Ну такой массив не создать если переменное число эл-тов. Проще всего std::vector или QVector, а можно и просто new. Главное чтобы в памяти это было "подряд" (а не разбросано в разныз местах). Напр QList здесь не годится
« Последнее редактирование: Июль 17, 2014, 08:12 от Igors » Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #14 : Июль 17, 2014, 08:21 »

Напр QList здесь не годится
Поэтому, лучше использовать vbo. Тогда и связанные списки сгодяться.
Записан
Страниц: [1] 2   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.365 секунд. Запросов: 23.