Uses alpha channel to draw lines, uses Qt::FlatCap style, uses QPainter::Antialiasing
This commit is contained in:
@@ -17,11 +17,11 @@ qint32 framesForDuration(qint64 duration){
|
|||||||
OsciWidget::OsciWidget(QWidget *parent)
|
OsciWidget::OsciWidget(QWidget *parent)
|
||||||
: QOpenGLWidget{parent}
|
: QOpenGLWidget{parent}
|
||||||
, m_bufferOffset{m_buffer.begin()}
|
, m_bufferOffset{m_buffer.begin()}
|
||||||
, m_lastTime{0}
|
, m_lastBufferUpdate{0}
|
||||||
, m_redrawTimerId(startTimer(1000/m_fps, Qt::PreciseTimer))
|
, m_redrawTimerId(startTimer(1000/m_fps, Qt::PreciseTimer))
|
||||||
{
|
{
|
||||||
m_statsTimer.start();
|
m_statsTimer.start();
|
||||||
m_bufferTimer.start();
|
m_globalTimer.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
int OsciWidget::lightspeed() const
|
int OsciWidget::lightspeed() const
|
||||||
@@ -62,17 +62,18 @@ void OsciWidget::renderSamples(const SamplePair *begin, const SamplePair *end)
|
|||||||
|
|
||||||
auto offset = std::distance(m_buffer.begin(), m_bufferOffset);
|
auto offset = std::distance(m_buffer.begin(), m_bufferOffset);
|
||||||
|
|
||||||
if(m_bufferTimer.elapsed()-m_lastTime > 5000)
|
if(m_globalTimer.elapsed()-m_lastBufferUpdate > 5000)
|
||||||
{
|
{
|
||||||
//qDebug() << "deleting: " << m_bufferOffset - m_buffer.begin() << m_buffer.size();
|
//qDebug() << "deleting: " << m_bufferOffset - m_buffer.begin() << m_buffer.size();
|
||||||
// Delete drawn frames
|
// Delete drawn frames
|
||||||
//m_buffer.erase(m_buffer.begin(), m_bufferOffset);
|
//m_buffer.erase(m_buffer.begin(), m_bufferOffset);
|
||||||
|
|
||||||
// TODO improve by drawing remaining(undrawn) buffer instead
|
// TODO improve by drawing remaining(undrawn) buffer instead
|
||||||
|
drawBuffer(m_bufferOffset, m_buffer.end(), QColor(0, 255, 0));
|
||||||
m_buffer.clear();
|
m_buffer.clear();
|
||||||
offset = 0;
|
offset = 0;
|
||||||
|
|
||||||
m_lastTime = m_bufferTimer.elapsed();
|
m_lastBufferUpdate = m_globalTimer.elapsed();
|
||||||
}
|
}
|
||||||
//qDebug () << " inserting " << std::distance(begin, end);
|
//qDebug () << " inserting " << std::distance(begin, end);
|
||||||
m_buffer.insert(m_buffer.end(), begin, end);
|
m_buffer.insert(m_buffer.end(), begin, end);
|
||||||
@@ -88,7 +89,7 @@ void OsciWidget::paintEvent(QPaintEvent *event)
|
|||||||
m_frameCounter++;
|
m_frameCounter++;
|
||||||
if (m_statsTimer.hasExpired(1000))
|
if (m_statsTimer.hasExpired(1000))
|
||||||
{
|
{
|
||||||
emit statusUpdate(QString("%0FPS (%1 callbacks, %2 samples, %3 avg per callback, bufferSize %4, elapsed %5)").arg(m_frameCounter).arg(m_callbacksCounter).arg(m_samplesCounter).arg(m_callbacksCounter>0?m_samplesCounter/m_callbacksCounter:0).arg(m_buffer.size()).arg(m_bufferTimer.elapsed()));
|
emit statusUpdate(QString("%0FPS (%1 callbacks, %2 samples, %3 avg per callback, bufferSize %4, elapsed %5)").arg(m_frameCounter).arg(m_callbacksCounter).arg(m_samplesCounter).arg(m_callbacksCounter>0?m_samplesCounter/m_callbacksCounter:0).arg(m_buffer.size()).arg(m_globalTimer.elapsed()));
|
||||||
m_frameCounter = 0;
|
m_frameCounter = 0;
|
||||||
m_callbacksCounter = 0;
|
m_callbacksCounter = 0;
|
||||||
m_samplesCounter = 0;
|
m_samplesCounter = 0;
|
||||||
@@ -103,28 +104,32 @@ void OsciWidget::darkenFrame()
|
|||||||
{
|
{
|
||||||
QPainter painter(&m_pixmap);
|
QPainter painter(&m_pixmap);
|
||||||
|
|
||||||
painter.setCompositionMode(QPainter::CompositionMode_Multiply);
|
|
||||||
painter.setPen({});
|
|
||||||
//auto afterglowColor = 255 * pow(m_decayTime, 1.0/m_fps);
|
//auto afterglowColor = 255 * pow(m_decayTime, 1.0/m_fps);
|
||||||
auto afterglowColor = static_cast<int>(255 * pow(exp(-1), 1000.0/m_decayTime/m_fps));
|
auto afterglowFactor = pow(exp(-1), 1000.0/m_decayTime/m_fps);
|
||||||
qDebug() << afterglowColor;
|
auto afterglowColor = static_cast<int>(255*afterglowFactor);
|
||||||
|
//qDebug() << afterglowFactor;
|
||||||
|
//QColor blendColor;
|
||||||
|
//black.setAlpha(afterglowColor);
|
||||||
|
painter.setCompositionMode(QPainter::CompositionMode_Multiply);
|
||||||
painter.setBrush(QColor(afterglowColor, afterglowColor, afterglowColor));
|
painter.setBrush(QColor(afterglowColor, afterglowColor, afterglowColor));
|
||||||
painter.drawRect(m_pixmap.rect());
|
painter.drawRect(m_pixmap.rect());
|
||||||
//m_pixmap.fill(Qt::black);
|
//m_pixmap.fill(Qt::black);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void OsciWidget::drawBuffer(SampleBuffer::iterator &bufferPos, const SampleBuffer::iterator &end)
|
void OsciWidget::drawBuffer(SampleBuffer::iterator &bufferPos, const SampleBuffer::iterator &end, QColor color)
|
||||||
{
|
{
|
||||||
QPainter painter(&m_pixmap);
|
QPainter painter(&m_pixmap);
|
||||||
|
painter.setRenderHint(QPainter::Antialiasing);
|
||||||
painter.translate(m_pixmap.width()/2, m_pixmap.height()/2);
|
painter.translate(m_pixmap.width()/2, m_pixmap.height()/2);
|
||||||
painter.scale(m_factor * m_pixmap.width() / 2.0, m_factor * m_pixmap.height() / 2.0);
|
painter.scale(m_factor * m_pixmap.width() / 2.0, m_factor * m_pixmap.height() / 2.0);
|
||||||
|
|
||||||
QPen pen;
|
QPen pen;
|
||||||
pen.setCosmetic(true); // let pen be scale invariant
|
pen.setCosmetic(true); // let pen be scale invariant
|
||||||
pen.setWidth(2);
|
pen.setWidth(2);
|
||||||
pen.setColor(QColor(0, 255, 0));
|
// This prevents most of the overlapping when drawing lines from and to the same points
|
||||||
painter.setPen(pen);
|
pen.setCapStyle(Qt::FlatCap);
|
||||||
|
|
||||||
for (;bufferPos < end; ++bufferPos)
|
for (;bufferPos < end; ++bufferPos)
|
||||||
{
|
{
|
||||||
@@ -137,14 +142,26 @@ void OsciWidget::drawBuffer(SampleBuffer::iterator &bufferPos, const SampleBuffe
|
|||||||
|
|
||||||
const QLineF line(m_lastPoint, p);
|
const QLineF line(m_lastPoint, p);
|
||||||
|
|
||||||
auto beamOpacity = std::min(1.0, 1. / ((line.length() * m_lightspeed) + 1));
|
auto beamBrightness = std::min(1.0, 1. / ((line.length() * m_lightspeed) + 1));
|
||||||
|
|
||||||
|
|
||||||
|
// time from bufferPos to end in ms
|
||||||
double time = 1000.0 * std::distance(bufferPos, end) / 44100.0;
|
double time = 1000.0 * std::distance(bufferPos, end) / 44100.0;
|
||||||
auto beamDecay = exp(-time/m_decayTime);
|
|
||||||
|
|
||||||
painter.setOpacity(beamDecay*beamOpacity);
|
auto beamDecay = exp(-time/m_decayTime);
|
||||||
|
// HACK: gamma rolloff the brightness to make it look better (make configurable?)
|
||||||
|
auto beamVisibility = pow(beamBrightness, 2.0)*beamDecay;
|
||||||
|
|
||||||
|
QColor drawColor(color);
|
||||||
|
drawColor.setAlphaF(beamVisibility);
|
||||||
|
//QColor drawColor(color.red()*beamVisibility, color.green()*beamVisibility, color.blue()*beamVisibility);
|
||||||
|
|
||||||
|
pen.setColor(drawColor);
|
||||||
|
painter.setPen(pen);
|
||||||
|
//painter.setOpacity(beamVisibility);
|
||||||
painter.drawLine(m_lastPoint, p);
|
painter.drawLine(m_lastPoint, p);
|
||||||
|
//painter.drawLine(m_lastPoint, m_lastPoint);
|
||||||
|
//painter.setPen(pen);
|
||||||
|
//painter.drawPoint(m_lastPoint);
|
||||||
|
|
||||||
m_lastPoint = p;
|
m_lastPoint = p;
|
||||||
}
|
}
|
||||||
@@ -166,14 +183,14 @@ void OsciWidget::updateDrawBuffer()
|
|||||||
|
|
||||||
resizeDrawBuffer();
|
resizeDrawBuffer();
|
||||||
darkenFrame();
|
darkenFrame();
|
||||||
// persistance time is the time it needs to decay to 1/e ~ 36,7%
|
// decay time is the time it needs to decay to 1/e ~ 36,7%
|
||||||
|
|
||||||
auto duration = 1000*(m_bufferTimer.elapsed()-m_lastTime);
|
auto duration = 1000*(m_globalTimer.elapsed()-m_lastBufferUpdate);
|
||||||
size_t framesOffset = framesForDuration(duration);
|
size_t framesOffset = framesForDuration(duration);
|
||||||
//qDebug() << framesOffset << m_buffer.size()-framesOffset << m_bufferOffset - m_buffer.begin();
|
//qDebug() << framesOffset << m_buffer.size()-framesOffset << m_bufferOffset - m_buffer.begin();
|
||||||
|
|
||||||
auto bufferEnd = m_buffer.begin() + std::min(framesOffset, m_buffer.size());
|
auto bufferEnd = m_buffer.begin() + std::min(framesOffset, m_buffer.size());
|
||||||
drawBuffer(m_bufferOffset, bufferEnd);
|
drawBuffer(m_bufferOffset, bufferEnd, QColor(0, 255, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
void OsciWidget::timerEvent(QTimerEvent *event)
|
void OsciWidget::timerEvent(QTimerEvent *event)
|
||||||
|
@@ -54,13 +54,13 @@ private:
|
|||||||
|
|
||||||
int m_frameCounter{0}, m_callbacksCounter{0}, m_samplesCounter{0};
|
int m_frameCounter{0}, m_callbacksCounter{0}, m_samplesCounter{0};
|
||||||
QElapsedTimer m_statsTimer;
|
QElapsedTimer m_statsTimer;
|
||||||
QElapsedTimer m_bufferTimer;
|
QElapsedTimer m_globalTimer;
|
||||||
qint64 m_lastTime;
|
qint64 m_lastBufferUpdate;
|
||||||
|
|
||||||
int m_redrawTimerId;
|
int m_redrawTimerId;
|
||||||
QPointF m_lastPoint;
|
QPointF m_lastPoint;
|
||||||
QPixmap m_pixmap;
|
QPixmap m_pixmap;
|
||||||
void darkenFrame();
|
void darkenFrame();
|
||||||
void drawBuffer(SampleBuffer::iterator &bufferPos, const SampleBuffer::iterator &end);
|
void drawBuffer(SampleBuffer::iterator &bufferPos, const SampleBuffer::iterator &end, QColor color);
|
||||||
void resizeDrawBuffer();
|
void resizeDrawBuffer();
|
||||||
};
|
};
|
||||||
|
Reference in New Issue
Block a user