Creating OpenGL utility class, consolidating number of OpenGL function objects

This commit is contained in:
Dan Paulat 2021-07-23 21:30:51 -05:00
parent c6a323247d
commit 59be110c10
10 changed files with 124 additions and 73 deletions

View file

@ -59,7 +59,8 @@ set(SRC_MAP source/scwx/qt/map/map_widget.cpp
source/scwx/qt/map/radar_layer.cpp source/scwx/qt/map/radar_layer.cpp
source/scwx/qt/map/radar_range_layer.cpp source/scwx/qt/map/radar_range_layer.cpp
source/scwx/qt/map/triangle_layer.cpp) source/scwx/qt/map/triangle_layer.cpp)
set(HDR_UTIL source/scwx/qt/util/shader_program.hpp) set(HDR_UTIL source/scwx/qt/util/gl.hpp
source/scwx/qt/util/shader_program.hpp)
set(SRC_UTIL source/scwx/qt/util/shader_program.cpp) set(SRC_UTIL source/scwx/qt/util/shader_program.cpp)
set(RESOURCE_FILES scwx-qt.qrc) set(RESOURCE_FILES scwx-qt.qrc)

View file

@ -2,6 +2,7 @@
#include <scwx/qt/map/radar_layer.hpp> #include <scwx/qt/map/radar_layer.hpp>
#include <scwx/qt/map/radar_range_layer.hpp> #include <scwx/qt/map/radar_range_layer.hpp>
#include <scwx/qt/util/gl.hpp>
#include <QApplication> #include <QApplication>
#include <QColor> #include <QColor>
@ -31,7 +32,27 @@ static const MapStyle satelliteStreets { "mapbox://styles/mapbox/satellite-stree
static const std::array<MapStyle, 6> mapboxStyles_ = { static const std::array<MapStyle, 6> mapboxStyles_ = {
{streets, outdoors, light, dark, satellite, satelliteStreets}}; {streets, outdoors, light, dark, satellite, satelliteStreets}};
MapWidget::MapWidget(const QMapboxGLSettings& settings) : settings_(settings) class MapWidgetImpl
{
public:
explicit MapWidgetImpl(const QMapboxGLSettings& settings) :
gl_(), settings_(settings), map_(), lastPos_(), frameDraws_(0)
{
}
~MapWidgetImpl() = default;
OpenGLFunctions gl_;
QMapboxGLSettings settings_;
std::shared_ptr<QMapboxGL> map_;
QPointF lastPos_;
uint64_t frameDraws_;
};
MapWidget::MapWidget(const QMapboxGLSettings& settings) :
p(std::make_unique<MapWidgetImpl>(settings))
{ {
setFocusPolicy(Qt::StrongFocus); setFocusPolicy(Qt::StrongFocus);
} }
@ -54,7 +75,7 @@ void MapWidget::changeStyle()
auto& styles = mapboxStyles_; auto& styles = mapboxStyles_;
map_->setStyleUrl(styles[currentStyleIndex].first.c_str()); p->map_->setStyleUrl(styles[currentStyleIndex].first.c_str());
setWindowTitle(QString("Mapbox GL: ") + setWindowTitle(QString("Mapbox GL: ") +
styles[currentStyleIndex].second.c_str()); styles[currentStyleIndex].second.c_str());
@ -68,11 +89,11 @@ void MapWidget::AddLayers()
{ {
// 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(map_)); new RadarLayer(p->map_, p->gl_));
QString before = "ferry"; QString before = "ferry";
for (const QString& layer : map_->layerIds()) for (const QString& layer : p->map_->layerIds())
{ {
// Draw below tunnels, ferries and roads // Draw below tunnels, ferries and roads
if (layer.startsWith("tunnel") || layer.startsWith("ferry") || if (layer.startsWith("tunnel") || layer.startsWith("ferry") ||
@ -83,8 +104,8 @@ void MapWidget::AddLayers()
} }
} }
map_->addCustomLayer("radar", pHost, before); p->map_->addCustomLayer("radar", pHost, before);
RadarRangeLayer::Add(map_, before); RadarRangeLayer::Add(p->map_, before);
} }
void MapWidget::keyPressEvent(QKeyEvent* ev) void MapWidget::keyPressEvent(QKeyEvent* ev)
@ -94,7 +115,7 @@ void MapWidget::keyPressEvent(QKeyEvent* ev)
case Qt::Key_S: changeStyle(); break; case Qt::Key_S: changeStyle(); break;
case Qt::Key_L: case Qt::Key_L:
{ {
for (const QString& layer : map_->layerIds()) for (const QString& layer : p->map_->layerIds())
{ {
qDebug() << "Layer: " << layer; qDebug() << "Layer: " << layer;
} }
@ -108,7 +129,7 @@ void MapWidget::keyPressEvent(QKeyEvent* ev)
void MapWidget::mousePressEvent(QMouseEvent* ev) void MapWidget::mousePressEvent(QMouseEvent* ev)
{ {
lastPos_ = ev->position(); p->lastPos_ = ev->position();
if (ev->type() == QEvent::MouseButtonPress) if (ev->type() == QEvent::MouseButtonPress)
{ {
@ -122,11 +143,11 @@ void MapWidget::mousePressEvent(QMouseEvent* ev)
{ {
if (ev->buttons() == Qt::LeftButton) if (ev->buttons() == Qt::LeftButton)
{ {
map_->scaleBy(2.0, lastPos_); p->map_->scaleBy(2.0, p->lastPos_);
} }
else if (ev->buttons() == Qt::RightButton) else if (ev->buttons() == Qt::RightButton)
{ {
map_->scaleBy(0.5, lastPos_); p->map_->scaleBy(0.5, p->lastPos_);
} }
} }
@ -135,26 +156,26 @@ void MapWidget::mousePressEvent(QMouseEvent* ev)
void MapWidget::mouseMoveEvent(QMouseEvent* ev) void MapWidget::mouseMoveEvent(QMouseEvent* ev)
{ {
QPointF delta = ev->position() - lastPos_; QPointF delta = ev->position() - p->lastPos_;
if (!delta.isNull()) if (!delta.isNull())
{ {
if (ev->buttons() == Qt::LeftButton && if (ev->buttons() == Qt::LeftButton &&
ev->modifiers() & Qt::ShiftModifier) ev->modifiers() & Qt::ShiftModifier)
{ {
map_->pitchBy(delta.y()); p->map_->pitchBy(delta.y());
} }
else if (ev->buttons() == Qt::LeftButton) else if (ev->buttons() == Qt::LeftButton)
{ {
map_->moveBy(delta); p->map_->moveBy(delta);
} }
else if (ev->buttons() == Qt::RightButton) else if (ev->buttons() == Qt::RightButton)
{ {
map_->rotateBy(lastPos_, ev->position()); p->map_->rotateBy(p->lastPos_, ev->position());
} }
} }
lastPos_ = ev->position(); p->lastPos_ = ev->position();
ev->accept(); ev->accept();
} }
@ -171,18 +192,21 @@ void MapWidget::wheelEvent(QWheelEvent* ev)
factor = factor > -1 ? factor : 1 / factor; factor = factor > -1 ? factor : 1 / factor;
} }
map_->scaleBy(1 + factor, ev->position()); p->map_->scaleBy(1 + factor, ev->position());
ev->accept(); ev->accept();
} }
void MapWidget::initializeGL() void MapWidget::initializeGL()
{ {
map_.reset(new QMapboxGL(nullptr, settings_, size(), pixelRatio())); makeCurrent();
connect(map_.get(), SIGNAL(needsRendering()), this, SLOT(update())); p->gl_.initializeOpenGLFunctions();
p->map_.reset(new QMapboxGL(nullptr, p->settings_, size(), pixelRatio()));
connect(p->map_.get(), SIGNAL(needsRendering()), this, SLOT(update()));
// Set default location to KLSX. // Set default location to KLSX.
map_->setCoordinateZoom(QMapbox::Coordinate(38.6986, -90.6828), 11); p->map_->setCoordinateZoom(QMapbox::Coordinate(38.6986, -90.6828), 11);
QString styleUrl = qgetenv("MAPBOX_STYLE_URL"); QString styleUrl = qgetenv("MAPBOX_STYLE_URL");
if (styleUrl.isEmpty()) if (styleUrl.isEmpty())
@ -191,20 +215,20 @@ void MapWidget::initializeGL()
} }
else else
{ {
map_->setStyleUrl(styleUrl); p->map_->setStyleUrl(styleUrl);
setWindowTitle(QString("Mapbox GL: ") + styleUrl); setWindowTitle(QString("Mapbox GL: ") + styleUrl);
} }
connect(map_.get(), &QMapboxGL::mapChanged, this, &MapWidget::mapChanged); connect(p->map_.get(), &QMapboxGL::mapChanged, this, &MapWidget::mapChanged);
} }
void MapWidget::paintGL() void MapWidget::paintGL()
{ {
frameDraws_++; p->frameDraws_++;
map_->resize(size()); p->map_->resize(size());
map_->setFramebufferObject(defaultFramebufferObject(), p->map_->setFramebufferObject(defaultFramebufferObject(),
size() * pixelRatio()); size() * pixelRatio());
map_->render(); p->map_->render();
} }
void MapWidget::mapChanged(QMapboxGL::MapChange mapChange) void MapWidget::mapChanged(QMapboxGL::MapChange mapChange)

View file

@ -17,12 +17,14 @@ namespace scwx
namespace qt namespace qt
{ {
class MapWidgetImpl;
class MapWidget : public QOpenGLWidget class MapWidget : public QOpenGLWidget
{ {
Q_OBJECT Q_OBJECT
public: public:
MapWidget(const QMapboxGLSettings&); explicit MapWidget(const QMapboxGLSettings&);
~MapWidget(); ~MapWidget();
private: private:
@ -41,12 +43,7 @@ private:
void AddLayers(); void AddLayers();
QPointF lastPos_; std::unique_ptr<MapWidgetImpl> p;
QMapboxGLSettings settings_;
std::shared_ptr<QMapboxGL> map_;
uint64_t frameDraws_ = 0;
private slots: private slots:
void mapChanged(QMapboxGL::MapChange); void mapChanged(QMapboxGL::MapChange);

View file

@ -3,8 +3,6 @@
#include <execution> #include <execution>
#include <QOpenGLFunctions_3_3_Core>
#include <boost/log/trivial.hpp> #include <boost/log/trivial.hpp>
#include <boost/range/irange.hpp> #include <boost/range/irange.hpp>
#include <boost/timer/timer.hpp> #include <boost/timer/timer.hpp>
@ -30,10 +28,11 @@ LatLongToScreenCoordinate(const QMapbox::Coordinate& coordinate);
class RadarLayerImpl class RadarLayerImpl
{ {
public: public:
explicit RadarLayerImpl(std::shared_ptr<QMapboxGL> map) : explicit RadarLayerImpl(std::shared_ptr<QMapboxGL> map,
OpenGLFunctions& gl) :
map_(map), map_(map),
gl_(), gl_(gl),
shaderProgram_(), shaderProgram_(gl),
uMVPMatrixLocation_(GL_INVALID_INDEX), uMVPMatrixLocation_(GL_INVALID_INDEX),
uMapScreenCoordLocation_(GL_INVALID_INDEX), uMapScreenCoordLocation_(GL_INVALID_INDEX),
vbo_ {GL_INVALID_INDEX}, vbo_ {GL_INVALID_INDEX},
@ -42,13 +41,12 @@ public:
bearing_ {0.0}, bearing_ {0.0},
numVertices_ {0} numVertices_ {0}
{ {
gl_.initializeOpenGLFunctions();
} }
~RadarLayerImpl() = default; ~RadarLayerImpl() = default;
std::shared_ptr<QMapboxGL> map_; std::shared_ptr<QMapboxGL> map_;
QOpenGLFunctions_3_3_Core gl_; OpenGLFunctions& gl_;
ShaderProgram shaderProgram_; ShaderProgram shaderProgram_;
GLint uMVPMatrixLocation_; GLint uMVPMatrixLocation_;
@ -62,8 +60,8 @@ public:
GLsizeiptr numVertices_; GLsizeiptr numVertices_;
}; };
RadarLayer::RadarLayer(std::shared_ptr<QMapboxGL> map) : RadarLayer::RadarLayer(std::shared_ptr<QMapboxGL> map, OpenGLFunctions& gl) :
p(std::make_unique<RadarLayerImpl>(map)) p(std::make_unique<RadarLayerImpl>(map, gl))
{ {
} }
RadarLayer::~RadarLayer() = default; RadarLayer::~RadarLayer() = default;
@ -75,7 +73,7 @@ void RadarLayer::initialize()
{ {
BOOST_LOG_TRIVIAL(debug) << logPrefix_ << "initialize()"; BOOST_LOG_TRIVIAL(debug) << logPrefix_ << "initialize()";
QOpenGLFunctions_3_3_Core& gl = p->gl_; OpenGLFunctions& gl = p->gl_;
boost::timer::cpu_timer timer; boost::timer::cpu_timer timer;
@ -134,7 +132,7 @@ void RadarLayer::initialize()
}); });
timer.stop(); timer.stop();
BOOST_LOG_TRIVIAL(debug) BOOST_LOG_TRIVIAL(debug)
<< "Coordinates calculated in " << timer.format(6, "%ws"); << logPrefix_ << "Coordinates calculated in " << timer.format(6, "%ws");
// Calculate vertices // Calculate vertices
static std::array<GLfloat, MAX_RADIALS * MAX_DATA_MOMENT_GATES * 6 * 2> static std::array<GLfloat, MAX_RADIALS * MAX_DATA_MOMENT_GATES * 6 * 2>
@ -185,7 +183,7 @@ void RadarLayer::initialize()
} }
timer.stop(); timer.stop();
BOOST_LOG_TRIVIAL(debug) BOOST_LOG_TRIVIAL(debug)
<< "Vertices calculated in " << timer.format(6, "%ws"); << logPrefix_ << "Vertices calculated in " << timer.format(6, "%ws");
// Generate a vertex buffer object // Generate a vertex buffer object
gl.glGenBuffers(1, &p->vbo_); gl.glGenBuffers(1, &p->vbo_);
@ -205,7 +203,7 @@ void RadarLayer::initialize()
GL_STATIC_DRAW); GL_STATIC_DRAW);
timer.stop(); timer.stop();
BOOST_LOG_TRIVIAL(debug) BOOST_LOG_TRIVIAL(debug)
<< "Vertices buffered in " << timer.format(6, "%ws"); << logPrefix_ << "Vertices buffered in " << timer.format(6, "%ws");
// Set the vertex attributes pointers // Set the vertex attributes pointers
gl.glVertexAttribPointer( gl.glVertexAttribPointer(
@ -218,7 +216,7 @@ void RadarLayer::initialize()
void RadarLayer::render(const QMapbox::CustomLayerRenderParameters& params) void RadarLayer::render(const QMapbox::CustomLayerRenderParameters& params)
{ {
QOpenGLFunctions_3_3_Core& gl = p->gl_; OpenGLFunctions& gl = p->gl_;
p->shaderProgram_.Use(); p->shaderProgram_.Use();
@ -249,7 +247,7 @@ void RadarLayer::render(const QMapbox::CustomLayerRenderParameters& params)
void RadarLayer::deinitialize() void RadarLayer::deinitialize()
{ {
QOpenGLFunctions_3_3_Core& gl = p->gl_; OpenGLFunctions& gl = p->gl_;
BOOST_LOG_TRIVIAL(debug) << logPrefix_ << "deinitialize()"; BOOST_LOG_TRIVIAL(debug) << logPrefix_ << "deinitialize()";

View file

@ -1,5 +1,7 @@
#pragma once #pragma once
#include <scwx/qt/util/gl.hpp>
#include <QMapboxGL> #include <QMapboxGL>
namespace scwx namespace scwx
@ -12,7 +14,7 @@ class RadarLayerImpl;
class RadarLayer : public QMapbox::CustomLayerHostInterface class RadarLayer : public QMapbox::CustomLayerHostInterface
{ {
public: public:
explicit RadarLayer(std::shared_ptr<QMapboxGL> map); explicit RadarLayer(std::shared_ptr<QMapboxGL> map, OpenGLFunctions& gl);
~RadarLayer(); ~RadarLayer();
RadarLayer(const RadarLayer&) = delete; RadarLayer(const RadarLayer&) = delete;

View file

@ -1,7 +1,5 @@
#include <scwx/qt/map/triangle_layer.hpp> #include <scwx/qt/map/triangle_layer.hpp>
#include <QOpenGLFunctions_3_3_Core>
#include <boost/log/trivial.hpp> #include <boost/log/trivial.hpp>
namespace scwx namespace scwx
@ -9,13 +7,13 @@ namespace scwx
namespace qt namespace qt
{ {
static const std::string logPrefix_ = "[scwx::map::triangle_layer] "; static const std::string logPrefix_ = "[scwx::qt::map::triangle_layer] ";
class TriangleLayerImpl class TriangleLayerImpl
{ {
public: public:
explicit TriangleLayerImpl() : explicit TriangleLayerImpl(OpenGLFunctions& gl) :
gl_(), gl_(gl),
shaderProgram_ {GL_INVALID_INDEX}, shaderProgram_ {GL_INVALID_INDEX},
vbo_ {GL_INVALID_INDEX}, vbo_ {GL_INVALID_INDEX},
vao_ {GL_INVALID_INDEX} vao_ {GL_INVALID_INDEX}
@ -24,14 +22,17 @@ public:
} }
~TriangleLayerImpl() = default; ~TriangleLayerImpl() = default;
QOpenGLFunctions_3_3_Core gl_; OpenGLFunctions& gl_;
GLuint shaderProgram_; GLuint shaderProgram_;
GLuint vbo_; GLuint vbo_;
GLuint vao_; GLuint vao_;
}; };
TriangleLayer::TriangleLayer() : p(std::make_unique<TriangleLayerImpl>()) {} TriangleLayer::TriangleLayer(OpenGLFunctions& gl) :
p(std::make_unique<TriangleLayerImpl>(gl))
{
}
TriangleLayer::~TriangleLayer() = default; TriangleLayer::~TriangleLayer() = default;
TriangleLayer::TriangleLayer(TriangleLayer&&) noexcept = default; TriangleLayer::TriangleLayer(TriangleLayer&&) noexcept = default;
@ -39,7 +40,7 @@ TriangleLayer& TriangleLayer::operator=(TriangleLayer&&) noexcept = default;
void TriangleLayer::initialize() void TriangleLayer::initialize()
{ {
QOpenGLFunctions_3_3_Core& gl = p->gl_; OpenGLFunctions& gl = p->gl_;
static const char* vertexShaderSource = static const char* vertexShaderSource =
"#version 330 core\n" "#version 330 core\n"
@ -141,7 +142,7 @@ void TriangleLayer::initialize()
void TriangleLayer::render(const QMapbox::CustomLayerRenderParameters&) void TriangleLayer::render(const QMapbox::CustomLayerRenderParameters&)
{ {
QOpenGLFunctions_3_3_Core& gl = p->gl_; OpenGLFunctions& gl = p->gl_;
gl.glUseProgram(p->shaderProgram_); gl.glUseProgram(p->shaderProgram_);
gl.glBindVertexArray(p->vao_); gl.glBindVertexArray(p->vao_);
@ -150,7 +151,7 @@ void TriangleLayer::render(const QMapbox::CustomLayerRenderParameters&)
void TriangleLayer::deinitialize() void TriangleLayer::deinitialize()
{ {
QOpenGLFunctions_3_3_Core& gl = p->gl_; OpenGLFunctions& gl = p->gl_;
BOOST_LOG_TRIVIAL(debug) << logPrefix_ << "deinitialize()"; BOOST_LOG_TRIVIAL(debug) << logPrefix_ << "deinitialize()";

View file

@ -1,4 +1,8 @@
#include <qmapboxgl.hpp> #pragma once
#include <scwx/qt/util/gl.hpp>
#include <QMapboxGL>
namespace scwx namespace scwx
{ {
@ -10,7 +14,7 @@ class TriangleLayerImpl;
class TriangleLayer : public QMapbox::CustomLayerHostInterface class TriangleLayer : public QMapbox::CustomLayerHostInterface
{ {
public: public:
explicit TriangleLayer(); explicit TriangleLayer(OpenGLFunctions& gl);
~TriangleLayer(); ~TriangleLayer();
TriangleLayer(const TriangleLayer&) = delete; TriangleLayer(const TriangleLayer&) = delete;

View file

@ -0,0 +1,23 @@
#pragma once
#include <QOpenGLFunctions_3_3_Core>
#define SCWX_GL_CHECK_ERROR() \
{ \
GLenum err; \
while ((err = p->gl_.glGetError()) != GL_NO_ERROR) \
{ \
BOOST_LOG_TRIVIAL(warning) << logPrefix_ << "GL Error: " << err \
<< ", " __FILE__ << ":" << __LINE__; \
} \
}
namespace scwx
{
namespace qt
{
using OpenGLFunctions = QOpenGLFunctions_3_3_Core;
} // namespace qt
} // namespace scwx

View file

@ -1,7 +1,6 @@
#include <scwx/qt/util/shader_program.hpp> #include <scwx/qt/util/shader_program.hpp>
#include <QFile> #include <QFile>
#include <QOpenGLFunctions_3_3_Core>
#include <boost/log/trivial.hpp> #include <boost/log/trivial.hpp>
@ -15,10 +14,9 @@ static const std::string logPrefix_ = "[scwx::qt::util::shader_program] ";
class ShaderProgramImpl class ShaderProgramImpl
{ {
public: public:
explicit ShaderProgramImpl() : gl_(), id_ {GL_INVALID_INDEX} explicit ShaderProgramImpl(OpenGLFunctions& gl) :
gl_(gl), id_ {GL_INVALID_INDEX}
{ {
gl_.initializeOpenGLFunctions();
// Create shader program // Create shader program
id_ = gl_.glCreateProgram(); id_ = gl_.glCreateProgram();
} }
@ -29,12 +27,15 @@ public:
gl_.glDeleteProgram(id_); gl_.glDeleteProgram(id_);
} }
QOpenGLFunctions_3_3_Core gl_; OpenGLFunctions& gl_;
GLuint id_; GLuint id_;
}; };
ShaderProgram::ShaderProgram() : p(std::make_unique<ShaderProgramImpl>()) {} ShaderProgram::ShaderProgram(OpenGLFunctions& gl) :
p(std::make_unique<ShaderProgramImpl>(gl))
{
}
ShaderProgram::~ShaderProgram() = default; ShaderProgram::~ShaderProgram() = default;
ShaderProgram::ShaderProgram(ShaderProgram&&) noexcept = default; ShaderProgram::ShaderProgram(ShaderProgram&&) noexcept = default;
@ -50,7 +51,7 @@ bool ShaderProgram::Load(const std::string& vertexPath,
{ {
BOOST_LOG_TRIVIAL(debug) << logPrefix_ << "Load()"; BOOST_LOG_TRIVIAL(debug) << logPrefix_ << "Load()";
QOpenGLFunctions_3_3_Core& gl = p->gl_; OpenGLFunctions& gl = p->gl_;
GLint glSuccess; GLint glSuccess;
bool success = true; bool success = true;

View file

@ -1,14 +1,14 @@
#pragma once #pragma once
#include <scwx/qt/util/gl.hpp>
#ifdef _WIN32 #ifdef _WIN32
#include <Windows.h> # include <Windows.h>
#endif #endif
#include <memory> #include <memory>
#include <string> #include <string>
#include <GL/gl.h>
namespace scwx namespace scwx
{ {
namespace qt namespace qt
@ -19,7 +19,7 @@ class ShaderProgramImpl;
class ShaderProgram class ShaderProgram
{ {
public: public:
explicit ShaderProgram(); explicit ShaderProgram(OpenGLFunctions& gl);
~ShaderProgram(); ~ShaderProgram();
ShaderProgram(const ShaderProgram&) = delete; ShaderProgram(const ShaderProgram&) = delete;