Adding color table layer

This commit is contained in:
Dan Paulat 2021-11-16 22:43:52 -06:00
parent 5bbfb1ecd9
commit 1c093d01f4
12 changed files with 324 additions and 25 deletions

15
scwx-qt/gl/texture1d.frag Normal file
View file

@ -0,0 +1,15 @@
#version 330 core
// Lower the default precision to medium
precision mediump float;
uniform sampler1D uTexture;
in float texCoord;
layout (location = 0) out vec4 fragColor;
void main()
{
fragColor = texture(uTexture, texCoord);
}

13
scwx-qt/gl/texture1d.vert Normal file
View file

@ -0,0 +1,13 @@
#version 330 core
layout (location = 0) in vec2 aVertex;
layout (location = 1) in float aTexCoord;
out float texCoord;
uniform mat4 uMVPMatrix;
void main()
{
gl_Position = uMVPMatrix * vec4(aVertex, 0.0f, 1.0f);
texCoord = aTexCoord;
}

View file

@ -64,12 +64,14 @@ set(HDR_MANAGER source/scwx/qt/manager/radar_product_manager.hpp
set(SRC_MANAGER source/scwx/qt/manager/radar_product_manager.cpp
source/scwx/qt/manager/resource_manager.cpp
source/scwx/qt/manager/settings_manager.cpp)
set(HDR_MAP source/scwx/qt/map/map_widget.hpp
set(HDR_MAP source/scwx/qt/map/color_table_layer.hpp
source/scwx/qt/map/map_widget.hpp
source/scwx/qt/map/overlay_layer.hpp
source/scwx/qt/map/radar_product_layer.hpp
source/scwx/qt/map/radar_range_layer.hpp
source/scwx/qt/map/triangle_layer.hpp)
set(SRC_MAP source/scwx/qt/map/map_widget.cpp
set(SRC_MAP source/scwx/qt/map/color_table_layer.cpp
source/scwx/qt/map/map_widget.cpp
source/scwx/qt/map/overlay_layer.cpp
source/scwx/qt/map/radar_product_layer.cpp
source/scwx/qt/map/radar_range_layer.cpp
@ -100,7 +102,9 @@ set(SHADER_FILES gl/overlay.frag
gl/radar.frag
gl/radar.vert
gl/text.frag
gl/text.vert)
gl/text.vert
gl/texture1d.frag
gl/texture1d.vert)
set(TS_FILES ts/scwx_en_US.ts)

View file

@ -6,6 +6,8 @@
<file>gl/radar.vert</file>
<file>gl/text.frag</file>
<file>gl/text.vert</file>
<file>gl/texture1d.frag</file>
<file>gl/texture1d.vert</file>
<file>res/fonts/din1451alt.ttf</file>
<file>res/fonts/din1451alt_g.ttf</file>
</qresource>

View file

@ -0,0 +1,191 @@
#include <scwx/qt/map/color_table_layer.hpp>
#include <scwx/qt/gl/shader_program.hpp>
#include <boost/log/trivial.hpp>
#include <glm/glm.hpp>
#include <glm/gtc/type_ptr.hpp>
namespace scwx
{
namespace qt
{
namespace map
{
static const std::string logPrefix_ = "[scwx::qt::map::color_table_layer] ";
class ColorTableLayerImpl
{
public:
explicit ColorTableLayerImpl(
std::shared_ptr<view::RadarProductView> radarProductView,
gl::OpenGLFunctions& gl) :
radarProductView_(radarProductView),
gl_(gl),
shaderProgram_(gl),
uMVPMatrixLocation_(GL_INVALID_INDEX),
vbo_ {GL_INVALID_INDEX},
vao_ {GL_INVALID_INDEX},
texture_ {GL_INVALID_INDEX},
colorTableNeedsUpdate_ {true}
{
}
~ColorTableLayerImpl() = default;
std::shared_ptr<view::RadarProductView> radarProductView_;
gl::OpenGLFunctions& gl_;
gl::ShaderProgram shaderProgram_;
GLint uMVPMatrixLocation_;
std::array<GLuint, 2> vbo_;
GLuint vao_;
GLuint texture_;
std::vector<boost::gil::rgba8_pixel_t> colorTable_;
bool colorTableNeedsUpdate_;
};
ColorTableLayer::ColorTableLayer(
std::shared_ptr<view::RadarProductView> radarProductView,
gl::OpenGLFunctions& gl) :
p(std::make_unique<ColorTableLayerImpl>(radarProductView, gl))
{
}
ColorTableLayer::~ColorTableLayer() = default;
void ColorTableLayer::initialize()
{
BOOST_LOG_TRIVIAL(debug) << logPrefix_ << "initialize()";
gl::OpenGLFunctions& gl = p->gl_;
// Load and configure overlay shader
p->shaderProgram_.Load(":/gl/texture1d.vert", ":/gl/texture1d.frag");
p->uMVPMatrixLocation_ =
gl.glGetUniformLocation(p->shaderProgram_.id(), "uMVPMatrix");
if (p->uMVPMatrixLocation_ == -1)
{
BOOST_LOG_TRIVIAL(warning) << logPrefix_ << "Could not find uMVPMatrix";
}
gl.glGenTextures(1, &p->texture_);
p->shaderProgram_.Use();
// Generate a vertex array object
gl.glGenVertexArrays(1, &p->vao_);
// Generate vertex buffer objects
gl.glGenBuffers(2, p->vbo_.data());
gl.glBindVertexArray(p->vao_);
// Bottom panel
gl.glBindBuffer(GL_ARRAY_BUFFER, p->vbo_[0]);
gl.glBufferData(
GL_ARRAY_BUFFER, sizeof(float) * 6 * 2, nullptr, GL_DYNAMIC_DRAW);
gl.glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, static_cast<void*>(0));
gl.glEnableVertexAttribArray(0);
// Color table panel texture coordinates
const float textureCoords[6][1] = {{0.0f}, // TL
{0.0f}, // BL
{1.0f}, // TR
//
{0.0f}, // BL
{1.0f}, // TR
{1.0f}}; // BR
gl.glBindBuffer(GL_ARRAY_BUFFER, p->vbo_[1]);
gl.glBufferData(
GL_ARRAY_BUFFER, sizeof(textureCoords), textureCoords, GL_STATIC_DRAW);
gl.glVertexAttribPointer(1, 1, GL_FLOAT, GL_FALSE, 0, static_cast<void*>(0));
gl.glEnableVertexAttribArray(1);
connect(p->radarProductView_.get(),
&view::RadarProductView::ColorTableUpdated,
this,
[=]() { p->colorTableNeedsUpdate_ = true; });
}
void ColorTableLayer::render(const QMapbox::CustomLayerRenderParameters& params)
{
gl::OpenGLFunctions& gl = p->gl_;
glm::mat4 projection = glm::ortho(0.0f,
static_cast<float>(params.width),
0.0f,
static_cast<float>(params.height));
p->shaderProgram_.Use();
gl.glUniformMatrix4fv(
p->uMVPMatrixLocation_, 1, GL_FALSE, glm::value_ptr(projection));
if (p->colorTableNeedsUpdate_)
{
p->colorTable_ = p->radarProductView_->color_table();
gl.glActiveTexture(GL_TEXTURE0);
gl.glBindTexture(GL_TEXTURE_1D, p->texture_);
gl.glTexImage1D(GL_TEXTURE_1D,
0,
GL_RGBA,
(GLsizei) p->colorTable_.size(),
0,
GL_RGBA,
GL_UNSIGNED_BYTE,
p->colorTable_.data());
gl.glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
gl.glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
gl.glGenerateMipmap(GL_TEXTURE_1D);
}
if (p->colorTable_.size() > 0 && p->radarProductView_->sweep_time() !=
std::chrono::system_clock::time_point())
{
// Color table panel vertices
const float vertexLX = 0.0f;
const float vertexRX = static_cast<float>(params.width);
const float vertexTY = 10.0f;
const float vertexBY = 0.0f;
const float vertices[6][2] = {{vertexLX, vertexTY}, // TL
{vertexLX, vertexBY}, // BL
{vertexRX, vertexTY}, // TR
//
{vertexLX, vertexBY}, // BL
{vertexRX, vertexTY}, // TR
{vertexRX, vertexBY}}; // BR
// Draw vertices
gl.glBindVertexArray(p->vao_);
gl.glBindBuffer(GL_ARRAY_BUFFER, p->vbo_[0]);
gl.glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices);
gl.glDrawArrays(GL_TRIANGLES, 0, 6);
}
SCWX_GL_CHECK_ERROR();
}
void ColorTableLayer::deinitialize()
{
gl::OpenGLFunctions& gl = p->gl_;
BOOST_LOG_TRIVIAL(debug) << logPrefix_ << "deinitialize()";
gl.glDeleteVertexArrays(1, &p->vao_);
gl.glDeleteBuffers(2, p->vbo_.data());
gl.glDeleteTextures(1, &p->texture_);
p->uMVPMatrixLocation_ = GL_INVALID_INDEX;
p->vao_ = GL_INVALID_INDEX;
p->vbo_ = {GL_INVALID_INDEX};
p->texture_ = GL_INVALID_INDEX;
}
} // namespace map
} // namespace qt
} // namespace scwx

View file

@ -0,0 +1,37 @@
#pragma once
#include <scwx/qt/gl/gl.hpp>
#include <scwx/qt/view/radar_product_view.hpp>
#include <QMapboxGL>
namespace scwx
{
namespace qt
{
namespace map
{
class ColorTableLayerImpl;
class ColorTableLayer : public QObject, public QMapbox::CustomLayerHostInterface
{
Q_OBJECT
public:
explicit ColorTableLayer(
std::shared_ptr<view::RadarProductView> radarProductView,
gl::OpenGLFunctions& gl);
~ColorTableLayer();
void initialize() override final;
void render(const QMapbox::CustomLayerRenderParameters&) override final;
void deinitialize() override final;
private:
std::unique_ptr<ColorTableLayerImpl> p;
};
} // namespace map
} // namespace qt
} // namespace scwx

View file

@ -2,6 +2,7 @@
#include <scwx/qt/gl/gl.hpp>
#include <scwx/qt/manager/radar_product_manager.hpp>
#include <scwx/qt/manager/settings_manager.hpp>
#include <scwx/qt/map/color_table_layer.hpp>
#include <scwx/qt/map/overlay_layer.hpp>
#include <scwx/qt/map/radar_product_layer.hpp>
#include <scwx/qt/map/radar_range_layer.hpp>
@ -180,12 +181,18 @@ void MapWidget::AddLayers()
{
p->map_->removeLayer("overlay");
}
if (p->map_->layerExists("colorTable"))
{
p->map_->removeLayer("colorTable");
}
// QMapboxGL::addCustomLayer will take ownership of the QScopedPointer
QScopedPointer<QMapbox::CustomLayerHostInterface> pHost(
new RadarProductLayer(p->radarProductView_, p->gl_));
QScopedPointer<QMapbox::CustomLayerHostInterface> pOverlayHost(
new OverlayLayer(p->radarProductView_, p->gl_));
QScopedPointer<QMapbox::CustomLayerHostInterface> pColorTableHost(
new ColorTableLayer(p->radarProductView_, p->gl_));
QString before = "ferry";
@ -203,6 +210,7 @@ void MapWidget::AddLayers()
p->map_->addCustomLayer("radar", pHost, before);
RadarRangeLayer::Add(p->map_, p->radarProductView_->range(), before);
p->map_->addCustomLayer("overlay", pOverlayHost);
p->map_->addCustomLayer("colorTable", pColorTableHost);
}
void MapWidget::keyPressEvent(QKeyEvent* ev)

View file

@ -318,18 +318,16 @@ void RadarProductLayer::UpdateColorTable()
{
BOOST_LOG_TRIVIAL(debug) << logPrefix_ << "UpdateColorTable()";
uint16_t rangeMin;
uint16_t rangeMax;
float scale;
p->colorTableNeedsUpdate_ = false;
gl::OpenGLFunctions& gl = p->gl_;
const std::vector<boost::gil::rgba8_pixel_t>& colorTable =
p->radarProductView_->color_table(rangeMin, rangeMax);
p->radarProductView_->color_table();
const uint16_t rangeMin = p->radarProductView_->color_table_min();
const uint16_t rangeMax = p->radarProductView_->color_table_max();
scale = rangeMax - rangeMin;
const float scale = rangeMax - rangeMin;
gl.glActiveTexture(GL_TEXTURE0);
gl.glBindTexture(GL_TEXTURE_1D, p->texture_);

View file

@ -122,20 +122,42 @@ Level2ProductView::Level2ProductView(
Level2ProductView::~Level2ProductView() = default;
const std::vector<boost::gil::rgba8_pixel_t>&
Level2ProductView::color_table(uint16_t& minValue, uint16_t& maxValue) const
Level2ProductView::color_table() const
{
if (p->colorTableLut_.size() == 0)
{
return RadarProductView::color_table(minValue, maxValue);
return RadarProductView::color_table();
}
else
{
minValue = p->colorTableMin_;
maxValue = p->colorTableMax_;
return p->colorTableLut_;
}
}
uint16_t Level2ProductView::color_table_min() const
{
if (p->colorTableLut_.size() == 0)
{
return RadarProductView::color_table_min();
}
else
{
return p->colorTableMin_;
}
}
uint16_t Level2ProductView::color_table_max() const
{
if (p->colorTableLut_.size() == 0)
{
return RadarProductView::color_table_max();
}
else
{
return p->colorTableMax_;
}
}
float Level2ProductView::elevation() const
{
return p->elevationCut_;
@ -306,7 +328,6 @@ void Level2ProductView::ComputeSweep()
return;
}
float elevation;
std::shared_ptr<wsr88d::rda::ElevationScan> radarData;
std::tie(radarData, p->elevationCut_, p->elevationCuts_) =
p->radarProductManager_->GetLevel2Data(p->dataBlockType_,

View file

@ -29,10 +29,11 @@ public:
std::shared_ptr<manager::RadarProductManager> radarProductManager);
~Level2ProductView();
const std::vector<boost::gil::rgba8_pixel_t>&
color_table(uint16_t& minValue, uint16_t& maxValue) const override;
float elevation() const override;
float range() const override;
const std::vector<boost::gil::rgba8_pixel_t>& color_table() const override;
uint16_t color_table_min() const override;
uint16_t color_table_max() const override;
float elevation() const override;
float range() const override;
std::chrono::system_clock::time_point sweep_time() const override;
const std::vector<float>& vertices() const override;

View file

@ -33,13 +33,21 @@ RadarProductView::RadarProductView() :
RadarProductView::~RadarProductView() = default;
const std::vector<boost::gil::rgba8_pixel_t>&
RadarProductView::color_table(uint16_t& minValue, uint16_t& maxValue) const
RadarProductView::color_table() const
{
minValue = DEFAULT_COLOR_TABLE_MIN;
maxValue = DEFAULT_COLOR_TABLE_MAX;
return DEFAULT_COLOR_TABLE;
}
uint16_t RadarProductView::color_table_min() const
{
return DEFAULT_COLOR_TABLE_MIN;
}
uint16_t RadarProductView::color_table_max() const
{
return DEFAULT_COLOR_TABLE_MAX;
}
float RadarProductView::elevation() const
{
return 0.0f;

View file

@ -25,10 +25,11 @@ public:
explicit RadarProductView();
~RadarProductView();
virtual const std::vector<boost::gil::rgba8_pixel_t>&
color_table(uint16_t& minValue, uint16_t& maxValue) const;
virtual float elevation() const;
virtual float range() const;
virtual const std::vector<boost::gil::rgba8_pixel_t>& color_table() const;
virtual uint16_t color_table_min() const;
virtual uint16_t color_table_max() const;
virtual float elevation() const;
virtual float range() const;
virtual std::chrono::system_clock::time_point sweep_time() const;
virtual const std::vector<float>& vertices() const = 0;