Canvas (холст) в QOPenGL

Пытаюсь отобразить спектрограмму в Qt с помощью OpenGL, данные для отображения синтетические (пока что генерируются рандомно) В данный момент при запуске приложения отображается только один набор точек (текущий набор), а все предыдущие нет.

Подозреваю, что при update() перерисовывается весь контекст OpenGL

Подскажите, пожалуйста, может использование холста поможет? С заданием явной очистки, чтобы контролировать этот момент

Спасибо.

#ifndef SPECTROGRAM_H
#define SPECTROGRAM_H

#include <QOpenGLWidget>
#include <QOpenGLFunctions>
#include <QTimer>

struct Pixel {
    float x;
    float y;
    float z;
};

class Spectrogram : public QOpenGLWidget, protected QOpenGLFunctions
{
    Q_OBJECT

public:
    Spectrogram(QWidget *parent = nullptr);
    ~Spectrogram();

protected:
    void initializeGL() override;
    void resizeGL(int w, int h) override;
    void paintGL() override;

private slots:
    void generateData();

private:
    QVector<Pixel>pixels;
    float currentY;
    QTimer timer;
    int lastRenderedIndex;
};
#endif // SPECTROGRAM_H

#include "spectrogram.h"

Spectrogram::Spectrogram(QWidget *parent)
    : QOpenGLWidget(parent), currentY(0), lastRenderedIndex(0)
{
    srand(time(nullptr));
    connect(&timer, &QTimer::timeout, this, &Spectrogram::generateData);
    timer.start(100);
}

void Spectrogram::initializeGL()
{
    initializeOpenGLFunctions();
    glClearColor(0.0, 0.0, 0.0, 1.0);
}

void Spectrogram::resizeGL(int w, int h)
{
    glViewport(0, 0, w, h); // на все окно

    // Явно указываю, что работаю с 2D
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrtho(0, w, h, 0, -1, 1);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity(); // чтобы изменения не накладывались друг на друга
}

void Spectrogram::paintGL()
{
    // Удалит холст
//    glClear(GL_COLOR_BUFFER_BIT);
    int width = this->width(); // Текущая ширина виджета для последюущей нормализаци

    glBegin(GL_POINTS);
    // предыдущий цикл for-each заменил но for, чтобы начинать с
      for (int i = lastRenderedIndex; i < pixels.size(); ++i){
          float red = pixels[i].z;
          float green = static_cast<float>(rand() / static_cast<float>(RAND_MAX));
          float blue = static_cast<float>(rand() / static_cast<float>(RAND_MAX));

          glColor3f(red, green, blue);

          float normalizedX = pixels[i].x * width;
          glVertex2f(normalizedX, pixels[i].y);
      }
    glEnd();
    lastRenderedIndex = pixels.size();
}

void Spectrogram::generateData()
{
    int width = this->width();
    int height = this->height();

    // когда данные заполнили весь экран, начинаем отрисовку заново сверху
    if (currentY >= height) currentY = 0;

    for (int i = 0; i < 500; ++i) {
        Pixel pixel;

        pixel.x = static_cast<float>(rand()) / static_cast<float>(RAND_MAX);
        pixel.y = static_cast<float>(currentY);

        // Интенсивность для красного канала
        pixel.z = static_cast<float>(rand()) / static_cast<float>(RAND_MAX);

        pixels.push_back(pixel);
    }

    currentY += 5;
    update(); // обновление виджета для перерисовки
}

Spectrogram::~Spectrogram()
{
}

Ответы (0 шт):