Color radar image using a color table

This commit is contained in:
Dan Paulat 2021-07-29 21:59:21 -05:00
parent f004c7aee0
commit c06230ed6c
6 changed files with 81 additions and 14 deletions

View file

@ -3,7 +3,7 @@
// Lower the default precision to medium // Lower the default precision to medium
precision mediump float; precision mediump float;
uniform sampler2D uTexture; uniform sampler1D uTexture;
flat in uint dataMoment; flat in uint dataMoment;
@ -11,16 +11,7 @@ layout (location = 0) out vec4 fragColor;
void main() void main()
{ {
if (dataMoment < 126u) float texCoord = float(dataMoment - 2u) / 253.0f; // TODO: Scale properly
{
fragColor = vec4(0.0f, 0.5f, 0.0f, 0.9f); fragColor = texture(uTexture, texCoord);
}
else if (dataMoment < 156u)
{
fragColor = vec4(1.0f, 0.75f, 0.0f, 0.9f);
}
else
{
fragColor = vec4(1.0f, 0.0f, 0.0f, 0.9f);
}
} }

View file

@ -106,6 +106,14 @@ void MapWidget::AddLayers()
radarView->Initialize(); radarView->Initialize();
QString colorTableFile = qgetenv("COLOR_TABLE");
if (!colorTableFile.isEmpty())
{
std::shared_ptr<common::ColorTable> colorTable =
common::ColorTable::Load(colorTableFile.toUtf8().constData());
radarView->LoadColorTable(colorTable);
}
// QMapboxGL::addCustomLayer will take ownership of the QScopedPointer // QMapboxGL::addCustomLayer will take ownership of the QScopedPointer
QScopedPointer<QMapbox::CustomLayerHostInterface> pHost( QScopedPointer<QMapbox::CustomLayerHostInterface> pHost(
new RadarLayer(radarView, p->gl_)); new RadarLayer(radarView, p->gl_));

View file

@ -36,6 +36,7 @@ public:
uMapScreenCoordLocation_(GL_INVALID_INDEX), uMapScreenCoordLocation_(GL_INVALID_INDEX),
vbo_ {GL_INVALID_INDEX}, vbo_ {GL_INVALID_INDEX},
vao_ {GL_INVALID_INDEX}, vao_ {GL_INVALID_INDEX},
texture_ {GL_INVALID_INDEX},
numVertices_ {0} numVertices_ {0}
{ {
} }
@ -49,6 +50,7 @@ public:
GLint uMapScreenCoordLocation_; GLint uMapScreenCoordLocation_;
std::array<GLuint, 2> vbo_; std::array<GLuint, 2> vbo_;
GLuint vao_; GLuint vao_;
GLuint texture_;
GLsizeiptr numVertices_; GLsizeiptr numVertices_;
}; };
@ -143,6 +145,11 @@ void RadarLayer::initialize()
gl.glEnableVertexAttribArray(1); gl.glEnableVertexAttribArray(1);
p->numVertices_ = vertices.size() / 2; p->numVertices_ = vertices.size() / 2;
// Create color table
gl.glGenTextures(1, &p->texture_);
UpdateColorTable();
gl.glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
} }
void RadarLayer::render(const QMapbox::CustomLayerRenderParameters& params) void RadarLayer::render(const QMapbox::CustomLayerRenderParameters& params)
@ -170,6 +177,8 @@ void RadarLayer::render(const QMapbox::CustomLayerRenderParameters& params)
gl.glUniformMatrix4fv( gl.glUniformMatrix4fv(
p->uMVPMatrixLocation_, 1, GL_FALSE, glm::value_ptr(uMVPMatrix)); p->uMVPMatrixLocation_, 1, GL_FALSE, glm::value_ptr(uMVPMatrix));
gl.glActiveTexture(GL_TEXTURE0);
gl.glBindTexture(GL_TEXTURE_1D, p->texture_);
gl.glBindVertexArray(p->vao_); gl.glBindVertexArray(p->vao_);
gl.glDrawArrays(GL_TRIANGLES, 0, p->numVertices_); gl.glDrawArrays(GL_TRIANGLES, 0, p->numVertices_);
} }
@ -186,6 +195,27 @@ void RadarLayer::deinitialize()
p->uMVPMatrixLocation_ = GL_INVALID_INDEX; p->uMVPMatrixLocation_ = GL_INVALID_INDEX;
p->vao_ = GL_INVALID_INDEX; p->vao_ = GL_INVALID_INDEX;
p->vbo_ = {GL_INVALID_INDEX}; p->vbo_ = {GL_INVALID_INDEX};
p->texture_ = GL_INVALID_INDEX;
}
void RadarLayer::UpdateColorTable()
{
OpenGLFunctions& gl = p->gl_;
const std::vector<boost::gil::rgba8_pixel_t>& colorTable =
p->radarView_->color_table();
gl.glActiveTexture(GL_TEXTURE0);
gl.glBindTexture(GL_TEXTURE_1D, p->texture_);
gl.glTexImage1D(GL_TEXTURE_1D,
0,
GL_RGBA,
(GLsizei) colorTable.size(),
0,
GL_RGBA,
GL_UNSIGNED_BYTE,
colorTable.data());
gl.glGenerateMipmap(GL_TEXTURE_1D);
} }
static glm::vec2 static glm::vec2

View file

@ -28,6 +28,8 @@ public:
void render(const QMapbox::CustomLayerRenderParameters&) override final; void render(const QMapbox::CustomLayerRenderParameters&) override final;
void deinitialize() override final; void deinitialize() override final;
void UpdateColorTable();
private: private:
std::unique_ptr<RadarLayerImpl> p; std::unique_ptr<RadarLayerImpl> p;
}; };

View file

@ -2,6 +2,7 @@
#include <scwx/common/constants.hpp> #include <scwx/common/constants.hpp>
#include <boost/log/trivial.hpp> #include <boost/log/trivial.hpp>
#include <boost/range/irange.hpp>
#include <boost/timer/timer.hpp> #include <boost/timer/timer.hpp>
namespace scwx namespace scwx
@ -21,7 +22,11 @@ class RadarViewImpl
public: public:
explicit RadarViewImpl(std::shared_ptr<manager::RadarManager> radarManager, explicit RadarViewImpl(std::shared_ptr<manager::RadarManager> radarManager,
std::shared_ptr<QMapboxGL> map) : std::shared_ptr<QMapboxGL> map) :
radarManager_(radarManager), map_(map) radarManager_(radarManager),
map_(map),
colorTable_ {boost::gil::rgba8_pixel_t(0, 128, 0, 255),
boost::gil::rgba8_pixel_t(255, 192, 0, 255),
boost::gil::rgba8_pixel_t(255, 0, 0, 255)}
{ {
} }
~RadarViewImpl() = default; ~RadarViewImpl() = default;
@ -32,6 +37,8 @@ public:
std::vector<float> vertices_; std::vector<float> vertices_;
std::vector<uint8_t> dataMoments8_; std::vector<uint8_t> dataMoments8_;
std::vector<uint16_t> dataMoments16_; std::vector<uint16_t> dataMoments16_;
std::vector<boost::gil::rgba8_pixel_t> colorTable_;
}; };
RadarView::RadarView(std::shared_ptr<manager::RadarManager> radarManager, RadarView::RadarView(std::shared_ptr<manager::RadarManager> radarManager,
@ -69,6 +76,11 @@ const std::vector<float>& RadarView::vertices() const
return p->vertices_; return p->vertices_;
} }
const std::vector<boost::gil::rgba8_pixel_t>& RadarView::color_table() const
{
return p->colorTable_;
}
void RadarView::Initialize() void RadarView::Initialize()
{ {
BOOST_LOG_TRIVIAL(debug) << logPrefix_ << "Initialize()"; BOOST_LOG_TRIVIAL(debug) << logPrefix_ << "Initialize()";
@ -297,6 +309,26 @@ void RadarView::Initialize()
<< logPrefix_ << "Vertices calculated in " << timer.format(6, "%ws"); << logPrefix_ << "Vertices calculated in " << timer.format(6, "%ws");
} }
void RadarView::LoadColorTable(std::shared_ptr<common::ColorTable> colorTable)
{
// TODO: Make size, offset and scale dynamic
const float offset = 66.0f;
const float scale = 2.0f;
std::vector<boost::gil::rgba8_pixel_t>& lut = p->colorTable_;
lut.resize(254);
auto dataRange = boost::irange<uint16_t>(2, 255);
std::for_each(std::execution::par_unseq,
dataRange.begin(),
dataRange.end(),
[&](uint16_t i) {
float f = (i - offset) / scale;
lut[i - *dataRange.begin()] = colorTable->Color(f);
});
}
} // namespace view } // namespace view
} // namespace qt } // namespace qt
} // namespace scwx } // namespace scwx

View file

@ -1,5 +1,6 @@
#pragma once #pragma once
#include <scwx/common/color_table.hpp>
#include <scwx/qt/manager/radar_manager.hpp> #include <scwx/qt/manager/radar_manager.hpp>
#include <memory> #include <memory>
@ -35,7 +36,10 @@ public:
const std::vector<uint16_t>& data_moments16() const; const std::vector<uint16_t>& data_moments16() const;
const std::vector<float>& vertices() const; const std::vector<float>& vertices() const;
const std::vector<boost::gil::rgba8_pixel_t>& color_table() const;
void Initialize(); void Initialize();
void LoadColorTable(std::shared_ptr<common::ColorTable> colorTable);
private: private:
std::unique_ptr<RadarViewImpl> p; std::unique_ptr<RadarViewImpl> p;