diff --git a/sdrbase/dsp/spectrumsettings.cpp b/sdrbase/dsp/spectrumsettings.cpp
index 9b9116ecf0..f7b2ff96f8 100644
--- a/sdrbase/dsp/spectrumsettings.cpp
+++ b/sdrbase/dsp/spectrumsettings.cpp
@@ -66,7 +66,8 @@ void SpectrumSettings::resetToDefaults()
m_useCalibration = false;
m_calibrationInterpMode = CalibInterpLinear;
m_3DSpectrogramStyle = Outline;
- m_3DSpectrogramColorMap = "Angel";
+ m_colorMap = "Angel";
+ m_spectrumStyle = Line;
}
QByteArray SpectrumSettings::serialize() const
@@ -104,8 +105,9 @@ QByteArray SpectrumSettings::serialize() const
s.writeS32(30, (int) m_calibrationInterpMode);
s.writeBool(31, m_display3DSpectrogram);
s.writeS32(32, (int) m_3DSpectrogramStyle);
- s.writeString(33, m_3DSpectrogramColorMap);
- s.writeS32(100, m_histogramMarkers.size());
+ s.writeString(33, m_colorMap);
+ s.writeS32(34, (int) m_spectrumStyle);
+ s.writeS32(100, m_histogramMarkers.size());
for (int i = 0; i < m_histogramMarkers.size(); i++) {
s.writeBlob(101+i, m_histogramMarkers[i].serialize());
@@ -204,7 +206,8 @@ bool SpectrumSettings::deserialize(const QByteArray& data)
m_calibrationInterpMode = (CalibrationInterpolationMode) tmp;
d.readBool(31, &m_display3DSpectrogram, false);
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;
d.readS32(100, &histogramMarkersSize, 0);
diff --git a/sdrbase/dsp/spectrumsettings.h b/sdrbase/dsp/spectrumsettings.h
index badb812b21..71d6904e59 100644
--- a/sdrbase/dsp/spectrumsettings.h
+++ b/sdrbase/dsp/spectrumsettings.h
@@ -61,6 +61,13 @@ class SDRBASE_API SpectrumSettings : public Serializable
Shaded
};
+ enum SpectrumStyle
+ {
+ Line,
+ Fill,
+ Gradient
+ };
+
int m_fftSize;
int m_fftOverlap;
FFTWindow::Function m_fftWindow;
@@ -97,7 +104,8 @@ class SDRBASE_API SpectrumSettings : public Serializable
bool m_useCalibration;
CalibrationInterpolationMode m_calibrationInterpMode; //!< How is power interpolated between calibration points
SpectrogramStyle m_3DSpectrogramStyle;
- QString m_3DSpectrogramColorMap;
+ QString m_colorMap;
+ SpectrumStyle m_spectrumStyle;
static const int m_log2FFTSizeMin = 6; // 64
static const int m_log2FFTSizeMax = 15; // 32k
diff --git a/sdrbase/util/colormap.cpp b/sdrbase/util/colormap.cpp
index 9f9c7e7ea8..2f4eb61f48 100644
--- a/sdrbase/util/colormap.cpp
+++ b/sdrbase/util/colormap.cpp
@@ -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,
};
const float ColorMap::m_jet[m_size] =
diff --git a/sdrgui/CMakeLists.txt b/sdrgui/CMakeLists.txt
index 7594bb0d32..e0d590907d 100644
--- a/sdrgui/CMakeLists.txt
+++ b/sdrgui/CMakeLists.txt
@@ -44,6 +44,7 @@ set(sdrgui_SOURCES
gui/glscope.cpp
gui/glscopegui.cpp
gui/glshadercolors.cpp
+ gui/glshadercolormap.cpp
gui/glshadersimple.cpp
gui/glshaderspectrogram.cpp
gui/glshadertextured.cpp
@@ -145,6 +146,7 @@ set(sdrgui_HEADERS
gui/glscope.h
gui/glscopegui.h
gui/glshadercolors.h
+ gui/glshadercolormap.h
gui/glshadersimple.h
gui/glshaderspectrogram.h
gui/glshadertvarray.h
diff --git a/sdrgui/gui/glshadercolormap.cpp b/sdrgui/gui/glshadercolormap.cpp
new file mode 100644
index 0000000000..5a576bf065
--- /dev/null
+++ b/sdrgui/gui/glshadercolormap.cpp
@@ -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 . //
+///////////////////////////////////////////////////////////////////////////////////
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#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(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"
+ );
diff --git a/sdrgui/gui/glshadercolormap.h b/sdrgui/gui/glshadercolormap.h
new file mode 100644
index 0000000000..651abcbad5
--- /dev/null
+++ b/sdrgui/gui/glshadercolormap.h
@@ -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 . //
+///////////////////////////////////////////////////////////////////////////////////
+
+#ifndef INCLUDE_GUI_GLSHADERCOLORMAP_H_
+#define INCLUDE_GUI_GLSHADERCOLORMAP_H_
+
+#include
+#include
+#include
+#include
+#include
+
+#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_ */
diff --git a/sdrgui/gui/glshadersimple.cpp b/sdrgui/gui/glshadersimple.cpp
index 6905682fd0..125ae3081c 100644
--- a/sdrgui/gui/glshadersimple.cpp
+++ b/sdrgui/gui/glshadersimple.cpp
@@ -111,6 +111,11 @@ void GLShaderSimple::drawSurface(const QMatrix4x4& transformMatrix, const QVecto
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)
{
QOpenGLFunctions *f = QOpenGLContext::currentContext()->functions();
diff --git a/sdrgui/gui/glshadersimple.h b/sdrgui/gui/glshadersimple.h
index 5e261087d7..cac950165e 100644
--- a/sdrgui/gui/glshadersimple.h
+++ b/sdrgui/gui/glshadersimple.h
@@ -42,6 +42,7 @@ class SDRGUI_API GLShaderSimple
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 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();
private:
diff --git a/sdrgui/gui/glspectrum.cpp b/sdrgui/gui/glspectrum.cpp
index 816d575675..9ef07e2830 100644
--- a/sdrgui/gui/glspectrum.cpp
+++ b/sdrgui/gui/glspectrum.cpp
@@ -91,7 +91,7 @@ GLSpectrum::GLSpectrum(QWidget* parent) :
m_pan3DSpectrogram(false),
m_scaleZ3DSpectrogram(false),
m_3DSpectrogramStyle(SpectrumSettings::Outline),
- m_3DSpectrogramColorMap("Angel"),
+ m_colorMapName("Angel"),
m_histogramBuffer(nullptr),
m_histogram(nullptr),
m_displayHistogram(true),
@@ -345,16 +345,22 @@ void GLSpectrum::setDisplay3DSpectrogram(bool display)
update();
}
+void GLSpectrum::setSpectrumStyle(SpectrumSettings::SpectrumStyle style)
+{
+ m_spectrumStyle = style;
+ update();
+}
+
void GLSpectrum::set3DSpectrogramStyle(SpectrumSettings::SpectrogramStyle style)
{
m_3DSpectrogramStyle = style;
update();
}
-void GLSpectrum::set3DSpectrogramColorMap(const QString &colorMap)
+void GLSpectrum::setColorMapName(const QString &colorMapName)
{
m_mutex.lock();
- m_3DSpectrogramColorMap = colorMap;
+ m_colorMapName = colorMapName;
m_changesPending = true;
m_mutex.unlock();
update();
@@ -824,6 +830,7 @@ void GLSpectrum::initializeGL()
m_glShaderFrequencyScale.initializeGL(majorVersion, minorVersion);
m_glShaderWaterfall.initializeGL(majorVersion, minorVersion);
m_glShaderHistogram.initializeGL(majorVersion, minorVersion);
+ m_glShaderColorMap.initializeGL(majorVersion, minorVersion);
m_glShaderTextOverlay.initializeGL(majorVersion, minorVersion);
m_glShaderInfo.initializeGL(majorVersion, minorVersion);
m_glShaderSpectrogram.initializeGL(majorVersion, minorVersion);
@@ -1264,6 +1271,30 @@ void GLSpectrum::paintGL()
// m_referenceLevel - m_powerRange : bottom
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;
@@ -1289,10 +1320,40 @@ void GLSpectrum::paintGL()
// paint current spectrum line on top of histogram
if ((m_displayCurrent) && m_currentSpectrum)
{
+ Real bottom = -m_powerRange;
+ GLfloat *q3;
+
+ if (m_spectrumStyle != SpectrumSettings::Line)
{
- Real bottom = -m_powerRange;
- GLfloat *q3 = m_q3FFT.m_array;
+ 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++)
{
Real v = m_currentSpectrum[i] - m_referenceLevel;
@@ -1305,9 +1366,15 @@ void GLSpectrum::paintGL()
q3[2*i] = (Real) i;
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);
}
}
@@ -2598,7 +2665,17 @@ void GLSpectrum::applyChanges()
}
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)
{
@@ -2622,6 +2699,9 @@ void GLSpectrum::applyChanges()
memset(m_histogram, 0x00, 100 * 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)
diff --git a/sdrgui/gui/glspectrum.h b/sdrgui/gui/glspectrum.h
index 2993c73ca0..60141499b8 100644
--- a/sdrgui/gui/glspectrum.h
+++ b/sdrgui/gui/glspectrum.h
@@ -33,6 +33,7 @@
#include "gui/scaleengine.h"
#include "gui/glshadersimple.h"
#include "gui/glshadertextured.h"
+#include "gui/glshadercolormap.h"
#include "dsp/glspectruminterface.h"
#include "gui/glshaderspectrogram.h"
#include "dsp/spectrummarkers.h"
@@ -41,6 +42,7 @@
#include "export.h"
#include "util/incrementalarray.h"
#include "util/message.h"
+#include "util/colormap.h"
class QOpenGLShaderProgram;
class MessageQueue;
@@ -146,7 +148,8 @@ class SDRGUI_API GLSpectrum : public QOpenGLWidget, public GLSpectrumInterface {
void setDisplayWaterfall(bool display);
void setDisplay3DSpectrogram(bool display);
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 setLsbDisplay(bool lsbDisplay);
void setInvertedWaterfall(bool inv);
@@ -312,7 +315,9 @@ class SDRGUI_API GLSpectrum : public QOpenGLWidget, public GLSpectrumInterface {
QPixmap m_spectrogramTimePixmap;
QPixmap m_spectrogramPowerPixmap;
SpectrumSettings::SpectrogramStyle m_3DSpectrogramStyle;
- QString m_3DSpectrogramColorMap;
+ QString m_colorMapName;
+ SpectrumSettings::SpectrumStyle m_spectrumStyle;
+ const float *m_colorMap;
QRgb m_histogramPalette[240];
QImage* m_histogramBuffer;
@@ -336,6 +341,7 @@ class SDRGUI_API GLSpectrum : public QOpenGLWidget, public GLSpectrumInterface {
GLShaderTextured m_glShaderFrequencyScale;
GLShaderTextured m_glShaderWaterfall;
GLShaderTextured m_glShaderHistogram;
+ GLShaderColorMap m_glShaderColorMap;
GLShaderTextured m_glShaderTextOverlay;
GLShaderTextured m_glShaderInfo;
GLShaderSpectrogram m_glShaderSpectrogram;
@@ -351,6 +357,7 @@ class SDRGUI_API GLSpectrum : public QOpenGLWidget, public GLSpectrumInterface {
IncrementalArray m_q3TickFrequency;
IncrementalArray m_q3TickPower;
IncrementalArray m_q3FFT;
+ IncrementalArray m_q3ColorMap;
MessageQueue *m_messageQueueToGUI;
QOpenGLDebugLogger *m_openGLLogger;
diff --git a/sdrgui/gui/glspectrumgui.cpp b/sdrgui/gui/glspectrumgui.cpp
index 9377acaa6f..c6c6c105f3 100644
--- a/sdrgui/gui/glspectrumgui.cpp
+++ b/sdrgui/gui/glspectrumgui.cpp
@@ -71,8 +71,8 @@ GLSpectrumGUI::GLSpectrumGUI(QWidget* parent) :
ui->levelRange->setStyleSheet(levelStyle);
ui->fftOverlap->setStyleSheet(levelStyle);
- ui->spectrogramColorMap->addItems(ColorMap::getColorMapNames());
- ui->spectrogramColorMap->setCurrentText("Angel");
+ ui->colorMap->addItems(ColorMap::getColorMapNames());
+ ui->colorMap->setCurrentText("Angel");
connect(&m_messageQueue, SIGNAL(messageEnqueued()), this, SLOT(handleInputMessages()));
@@ -161,8 +161,8 @@ void GLSpectrumGUI::displaySettings()
ui->spectrogram->setChecked(m_settings.m_display3DSpectrogram);
ui->spectrogramStyle->setCurrentIndex((int) m_settings.m_3DSpectrogramStyle);
ui->spectrogramStyle->setVisible(m_settings.m_display3DSpectrogram);
- ui->spectrogramColorMap->setCurrentText(m_settings.m_3DSpectrogramColorMap);
- ui->spectrogramColorMap->setVisible(m_settings.m_display3DSpectrogram);
+ ui->colorMap->setCurrentText(m_settings.m_colorMap);
+ ui->spectrumStyle->setCurrentIndex((int) m_settings.m_spectrumStyle);
ui->maxHold->setChecked(m_settings.m_displayMaxHold);
ui->current->setChecked(m_settings.m_displayCurrent);
ui->histogram->setChecked(m_settings.m_displayHistogram);
@@ -246,7 +246,8 @@ void GLSpectrumGUI::applySpectrumSettings()
m_glSpectrum->setDisplayWaterfall(m_settings.m_displayWaterfall);
m_glSpectrum->setDisplay3DSpectrogram(m_settings.m_display3DSpectrogram);
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->setDisplayMaxHold(m_settings.m_displayMaxHold);
m_glSpectrum->setDisplayCurrent(m_settings.m_displayCurrent);
@@ -463,16 +464,22 @@ void GLSpectrumGUI::on_stroke_valueChanged(int index)
applySettings();
}
+void GLSpectrumGUI::on_spectrumStyle_currentIndexChanged(int index)
+{
+ m_settings.m_spectrumStyle = (SpectrumSettings::SpectrumStyle)index;
+ applySettings();
+}
+
void GLSpectrumGUI::on_spectrogramStyle_currentIndexChanged(int index)
{
m_settings.m_3DSpectrogramStyle = (SpectrumSettings::SpectrogramStyle)index;
applySettings();
}
-void GLSpectrumGUI::on_spectrogramColorMap_currentIndexChanged(int index)
+void GLSpectrumGUI::on_colorMap_currentIndexChanged(int index)
{
(void) index;
- m_settings.m_3DSpectrogramColorMap = ui->spectrogramColorMap->currentText();
+ m_settings.m_colorMap = ui->colorMap->currentText();
applySettings();
}
@@ -498,7 +505,6 @@ void GLSpectrumGUI::on_spectrogram_toggled(bool checked)
blockApplySettings(false);
}
ui->spectrogramStyle->setVisible(m_settings.m_display3DSpectrogram);
- ui->spectrogramColorMap->setVisible(m_settings.m_display3DSpectrogram);
applySettings();
}
diff --git a/sdrgui/gui/glspectrumgui.h b/sdrgui/gui/glspectrumgui.h
index 45d497bb04..b978fd4010 100644
--- a/sdrgui/gui/glspectrumgui.h
+++ b/sdrgui/gui/glspectrumgui.h
@@ -96,8 +96,9 @@ private slots:
void on_decay_valueChanged(int index);
void on_decayDivisor_valueChanged(int index);
void on_stroke_valueChanged(int index);
+ void on_spectrumStyle_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_traceIntensity_valueChanged(int index);
void on_averagingMode_currentIndexChanged(int index);
diff --git a/sdrgui/gui/glspectrumgui.ui b/sdrgui/gui/glspectrumgui.ui
index 12e355fa8d..1fb6d7e7fa 100644
--- a/sdrgui/gui/glspectrumgui.ui
+++ b/sdrgui/gui/glspectrumgui.ui
@@ -723,6 +723,40 @@
+ -
+
+
+
+ 80
+ 0
+
+
+
+
+ 80
+ 16777215
+
+
+
+ Spectrum Style
+
+
-
+
+ Line
+
+
+ -
+
+ Fill
+
+
+ -
+
+ Gradient
+
+
+
+
-
@@ -865,7 +899,7 @@
-
-
+
70
@@ -879,7 +913,7 @@
- 3D Spectrogram Color Map
+ Color Map