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()
{
}