A GPU-accelerated 2D time-series plotting library using Qt RHI and Qt Quick.
function_plotter example
vnm_plot renders time-series data through Qt RHI. It supports Level-of-Detail (LOD) for handling large datasets. The renderer automatically selects an appropriate resolution based on the current zoom level.
The library uses a type-erased data interface (vnm::plot::Data_source + vnm::plot::Data_access_policy) so it can work with any sample type without templates in the rendering code.
Data sources decide whether snapshots are copies or direct views; buffering, if needed, lives in the data source.
Public headers: #include <vnm_plot/vnm_plot.h> (umbrella),
#include <vnm_plot/core.h> (data/layout API), #include <vnm_plot/rhi.h>
(QRhi renderer and custom-layer API), and #include <vnm_plot/qt.h> (Qt Quick
API when built with Qt, VNM_PLOT_WITH_QT).
vnm_plot_data
-> Data_source, snapshots, access policies, time units, query APIs
vnm_plot_layout
-> Layout_calculator, range/window planning, formatting helpers
-> vnm_plot_data
vnm_plot_rhi
-> Asset_loader, Chrome_renderer, Series_renderer, Text_renderer, Font_renderer
-> custom QRhi series layers
-> vnm_plot_layout
vnm_plot_qtquick
-> Plot_widget (QQuickRhiItem), Plot_time_axis, interactions, QML resources
-> vnm_plot_rhi
vnm_plot_dataandvnm_plot_layoutare Qt-private-free in their link interfacesvnm_plot_rhiowns built-in QRhi renderers, shader resources, font/text rendering, asset loading, and the custom QRhi series-layer APIvnm_plot_qtquickis the Qt Quick wrapper (QML-friendly Plot_widget)Plot_rendererruns on the Qt RHI render thread and coordinates the sub-renderersSeries_rendererhandles lines, dots, and area fills with VBO managementChrome_rendererdraws the grid and axesFont_renderergenerates MSDF glyph atlases from FreeType
#include <vnm_plot/vnm_plot.h>
struct sample_t
{
std::int64_t t_ns;
float value;
};
std::vector<sample_t> samples;
samples.push_back({0, 0.0f});
samples.push_back({1'000'000'000, 1.0f});
auto source = std::make_shared<vnm::plot::Vector_data_source<sample_t>>();
source->set_data(std::move(samples));
auto access = vnm::plot::make_access_policy<sample_t>(
&sample_t::t_ns,
&sample_t::value);
auto series = vnm::plot::Series_builder()
.style(vnm::plot::Display_style::LINE)
.color(vnm::plot::rgba_u8(51, 153, 255))
.data_source(source)
.access(access)
.build_shared();
plot_widget->add_series(0, series);Thread Safety
Plot_widget renders on a separate RHI render thread. Treat series_data_t as immutable once added. To change series config (style, access policy, preview config, color), update a copy and call add_series again with the same id to replace it. Make sure your Data_source implementation is safe to read from the render thread.
Register the type in C++:
#include <vnm_plot/vnm_plot.h>
qmlRegisterType<vnm::plot::Plot_widget>("VnmPlot", 1, 0, "PlotWidget");
qmlRegisterType<vnm::plot::Plot_time_axis>("VnmPlot", 1, 0, "PlotTimeAxis");Use it in QML:
import VnmPlot 1.0
PlotWidget {
id: plot
anchors.fill: parent
}Shared time axis across plots:
import VnmPlot 1.0
PlotTimeAxis { id: sharedAxis }
Column {
PlotView { time_axis: sharedAxis }
PlotView { time_axis: sharedAxis }
}Implement a vnm::plot::Data_access_policy to tell the renderer how to read your samples:
struct my_sample_t
{
double timestamp;
float value;
float low;
float high;
};
auto policy = vnm::plot::make_access_policy<my_sample_t>(
&my_sample_t::timestamp,
&my_sample_t::value,
&my_sample_t::low,
&my_sample_t::high);
// Assign policy to a series
auto series = std::make_shared<vnm::plot::series_data_t>();
series->access = policy.erase();DOTS- pointsLINE- connected lineAREA- filled areaCOLORMAP_AREA- area colored by auxiliary metric- Combinations:
DOTS_LINE,LINE_AREA,DOTS_LINE_AREA
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
cmake --build buildQt 6 (Core, Gui, Quick, GuiPrivate, ShaderTools) is required. The build fetches
glm when it is not already available. Text rendering uses vnm_msdf_text; CMake
uses a sibling ../vnm_msdf_text checkout when present, otherwise it fetches the
GitHub master branch. vnm_msdf_text fetches FreeType and msdfgen when they
are not already available as targets.
CI currently builds QRhi and QRhi+Text on Linux, macOS, Windows, and FreeBSD.
The GitHub Actions jobs use the Qt 6.10.1 SDK on Linux, macOS, and Windows so
the QRhi private headers and qsb shader compiler are available consistently.
To disable text rendering (skips vnm_msdf_text, FreeType, and msdfgen):
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release -DVNM_PLOT_ENABLE_TEXT=OFF
cmake --build buildEnable examples with:
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release -DVNM_PLOT_BUILD_EXAMPLES=ON
cmake --build buildvnm_plot_hello- renders a sine wave using the example function-source helpervnm_plot_preview_config- preview uses a separate data source and AREA style viapreview_configfunction_plotter- multiple functions, per-series styles, expression evaluation via mexce
function_plotter depends on mexce. You can point at a local checkout by
configuring with -DMEXCE_LOCAL_PATH=....
Customize rendering via Plot_config:
vnm::plot::Plot_config config;
config.dark_mode = true;
config.line_width_px = 2.0;
config.auto_v_range_mode = vnm::plot::Auto_v_range_mode::VISIBLE;
config.format_timestamp = [](double ts, double range) {
return my_format_time(ts, range);
};
plot_widget->set_config(config);As a subdirectory:
add_subdirectory(vnm_plot)
target_link_libraries(your_app PRIVATE vnm_plot::qtquick)Via FetchContent:
include(FetchContent)
FetchContent_Declare(vnm_plot
GIT_REPOSITORY https://github.com/imakris/vnm_plot.git
GIT_TAG master
)
FetchContent_MakeAvailable(vnm_plot)
target_link_libraries(your_app PRIVATE vnm_plot::qtquick)For non-Qt consumers, link the narrow target needed by the code:
target_link_libraries(data_tool PRIVATE vnm_plot::data)
target_link_libraries(layout_tool PRIVATE vnm_plot::layout)
target_link_libraries(rhi_tool PRIVATE vnm_plot::rhi)This source tree declares CMake project version 0.1.0. Use master for this
source line, or replace it with a chosen release tag or commit when your
application needs a frozen revision.
Install exports are find_package-ready only when exported dependencies are
already imported package targets. Configure with -DVNM_PLOT_USE_SYSTEM_LIBS=ON
and provide find_package-able glm and, when text rendering is enabled,
vnm_msdf_text. When those dependencies are built locally through
FetchContent, install still installs headers and libraries, but skips the CMake
package export because CMake cannot export those local dependency targets from
this project.
Installed package targets are vnm_plot::data, vnm_plot::layout,
vnm_plot::rhi, and vnm_plot::qtquick. Requesting the data or layout
components does not require Qt private modules. Requesting rhi or qtquick
requires Qt GuiPrivate because those targets use QRhi. Qt ShaderTools is
required only when building vnm_plot from source.
- Qt 6.7+ with Qt Shader Tools
BSD-2-Clause