1
0
mirror of https://github.com/f4exb/sdrangel.git synced 2024-11-23 00:18:37 -05:00

Merge pull request #1299 from srcejon/spectrum_gradient

Spectrum fill/gradient
This commit is contained in:
Edouard Griffiths 2022-06-22 14:16:44 +02:00 committed by GitHub
commit 8b443037d1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 526 additions and 26 deletions

View File

@ -66,7 +66,8 @@ void SpectrumSettings::resetToDefaults()
m_useCalibration = false; m_useCalibration = false;
m_calibrationInterpMode = CalibInterpLinear; m_calibrationInterpMode = CalibInterpLinear;
m_3DSpectrogramStyle = Outline; m_3DSpectrogramStyle = Outline;
m_3DSpectrogramColorMap = "Angel"; m_colorMap = "Angel";
m_spectrumStyle = Line;
} }
QByteArray SpectrumSettings::serialize() const QByteArray SpectrumSettings::serialize() const
@ -104,7 +105,8 @@ QByteArray SpectrumSettings::serialize() const
s.writeS32(30, (int) m_calibrationInterpMode); s.writeS32(30, (int) m_calibrationInterpMode);
s.writeBool(31, m_display3DSpectrogram); s.writeBool(31, m_display3DSpectrogram);
s.writeS32(32, (int) m_3DSpectrogramStyle); s.writeS32(32, (int) m_3DSpectrogramStyle);
s.writeString(33, m_3DSpectrogramColorMap); s.writeString(33, m_colorMap);
s.writeS32(34, (int) m_spectrumStyle);
s.writeS32(100, m_histogramMarkers.size()); s.writeS32(100, m_histogramMarkers.size());
for (int i = 0; i < m_histogramMarkers.size(); i++) { for (int i = 0; i < m_histogramMarkers.size(); i++) {
@ -204,7 +206,8 @@ bool SpectrumSettings::deserialize(const QByteArray& data)
m_calibrationInterpMode = (CalibrationInterpolationMode) tmp; m_calibrationInterpMode = (CalibrationInterpolationMode) tmp;
d.readBool(31, &m_display3DSpectrogram, false); d.readBool(31, &m_display3DSpectrogram, false);
d.readS32(32, (int*)&m_3DSpectrogramStyle, (int)Outline); d.readS32(32, (int*)&m_3DSpectrogramStyle, (int)Outline);
d.readString(33, &m_3DSpectrogramColorMap, "Angel"); d.readString(33, &m_colorMap, "Angel");
d.readS32(34, (int*)&m_spectrumStyle, (int)Line);
int histogramMarkersSize; int histogramMarkersSize;
d.readS32(100, &histogramMarkersSize, 0); d.readS32(100, &histogramMarkersSize, 0);

View File

@ -61,6 +61,13 @@ public:
Shaded Shaded
}; };
enum SpectrumStyle
{
Line,
Fill,
Gradient
};
int m_fftSize; int m_fftSize;
int m_fftOverlap; int m_fftOverlap;
FFTWindow::Function m_fftWindow; FFTWindow::Function m_fftWindow;
@ -97,7 +104,8 @@ public:
bool m_useCalibration; bool m_useCalibration;
CalibrationInterpolationMode m_calibrationInterpMode; //!< How is power interpolated between calibration points CalibrationInterpolationMode m_calibrationInterpMode; //!< How is power interpolated between calibration points
SpectrogramStyle m_3DSpectrogramStyle; SpectrogramStyle m_3DSpectrogramStyle;
QString m_3DSpectrogramColorMap; QString m_colorMap;
SpectrumStyle m_spectrumStyle;
static const int m_log2FFTSizeMin = 6; // 64 static const int m_log2FFTSizeMin = 6; // 64
static const int m_log2FFTSizeMax = 15; // 32k static const int m_log2FFTSizeMax = 15; // 32k

View File

@ -315,6 +315,7 @@ const float ColorMap::m_angel[m_size] =
1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
1.0, 1.0, 1.0,
}; };
const float ColorMap::m_jet[m_size] = const float ColorMap::m_jet[m_size] =

View File

@ -44,6 +44,7 @@ set(sdrgui_SOURCES
gui/glscope.cpp gui/glscope.cpp
gui/glscopegui.cpp gui/glscopegui.cpp
gui/glshadercolors.cpp gui/glshadercolors.cpp
gui/glshadercolormap.cpp
gui/glshadersimple.cpp gui/glshadersimple.cpp
gui/glshaderspectrogram.cpp gui/glshaderspectrogram.cpp
gui/glshadertextured.cpp gui/glshadertextured.cpp
@ -145,6 +146,7 @@ set(sdrgui_HEADERS
gui/glscope.h gui/glscope.h
gui/glscopegui.h gui/glscopegui.h
gui/glshadercolors.h gui/glshadercolors.h
gui/glshadercolormap.h
gui/glshadersimple.h gui/glshadersimple.h
gui/glshaderspectrogram.h gui/glshaderspectrogram.h
gui/glshadertvarray.h gui/glshadertvarray.h

View File

@ -0,0 +1,283 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2016 Edouard Griffiths, F4EXB //
// Copyright (C) 2022 Jon Beniston, M7RCE //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation as version 3 of the License, or //
// (at your option) any later version. //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License V3 for more details. //
// //
// You should have received a copy of the GNU General Public License //
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#include <QOpenGLShaderProgram>
#include <QOpenGLFunctions>
#include <QOpenGLContext>
#include <QImage>
#include <QMatrix4x4>
#include <QVector4D>
#include <QDebug>
#include "gui/glshadercolormap.h"
#include "util/colormap.h"
GLShaderColorMap::GLShaderColorMap() :
m_program(nullptr),
m_vao(nullptr),
m_verticesBuf(nullptr),
m_colorMapTexture(nullptr),
m_colorMapTextureId(0),
m_vertexLoc(0),
m_matrixLoc(0),
m_colorMapLoc(0),
m_scaleLoc(0),
m_alphaLoc(0),
m_useImmutableStorage(true)
{ }
GLShaderColorMap::~GLShaderColorMap()
{
cleanup();
}
void GLShaderColorMap::initializeGL(int majorVersion, int minorVersion)
{
initializeOpenGLFunctions();
m_useImmutableStorage = useImmutableStorage();
qDebug() << "GLShaderColorMap::initializeGL: m_useImmutableStorage: " << m_useImmutableStorage;
m_program = new QOpenGLShaderProgram;
if ((majorVersion > 3) || ((majorVersion == 3) && (minorVersion >= 3)))
{
if (!m_program->addShaderFromSourceCode(QOpenGLShader::Vertex, m_vertexShaderSourceColorMap)) {
qDebug() << "GLShaderColorMap::initializeGL: error in vertex shader: " << m_program->log();
}
if (!m_program->addShaderFromSourceCode(QOpenGLShader::Fragment, m_fragmentShaderSourceColorMap)) {
qDebug() << "GLShaderColorMap::initializeGL: error in fragment shader: " << m_program->log();
}
m_vao = new QOpenGLVertexArrayObject();
m_vao->create();
m_vao->bind();
}
else
{
if (!m_program->addShaderFromSourceCode(QOpenGLShader::Vertex, m_vertexShaderSourceColorMap2)) {
qDebug() << "GLShaderColorMap::initializeGL: error in vertex shader: " << m_program->log();
}
if (!m_program->addShaderFromSourceCode(QOpenGLShader::Fragment, m_fragmentShaderSourceColorMap2)) {
qDebug() << "GLShaderColorMap::initializeGL: error in fragment shader: " << m_program->log();
}
}
m_program->bindAttributeLocation("vertex", 0);
if (!m_program->link()) {
qDebug() << "GLShaderColorMap::initializeGL: error linking shader: " << m_program->log();
}
m_program->bind();
m_vertexLoc = m_program->attributeLocation("vertex");
m_matrixLoc = m_program->uniformLocation("uMatrix");
m_colorMapLoc = m_program->uniformLocation("colorMap");
m_scaleLoc = m_program->uniformLocation("scale");
m_alphaLoc = m_program->uniformLocation("alpha");
if (m_vao)
{
m_verticesBuf = new QOpenGLBuffer(QOpenGLBuffer::VertexBuffer);
m_verticesBuf->setUsagePattern(QOpenGLBuffer::DynamicDraw);
m_verticesBuf->create();
m_vao->release();
}
m_program->release();
}
void GLShaderColorMap::initColorMapTexture(const QString &colorMapName)
{
if (m_useImmutableStorage) {
initColorMapTextureImmutable(colorMapName);
} else {
initColorMapTextureMutable(colorMapName);
}
}
void GLShaderColorMap::initColorMapTextureImmutable(const QString &colorMapName)
{
if (!m_colorMapTexture)
{
m_colorMapTexture = new QOpenGLTexture(QOpenGLTexture::Target1D);
m_colorMapTexture->setFormat(QOpenGLTexture::RGB32F);
m_colorMapTexture->setSize(256);
m_colorMapTexture->allocateStorage();
m_colorMapTexture->setMinificationFilter(QOpenGLTexture::Linear);
m_colorMapTexture->setMagnificationFilter(QOpenGLTexture::Linear);
m_colorMapTexture->setWrapMode(QOpenGLTexture::ClampToEdge);
}
GLfloat *colorMap = (GLfloat *)ColorMap::getColorMap(colorMapName);
if (colorMap) {
m_colorMapTexture->setData(QOpenGLTexture::RGB, QOpenGLTexture::Float32, colorMap);
} else {
qDebug() << "GLShaderColorMap::initColorMapTextureImmutable: colorMap " << colorMapName << " not supported";
}
}
void GLShaderColorMap::initColorMapTextureMutable(const QString &colorMapName)
{
if (m_colorMapTextureId)
{
glDeleteTextures(1, &m_colorMapTextureId);
m_colorMapTextureId = 0;
}
glGenTextures(1, &m_colorMapTextureId);
glBindTexture(GL_TEXTURE_1D, m_colorMapTextureId);
GLfloat *colorMap = (GLfloat *)ColorMap::getColorMap(colorMapName);
if (colorMap) {
glTexImage1D(GL_TEXTURE_1D, 0, GL_RGB, 256, 0, GL_RGB, GL_FLOAT, colorMap);
} else {
qDebug() << "GLShaderColorMap::initColorMapTextureMutable: colorMap " << colorMapName << " not supported";
}
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, QOpenGLTexture::Repeat);
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_T, QOpenGLTexture::Repeat);
}
void GLShaderColorMap::drawSurfaceStrip(const QMatrix4x4& transformMatrix, GLfloat *vertices, int nbVertices, float scale, float alpha)
{
QOpenGLFunctions *f = QOpenGLContext::currentContext()->functions();
m_program->bind();
m_program->setUniformValue(m_matrixLoc, transformMatrix);
m_colorMapTexture->bind();
m_program->setUniformValue(m_colorMapLoc, 0); // Texture unit 0 for color map
m_program->setUniformValue(m_scaleLoc, scale);
m_program->setUniformValue(m_alphaLoc, alpha);
if (m_vao)
{
m_vao->bind();
m_verticesBuf->bind();
m_verticesBuf->allocate(vertices, nbVertices * 2 * sizeof(GL_FLOAT));
m_program->enableAttributeArray(m_vertexLoc);
m_program->setAttributeBuffer(m_vertexLoc, GL_FLOAT, 0, 2);
}
else
{
f->glEnableVertexAttribArray(m_vertexLoc);
f->glVertexAttribPointer(m_vertexLoc, 2, GL_FLOAT, GL_FALSE, 0, vertices);
}
f->glEnable(GL_BLEND);
f->glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
f->glDrawArrays(GL_TRIANGLE_STRIP, 0, nbVertices);
if (m_vao)
{
m_vao->release();
}
else
{
f->glDisableVertexAttribArray(m_vertexLoc);
}
m_program->release();
}
void GLShaderColorMap::cleanup()
{
delete m_program;
m_program = nullptr;
delete m_vao;
m_vao = nullptr;
delete m_verticesBuf;
m_verticesBuf = nullptr;
delete m_colorMapTexture;
m_colorMapTexture = nullptr;
if (!QOpenGLContext::currentContext()) {
return;
}
if (m_colorMapTextureId)
{
glDeleteTextures(1, &m_colorMapTextureId);
m_colorMapTextureId = 0;
}
}
bool GLShaderColorMap::useImmutableStorage()
{
QOpenGLContext* ctx = QOpenGLContext::currentContext();
QSurfaceFormat sf = ctx->format();
if (sf.version() >= qMakePair(4, 2)
|| ctx->hasExtension(QByteArrayLiteral("GL_ARB_texture_storage"))
|| ctx->hasExtension(QByteArrayLiteral("GL_EXT_texture_storage")))
{
void (QOPENGLF_APIENTRYP glTexStorage2D)(
GLenum target, GLsizei levels, GLenum internalFormat, GLsizei width, GLsizei height);
glTexStorage2D = reinterpret_cast<void (QOPENGLF_APIENTRYP)(
GLenum, GLsizei, GLenum, GLsizei, GLsizei)>(ctx->getProcAddress("glTexStorage2D"));
int data = 0;
GLuint textureId;
glGenTextures(1, &textureId);
glBindTexture(GL_TEXTURE_2D, textureId);
glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, GL_RGBA, GL_UNSIGNED_BYTE, &data);
GLenum err = glGetError();
glDeleteTextures(1, &textureId);
return err == GL_NO_ERROR;
}
return false;
}
const QString GLShaderColorMap::m_vertexShaderSourceColorMap2 = QString(
"uniform highp mat4 uMatrix;\n"
"attribute highp vec4 vertex;\n"
"varying float y;\n"
"void main() {\n"
" gl_Position = uMatrix * vertex;\n"
" y = vertex.y;\n"
"}\n"
);
const QString GLShaderColorMap::m_vertexShaderSourceColorMap = QString(
"#version 330\n"
"uniform highp mat4 uMatrix;\n"
"in highp vec4 vertex;\n"
"out float y;\n"
"void main() {\n"
" gl_Position = uMatrix * vertex;\n"
" y = vertex.y;\n"
"}\n"
);
const QString GLShaderColorMap::m_fragmentShaderSourceColorMap2 = QString(
"uniform float alpha;\n"
"uniform float scale;\n"
"uniform highp sampler1D colorMap;\n"
"varying float y;\n"
"void main() {\n"
" gl_FragColor = vec4(texture1D(colorMap, 1.0-(y/scale)).rgb, alpha);\n"
"}\n"
);
const QString GLShaderColorMap::m_fragmentShaderSourceColorMap = QString(
"#version 330\n"
"uniform float alpha;\n"
"uniform float scale;\n"
"uniform sampler1D colorMap;\n"
"in float y;\n"
"out vec4 fragColor;\n"
"void main() {\n"
" fragColor = vec4(texture(colorMap, 1.0-(y/scale)).rgb, alpha);\n"
"}\n"
);

View File

@ -0,0 +1,69 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2016 Edouard Griffiths, F4EXB //
// Copyright (C) 2022 Jon Beniston, M7RCE //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation as version 3 of the License, or //
// (at your option) any later version. //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License V3 for more details. //
// //
// You should have received a copy of the GNU General Public License //
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#ifndef INCLUDE_GUI_GLSHADERCOLORMAP_H_
#define INCLUDE_GUI_GLSHADERCOLORMAP_H_
#include <QString>
#include <QOpenGLTexture>
#include <QOpenGLFunctions>
#include <QOpenGLVertexArrayObject>
#include <QOpenGLBuffer>
#include "export.h"
class QOpenGLShaderProgram;
class QMatrix4x4;
class QVector4D;
// Shader to fill with a gradient from a color map
// Used for filling the area under the spectrum
class SDRGUI_API GLShaderColorMap : protected QOpenGLFunctions
{
public:
GLShaderColorMap();
~GLShaderColorMap();
void initializeGL(int majorVersion, int minorVersion);
void initColorMapTexture(const QString &colorMapName);
void drawSurfaceStrip(const QMatrix4x4& transformMatrix, GLfloat *vertices, int nbVertices, float scale, float alpha);
void cleanup();
private:
void initColorMapTextureMutable(const QString &colorMapName);
void initColorMapTextureImmutable(const QString &colorMapName);
bool useImmutableStorage();
QOpenGLShaderProgram *m_program;
QOpenGLVertexArrayObject *m_vao;
QOpenGLBuffer *m_verticesBuf;
QOpenGLTexture *m_colorMapTexture;
unsigned int m_colorMapTextureId;
int m_vertexLoc;
int m_matrixLoc;
int m_colorMapLoc;
int m_scaleLoc;
int m_alphaLoc;
bool m_useImmutableStorage;
static const QString m_vertexShaderSourceColorMap2;
static const QString m_vertexShaderSourceColorMap;
static const QString m_fragmentShaderSourceColorMap2;
static const QString m_fragmentShaderSourceColorMap;
};
#endif /* INCLUDE_GUI_GLSHADERCOLORMAP_H_ */

View File

@ -111,6 +111,11 @@ void GLShaderSimple::drawSurface(const QMatrix4x4& transformMatrix, const QVecto
draw(GL_TRIANGLE_FAN, transformMatrix, color, vertices, nbVertices, nbComponents); draw(GL_TRIANGLE_FAN, transformMatrix, color, vertices, nbVertices, nbComponents);
} }
void GLShaderSimple::drawSurfaceStrip(const QMatrix4x4& transformMatrix, const QVector4D& color, GLfloat *vertices, int nbVertices, int nbComponents)
{
draw(GL_TRIANGLE_STRIP, transformMatrix, color, vertices, nbVertices, nbComponents);
}
void GLShaderSimple::draw(unsigned int mode, const QMatrix4x4& transformMatrix, const QVector4D& color, GLfloat *vertices, int nbVertices, int nbComponents) void GLShaderSimple::draw(unsigned int mode, const QMatrix4x4& transformMatrix, const QVector4D& color, GLfloat *vertices, int nbVertices, int nbComponents)
{ {
QOpenGLFunctions *f = QOpenGLContext::currentContext()->functions(); QOpenGLFunctions *f = QOpenGLContext::currentContext()->functions();

View File

@ -42,6 +42,7 @@ public:
void drawSegments(const QMatrix4x4& transformMatrix, const QVector4D& color, GLfloat *vertices, int nbVertices, int nbComponents=2); void drawSegments(const QMatrix4x4& transformMatrix, const QVector4D& color, GLfloat *vertices, int nbVertices, int nbComponents=2);
void drawContour(const QMatrix4x4& transformMatrix, const QVector4D& color, GLfloat *vertices, int nbVertices, int nbComponents=2); void drawContour(const QMatrix4x4& transformMatrix, const QVector4D& color, GLfloat *vertices, int nbVertices, int nbComponents=2);
void drawSurface(const QMatrix4x4& transformMatrix, const QVector4D& color, GLfloat *vertices, int nbVertices, int nbComponents=2); void drawSurface(const QMatrix4x4& transformMatrix, const QVector4D& color, GLfloat *vertices, int nbVertices, int nbComponents=2);
void drawSurfaceStrip(const QMatrix4x4& transformMatrix, const QVector4D& color, GLfloat *vertices, int nbVertices, int nbComponents=2);
void cleanup(); void cleanup();
private: private:

View File

@ -91,7 +91,7 @@ GLSpectrum::GLSpectrum(QWidget* parent) :
m_pan3DSpectrogram(false), m_pan3DSpectrogram(false),
m_scaleZ3DSpectrogram(false), m_scaleZ3DSpectrogram(false),
m_3DSpectrogramStyle(SpectrumSettings::Outline), m_3DSpectrogramStyle(SpectrumSettings::Outline),
m_3DSpectrogramColorMap("Angel"), m_colorMapName("Angel"),
m_histogramBuffer(nullptr), m_histogramBuffer(nullptr),
m_histogram(nullptr), m_histogram(nullptr),
m_displayHistogram(true), m_displayHistogram(true),
@ -345,16 +345,22 @@ void GLSpectrum::setDisplay3DSpectrogram(bool display)
update(); update();
} }
void GLSpectrum::setSpectrumStyle(SpectrumSettings::SpectrumStyle style)
{
m_spectrumStyle = style;
update();
}
void GLSpectrum::set3DSpectrogramStyle(SpectrumSettings::SpectrogramStyle style) void GLSpectrum::set3DSpectrogramStyle(SpectrumSettings::SpectrogramStyle style)
{ {
m_3DSpectrogramStyle = style; m_3DSpectrogramStyle = style;
update(); update();
} }
void GLSpectrum::set3DSpectrogramColorMap(const QString &colorMap) void GLSpectrum::setColorMapName(const QString &colorMapName)
{ {
m_mutex.lock(); m_mutex.lock();
m_3DSpectrogramColorMap = colorMap; m_colorMapName = colorMapName;
m_changesPending = true; m_changesPending = true;
m_mutex.unlock(); m_mutex.unlock();
update(); update();
@ -824,6 +830,7 @@ void GLSpectrum::initializeGL()
m_glShaderFrequencyScale.initializeGL(majorVersion, minorVersion); m_glShaderFrequencyScale.initializeGL(majorVersion, minorVersion);
m_glShaderWaterfall.initializeGL(majorVersion, minorVersion); m_glShaderWaterfall.initializeGL(majorVersion, minorVersion);
m_glShaderHistogram.initializeGL(majorVersion, minorVersion); m_glShaderHistogram.initializeGL(majorVersion, minorVersion);
m_glShaderColorMap.initializeGL(majorVersion, minorVersion);
m_glShaderTextOverlay.initializeGL(majorVersion, minorVersion); m_glShaderTextOverlay.initializeGL(majorVersion, minorVersion);
m_glShaderInfo.initializeGL(majorVersion, minorVersion); m_glShaderInfo.initializeGL(majorVersion, minorVersion);
m_glShaderSpectrogram.initializeGL(majorVersion, minorVersion); m_glShaderSpectrogram.initializeGL(majorVersion, minorVersion);
@ -1264,6 +1271,30 @@ void GLSpectrum::paintGL()
// m_referenceLevel - m_powerRange : bottom // m_referenceLevel - m_powerRange : bottom
m_maxHold[i] = ((j - 99) * m_powerRange) / 99.0 + m_referenceLevel; m_maxHold[i] = ((j - 99) * m_powerRange) / 99.0 + m_referenceLevel;
} }
// Fill under max hold line
if (m_spectrumStyle != SpectrumSettings::Line)
{
GLfloat *q3 = m_q3ColorMap.m_array;
for (int i = 0; i < m_nbBins; i++)
{
Real v = m_maxHold[i] - m_referenceLevel;
if (v > 0) {
v = 0;
} else if (v < -m_powerRange) {
v = -m_powerRange;
}
q3[4*i] = (GLfloat)i;
q3[4*i+1] = -m_powerRange;
q3[4*i+2] = (GLfloat)i;
q3[4*i+3] = v;
}
QVector4D color(0.5f, 0.0f, 0.0f, (float) m_displayTraceIntensity / 100.0f);
m_glShaderSimple.drawSurfaceStrip(m_glHistogramSpectrumMatrix, color, q3, 2*m_nbBins);
}
// Max hold line
{ {
GLfloat *q3 = m_q3FFT.m_array; GLfloat *q3 = m_q3FFT.m_array;
@ -1288,11 +1319,41 @@ void GLSpectrum::paintGL()
// paint current spectrum line on top of histogram // paint current spectrum line on top of histogram
if ((m_displayCurrent) && m_currentSpectrum) if ((m_displayCurrent) && m_currentSpectrum)
{
{ {
Real bottom = -m_powerRange; Real bottom = -m_powerRange;
GLfloat *q3 = m_q3FFT.m_array; GLfloat *q3;
if (m_spectrumStyle != SpectrumSettings::Line)
{
q3 = m_q3ColorMap.m_array;
// Fill under line
for (int i = 0; i < m_nbBins; i++)
{
Real v = m_currentSpectrum[i] - m_referenceLevel;
if (v > 0) {
v = 0;
} else if (v < bottom) {
v = bottom;
}
q3[4*i] = (GLfloat)i;
q3[4*i+1] = bottom;
q3[4*i+2] = (GLfloat)i;
q3[4*i+3] = v;
}
QVector4D color(1.0f, 1.0f, 0.25f, (float) m_displayTraceIntensity / 100.0f);
if (m_spectrumStyle == SpectrumSettings::Gradient) {
m_glShaderColorMap.drawSurfaceStrip(m_glHistogramSpectrumMatrix, q3, 2*m_nbBins, bottom, 0.75f);
} else {
m_glShaderSimple.drawSurfaceStrip(m_glHistogramSpectrumMatrix, color, q3, 2*m_nbBins);
}
}
{
// Draw line
q3 = m_q3FFT.m_array;
for (int i = 0; i < m_nbBins; i++) for (int i = 0; i < m_nbBins; i++)
{ {
Real v = m_currentSpectrum[i] - m_referenceLevel; Real v = m_currentSpectrum[i] - m_referenceLevel;
@ -1305,9 +1366,15 @@ void GLSpectrum::paintGL()
q3[2*i] = (Real) i; q3[2*i] = (Real) i;
q3[2*i+1] = v; q3[2*i+1] = v;
} }
QVector4D color(1.0f, 1.0f, 0.25f, (float) m_displayTraceIntensity / 100.0f); QVector4D color;
if (m_spectrumStyle == SpectrumSettings::Gradient) {
color = QVector4D(m_colorMap[255*3], m_colorMap[255*3+1], m_colorMap[255*3+2], (float) m_displayTraceIntensity / 100.0f);
} else {
color = QVector4D(1.0f, 1.0f, 0.25f, (float) m_displayTraceIntensity / 100.0f);
}
m_glShaderSimple.drawPolyline(m_glHistogramSpectrumMatrix, color, q3, m_nbBins); m_glShaderSimple.drawPolyline(m_glHistogramSpectrumMatrix, color, q3, m_nbBins);
} }
} }
@ -2598,7 +2665,17 @@ void GLSpectrum::applyChanges()
} }
m_3DSpectrogramBufferPos = 0; m_3DSpectrogramBufferPos = 0;
} }
m_glShaderSpectrogram.initColorMapTexture(m_3DSpectrogramColorMap); m_glShaderSpectrogram.initColorMapTexture(m_colorMapName);
m_glShaderColorMap.initColorMapTexture(m_colorMapName);
m_colorMap = ColorMap::getColorMap(m_colorMapName);
// Why only 240 entries in the palette?
for (int i = 0; i <= 239; i++)
{
((quint8*)&m_waterfallPalette[i])[0] = (quint8)(m_colorMap[i*3] * 255.0);
((quint8*)&m_waterfallPalette[i])[1] = (quint8)(m_colorMap[i*3+1] * 255.0);
((quint8*)&m_waterfallPalette[i])[2] = (quint8)(m_colorMap[i*3+2] * 255.0);
((quint8*)&m_waterfallPalette[i])[3] = 255;
}
if (fftSizeChanged) if (fftSizeChanged)
{ {
@ -2622,6 +2699,9 @@ void GLSpectrum::applyChanges()
memset(m_histogram, 0x00, 100 * m_nbBins); memset(m_histogram, 0x00, 100 * m_nbBins);
m_q3FFT.allocate(2*m_nbBins); m_q3FFT.allocate(2*m_nbBins);
m_q3ColorMap.allocate(4*m_nbBins);
std::fill(m_q3ColorMap.m_array, m_q3ColorMap.m_array+4*m_nbBins, 0.0f);
} }
if (fftSizeChanged || windowSizeChanged) if (fftSizeChanged || windowSizeChanged)

View File

@ -33,6 +33,7 @@
#include "gui/scaleengine.h" #include "gui/scaleengine.h"
#include "gui/glshadersimple.h" #include "gui/glshadersimple.h"
#include "gui/glshadertextured.h" #include "gui/glshadertextured.h"
#include "gui/glshadercolormap.h"
#include "dsp/glspectruminterface.h" #include "dsp/glspectruminterface.h"
#include "gui/glshaderspectrogram.h" #include "gui/glshaderspectrogram.h"
#include "dsp/spectrummarkers.h" #include "dsp/spectrummarkers.h"
@ -41,6 +42,7 @@
#include "export.h" #include "export.h"
#include "util/incrementalarray.h" #include "util/incrementalarray.h"
#include "util/message.h" #include "util/message.h"
#include "util/colormap.h"
class QOpenGLShaderProgram; class QOpenGLShaderProgram;
class MessageQueue; class MessageQueue;
@ -146,7 +148,8 @@ public:
void setDisplayWaterfall(bool display); void setDisplayWaterfall(bool display);
void setDisplay3DSpectrogram(bool display); void setDisplay3DSpectrogram(bool display);
void set3DSpectrogramStyle(SpectrumSettings::SpectrogramStyle style); void set3DSpectrogramStyle(SpectrumSettings::SpectrogramStyle style);
void set3DSpectrogramColorMap(const QString &colorMap); void setColorMapName(const QString &colorMapName);
void setSpectrumStyle(SpectrumSettings::SpectrumStyle style);
void setSsbSpectrum(bool ssbSpectrum); void setSsbSpectrum(bool ssbSpectrum);
void setLsbDisplay(bool lsbDisplay); void setLsbDisplay(bool lsbDisplay);
void setInvertedWaterfall(bool inv); void setInvertedWaterfall(bool inv);
@ -312,7 +315,9 @@ private:
QPixmap m_spectrogramTimePixmap; QPixmap m_spectrogramTimePixmap;
QPixmap m_spectrogramPowerPixmap; QPixmap m_spectrogramPowerPixmap;
SpectrumSettings::SpectrogramStyle m_3DSpectrogramStyle; SpectrumSettings::SpectrogramStyle m_3DSpectrogramStyle;
QString m_3DSpectrogramColorMap; QString m_colorMapName;
SpectrumSettings::SpectrumStyle m_spectrumStyle;
const float *m_colorMap;
QRgb m_histogramPalette[240]; QRgb m_histogramPalette[240];
QImage* m_histogramBuffer; QImage* m_histogramBuffer;
@ -336,6 +341,7 @@ private:
GLShaderTextured m_glShaderFrequencyScale; GLShaderTextured m_glShaderFrequencyScale;
GLShaderTextured m_glShaderWaterfall; GLShaderTextured m_glShaderWaterfall;
GLShaderTextured m_glShaderHistogram; GLShaderTextured m_glShaderHistogram;
GLShaderColorMap m_glShaderColorMap;
GLShaderTextured m_glShaderTextOverlay; GLShaderTextured m_glShaderTextOverlay;
GLShaderTextured m_glShaderInfo; GLShaderTextured m_glShaderInfo;
GLShaderSpectrogram m_glShaderSpectrogram; GLShaderSpectrogram m_glShaderSpectrogram;
@ -351,6 +357,7 @@ private:
IncrementalArray<GLfloat> m_q3TickFrequency; IncrementalArray<GLfloat> m_q3TickFrequency;
IncrementalArray<GLfloat> m_q3TickPower; IncrementalArray<GLfloat> m_q3TickPower;
IncrementalArray<GLfloat> m_q3FFT; IncrementalArray<GLfloat> m_q3FFT;
IncrementalArray<GLfloat> m_q3ColorMap;
MessageQueue *m_messageQueueToGUI; MessageQueue *m_messageQueueToGUI;
QOpenGLDebugLogger *m_openGLLogger; QOpenGLDebugLogger *m_openGLLogger;

View File

@ -71,8 +71,8 @@ GLSpectrumGUI::GLSpectrumGUI(QWidget* parent) :
ui->levelRange->setStyleSheet(levelStyle); ui->levelRange->setStyleSheet(levelStyle);
ui->fftOverlap->setStyleSheet(levelStyle); ui->fftOverlap->setStyleSheet(levelStyle);
ui->spectrogramColorMap->addItems(ColorMap::getColorMapNames()); ui->colorMap->addItems(ColorMap::getColorMapNames());
ui->spectrogramColorMap->setCurrentText("Angel"); ui->colorMap->setCurrentText("Angel");
connect(&m_messageQueue, SIGNAL(messageEnqueued()), this, SLOT(handleInputMessages())); connect(&m_messageQueue, SIGNAL(messageEnqueued()), this, SLOT(handleInputMessages()));
@ -161,8 +161,8 @@ void GLSpectrumGUI::displaySettings()
ui->spectrogram->setChecked(m_settings.m_display3DSpectrogram); ui->spectrogram->setChecked(m_settings.m_display3DSpectrogram);
ui->spectrogramStyle->setCurrentIndex((int) m_settings.m_3DSpectrogramStyle); ui->spectrogramStyle->setCurrentIndex((int) m_settings.m_3DSpectrogramStyle);
ui->spectrogramStyle->setVisible(m_settings.m_display3DSpectrogram); ui->spectrogramStyle->setVisible(m_settings.m_display3DSpectrogram);
ui->spectrogramColorMap->setCurrentText(m_settings.m_3DSpectrogramColorMap); ui->colorMap->setCurrentText(m_settings.m_colorMap);
ui->spectrogramColorMap->setVisible(m_settings.m_display3DSpectrogram); ui->spectrumStyle->setCurrentIndex((int) m_settings.m_spectrumStyle);
ui->maxHold->setChecked(m_settings.m_displayMaxHold); ui->maxHold->setChecked(m_settings.m_displayMaxHold);
ui->current->setChecked(m_settings.m_displayCurrent); ui->current->setChecked(m_settings.m_displayCurrent);
ui->histogram->setChecked(m_settings.m_displayHistogram); ui->histogram->setChecked(m_settings.m_displayHistogram);
@ -246,7 +246,8 @@ void GLSpectrumGUI::applySpectrumSettings()
m_glSpectrum->setDisplayWaterfall(m_settings.m_displayWaterfall); m_glSpectrum->setDisplayWaterfall(m_settings.m_displayWaterfall);
m_glSpectrum->setDisplay3DSpectrogram(m_settings.m_display3DSpectrogram); m_glSpectrum->setDisplay3DSpectrogram(m_settings.m_display3DSpectrogram);
m_glSpectrum->set3DSpectrogramStyle(m_settings.m_3DSpectrogramStyle); m_glSpectrum->set3DSpectrogramStyle(m_settings.m_3DSpectrogramStyle);
m_glSpectrum->set3DSpectrogramColorMap(m_settings.m_3DSpectrogramColorMap); m_glSpectrum->setColorMapName(m_settings.m_colorMap);
m_glSpectrum->setSpectrumStyle(m_settings.m_spectrumStyle);
m_glSpectrum->setInvertedWaterfall(m_settings.m_invertedWaterfall); m_glSpectrum->setInvertedWaterfall(m_settings.m_invertedWaterfall);
m_glSpectrum->setDisplayMaxHold(m_settings.m_displayMaxHold); m_glSpectrum->setDisplayMaxHold(m_settings.m_displayMaxHold);
m_glSpectrum->setDisplayCurrent(m_settings.m_displayCurrent); m_glSpectrum->setDisplayCurrent(m_settings.m_displayCurrent);
@ -463,16 +464,22 @@ void GLSpectrumGUI::on_stroke_valueChanged(int index)
applySettings(); applySettings();
} }
void GLSpectrumGUI::on_spectrumStyle_currentIndexChanged(int index)
{
m_settings.m_spectrumStyle = (SpectrumSettings::SpectrumStyle)index;
applySettings();
}
void GLSpectrumGUI::on_spectrogramStyle_currentIndexChanged(int index) void GLSpectrumGUI::on_spectrogramStyle_currentIndexChanged(int index)
{ {
m_settings.m_3DSpectrogramStyle = (SpectrumSettings::SpectrogramStyle)index; m_settings.m_3DSpectrogramStyle = (SpectrumSettings::SpectrogramStyle)index;
applySettings(); applySettings();
} }
void GLSpectrumGUI::on_spectrogramColorMap_currentIndexChanged(int index) void GLSpectrumGUI::on_colorMap_currentIndexChanged(int index)
{ {
(void) index; (void) index;
m_settings.m_3DSpectrogramColorMap = ui->spectrogramColorMap->currentText(); m_settings.m_colorMap = ui->colorMap->currentText();
applySettings(); applySettings();
} }
@ -498,7 +505,6 @@ void GLSpectrumGUI::on_spectrogram_toggled(bool checked)
blockApplySettings(false); blockApplySettings(false);
} }
ui->spectrogramStyle->setVisible(m_settings.m_display3DSpectrogram); ui->spectrogramStyle->setVisible(m_settings.m_display3DSpectrogram);
ui->spectrogramColorMap->setVisible(m_settings.m_display3DSpectrogram);
applySettings(); applySettings();
} }

View File

@ -96,8 +96,9 @@ private slots:
void on_decay_valueChanged(int index); void on_decay_valueChanged(int index);
void on_decayDivisor_valueChanged(int index); void on_decayDivisor_valueChanged(int index);
void on_stroke_valueChanged(int index); void on_stroke_valueChanged(int index);
void on_spectrumStyle_currentIndexChanged(int index);
void on_spectrogramStyle_currentIndexChanged(int index); void on_spectrogramStyle_currentIndexChanged(int index);
void on_spectrogramColorMap_currentIndexChanged(int index); void on_colorMap_currentIndexChanged(int index);
void on_gridIntensity_valueChanged(int index); void on_gridIntensity_valueChanged(int index);
void on_traceIntensity_valueChanged(int index); void on_traceIntensity_valueChanged(int index);
void on_averagingMode_currentIndexChanged(int index); void on_averagingMode_currentIndexChanged(int index);

View File

@ -723,6 +723,40 @@
</property> </property>
</widget> </widget>
</item> </item>
<item>
<widget class="QComboBox" name="spectrumStyle">
<property name="minimumSize">
<size>
<width>80</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>80</width>
<height>16777215</height>
</size>
</property>
<property name="toolTip">
<string>Spectrum Style</string>
</property>
<item>
<property name="text">
<string>Line</string>
</property>
</item>
<item>
<property name="text">
<string>Fill</string>
</property>
</item>
<item>
<property name="text">
<string>Gradient</string>
</property>
</item>
</widget>
</item>
<item> <item>
<widget class="QDial" name="traceIntensity"> <widget class="QDial" name="traceIntensity">
<property name="maximumSize"> <property name="maximumSize">
@ -865,7 +899,7 @@
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QComboBox" name="spectrogramColorMap"> <widget class="QComboBox" name="colorMap">
<property name="minimumSize"> <property name="minimumSize">
<size> <size>
<width>70</width> <width>70</width>
@ -879,7 +913,7 @@
</size> </size>
</property> </property>
<property name="toolTip"> <property name="toolTip">
<string>3D Spectrogram Color Map</string> <string>Color Map</string>
</property> </property>
</widget> </widget>
</item> </item>