Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
d49c185
Enables the wireframe mode, per-model
sebsjames Dec 11, 2025
b134b33
Skeleton.
sebsjames Dec 11, 2025
0c644e6
Refactors ssbo.h to ssbo_nomx.h
sebsjames Dec 12, 2025
a89059b
Forgot to change this in last commit
sebsjames Dec 12, 2025
10c74c3
Adds an MX version of ssbo
sebsjames Dec 12, 2025
a8f36d8
Removes some functions that pre-date the ssbo struct
sebsjames Dec 12, 2025
d395116
Basic instanced rendering
sebsjames Dec 12, 2025
e22ec85
Got the write-and-rewrite to SSBO to work. Now need to go back and se…
sebsjames Dec 15, 2025
ec70c99
Yes, we can use a vec inside an ssbo
sebsjames Dec 15, 2025
412683d
Think this sorts SSBOs
sebsjames Dec 15, 2025
1c02619
Adds the forgotten vertex shader changes
sebsjames Dec 15, 2025
55d0623
Attempted to get the update to avoid a requirement to copy all the data
sebsjames Dec 15, 2025
349aff1
Minor changes
sebsjames Dec 15, 2025
403e07d
Comment (confession)
sebsjames Dec 15, 2025
59d48c5
Makes scene_to_visualmodels OpenGL-versionable
sebsjames Dec 15, 2025
c413b4f
More robustness
sebsjames Dec 16, 2025
2fca400
Adds the necessary GLSL for breadcrumbs and scatter_instanced
sebsjames Dec 16, 2025
16bb73d
Moves some attributes back a level
sebsjames Dec 16, 2025
90fc9f8
Default for InstancedScatterVisual should be 4.3
sebsjames Dec 16, 2025
d38c606
Fix to allow both instanced and non-instanced models in one scene
sebsjames Dec 16, 2025
be8558c
Oops, make that last dim a 0
sebsjames Dec 16, 2025
2c696f6
Gold default colour
sebsjames Dec 16, 2025
f2a1aae
Next thing to fix
sebsjames Dec 16, 2025
8aba98a
Switches ssbo to use vvec instead of vec as data store.
sebsjames Dec 16, 2025
50c0626
Was a skeleton, but haven't used it
sebsjames Dec 16, 2025
bf285c1
Install InstancedScatterVisual
sebsjames Dec 16, 2025
139b2b4
Preparing for instance params in a second SSBO
sebsjames Dec 17, 2025
064ab71
Progress towards parameters
sebsjames Dec 17, 2025
ea3d43b
Nearly there with instanced models. Only problem to solve is how to a…
sebsjames Dec 17, 2025
d8465e2
Adds a new output-shaders feature (Ctrl-shift-s)
sebsjames Dec 17, 2025
bdd89c5
Beginning the architectural changes required to share SSBOs between i…
sebsjames Dec 17, 2025
8e8620a
Compiles now, but I want ssbos to be program-wide objects, so they sh…
sebsjames Dec 18, 2025
8a18ce4
Diff simplification
sebsjames Dec 18, 2025
505e08d
Diff simplification
sebsjames Dec 18, 2025
0df2783
Diff simplification
sebsjames Dec 18, 2025
5e89f44
Moves some code to the 'for future use' ifdef
sebsjames Dec 18, 2025
ef1afcc
Moves ssbos into VisualResources
sebsjames Dec 18, 2025
f1339c6
Am now allocating and then inserting data into SSBOs
sebsjames Dec 18, 2025
e8cad33
INserts instparam data
sebsjames Dec 18, 2025
b53dc41
More or less reinstates the working instanced model
sebsjames Dec 18, 2025
6b60d73
Copy to GPU only when required
sebsjames Dec 18, 2025
74c580c
Updates the shader to use the now-separate SSBO data
sebsjames Dec 18, 2025
4143d2b
Notes and reduction in size of SSBO's allocated
sebsjames Dec 18, 2025
1a23a33
set max-instances for our instanced models
sebsjames Dec 18, 2025
f1b5979
Applies changes to the NoMX classes
sebsjames Dec 18, 2025
cbd8647
Merge pull request #102 from sebsjames/dev/instancing_more_than_one
sebsjames Dec 18, 2025
b66c8e5
Shader tweaks
sebsjames Dec 18, 2025
6501dca
Merge pull request #100 from sebsjames/dev/drawarrays
sebsjames Dec 18, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions examples/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,12 @@ if(NOT APPLE)

add_executable(scatter_geodesic scatter_geodesic.cpp)
target_link_libraries(scatter_geodesic OpenGL::GL glfw Freetype::Freetype)

# Instancing also not available on Apple (limited to OpenGL 4.1)
add_executable(scatter_instanced scatter_instanced.cpp)
target_link_libraries(scatter_instanced OpenGL::GL glfw Freetype::Freetype)
add_executable(breadcrumbs breadcrumbs.cpp)
target_link_libraries(breadcrumbs OpenGL::GL glfw Freetype::Freetype)
endif()

add_executable(scatter_dynamic scatter_dynamic.cpp)
Expand Down
128 changes: 128 additions & 0 deletions examples/breadcrumbs.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
/*
* Visualize a test surface
*/
#include <iostream>
#include <fstream>
#include <cmath>
#include <array>

#include <sm/scale>
#include <sm/vec>
#include <sm/vvec>

#include <mplot/Visual.h>
#include <mplot/ColourMap.h>
#include <mplot/InstancedScatterVisual.h>
#include <mplot/GeodesicVisual.h>

// Instanced rendering requires OpenGL 4.3 or higher (for the SSBO)
constexpr int glver = mplot::gl::version_4_3;

constexpr float st = sm::mathconst<float>::two_pi / 360;
constexpr float z = 0.0f;
sm::vec<float, 3> f (int i, float _z = 0.0f)
{
float phi = st * i;
float r = 1.0f + 0.1f * std::sin (phi * 10.0f);
sm::vec<float, 3> xyz = {
r * std::sin (phi),
r * std::cos (phi),
_z
};
return xyz;
}

int main()
{
int rtn = -1;

mplot::Visual<glver> v(1024, 768, "mplot::InstancedScatterVisual");
v.lightingEffects();

// A normal, non instanced model. A sphere to orbit around.
auto gv1 = std::make_unique<mplot::GeodesicVisual<float,glver>> (sm::vec<>{}, 0.2f);
gv1->name = "geodesic";
v.bindmodel (gv1);
gv1->iterations = 3;
gv1->cm.setType (mplot::ColourMapType::Tofino);
gv1->finalize();
// re-colour after construction
auto gv1p = v.addVisualModel (gv1);
// sequential colouring:
size_t sz1 = gv1p->data.size();
gv1p->data.linspace (0.0f, 1.0f, sz1);
gv1p->reinitColours();

constexpr int dsz = 260;
sm::vvec<sm::vec<float, 3>> points(dsz);
sm::vvec<float> psz(dsz);

int i = 0;
sm::vec<float, 3> xyz = {};
for (i = 0; i < dsz; ++i) {
xyz = f (i);
points[i] = xyz;
psz[i] = xyz[2];
}

auto isv = std::make_unique<mplot::InstancedScatterVisual<glver>> (sm::vec<>{});
isv->name = "isv1";
v.bindmodel (isv);
isv->max_instances = dsz;
isv->radiusFixed = 0.03f;
isv->finalize();
auto isvp = v.addVisualModel (isv);

// Another one
isv = std::make_unique<mplot::InstancedScatterVisual<glver>> (sm::vec<>{0,0.1,0});
isv->name = "isv2";
v.bindmodel (isv);
isv->max_instances = dsz;
isv->radiusFixed = 0.03f;
isv->finalize();
auto isvp2 = v.addVisualModel (isv);

v.render();
isvp->set_instance_data (points); // colour, alpha, scale

isvp2->set_instance_data (points * 1.2f, mplot::colour::black, 0.7f, 1.0f);

sm::vvec<std::array<float, 3>> col = { mplot::colour::blue, mplot::colour::springgreen };
sm::vvec<float> alph = { 0.5f, 1.0f };
sm::vvec<float> scl = { 1.0f, 1.2f };

while (!v.readyToFinish()) {

xyz = f (i%360);
//std::cout << "i = " << i << ", i%dsz = " << (i%dsz) << ", i%360 = " << (i%360) << " f(i%360) = " << xyz << " -> points[" << (i%dsz)<< "]" << std::endl;

points[i%dsz] = xyz;
psz[i%dsz] = xyz[2];

#if 1
// Update all points/psz
// Place data in SSBO. first call of set_data must occur after first call to v.render()
isvp->set_instance_data (points, col, alph, scl);

v.render();
v.waitevents (0.018);

#else // I haven't mastered updating a subrange of data in an SSBO
// update circularly, change isvp->instance_start each time
std::cout << "updating data with points[i%dsz] = " << points[i%dsz] << std::endl;
isvp->update_instance_data (points, data, (i % dsz), (i % dsz));

std::cout << "Before render, isvp->instance_start is " << isvp->instance_start << std::endl;

v.render();
v.wait (0.4);

isvp->instance_start += 1;
if (isvp->instance_start >= isvp->instance_count) { isvp->instance_start = 0; }

#endif
++i;
}

return rtn;
}
2 changes: 1 addition & 1 deletion examples/gl_compute/shader_naive_scan.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

#include <mplot/gl/compute_manager.h>
#include <mplot/gl/texture.h>
#include <mplot/gl/ssbo.h>
#include <mplot/gl/ssbo_nomx.h>
#include <mplot/gl/shaders.h>
#include <mplot/loadpng.h>

Expand Down
2 changes: 1 addition & 1 deletion examples/gl_compute/shader_naive_scan_cli.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@

#include <mplot/gl/compute_manager_cli.h>
#include <mplot/gl/texture.h>
#include <mplot/gl/ssbo.h>
#include <mplot/gl/ssbo_nomx.h>
#include <mplot/loadpng.h>

namespace my {
Expand Down
38 changes: 26 additions & 12 deletions examples/gl_compute/shader_ssbo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
*/

// You have to include the GL headers manually so that you will be sure you have the
// right ones. THis is because for OpenGL version 4.3, you would include GL3/gl3.h and
// right ones. This is because for OpenGL version 4.3, you would include GL3/gl3.h and
// GL/glext.h whereas if you are targeting OpenGL 3.1 ES, you want to include
// GLES3/gl3[12].h (and maybe GLES3/gl3ext.h).
#include <GLES3/gl31.h>
Expand All @@ -13,13 +13,15 @@
#include <mplot/gl/compute_manager.h>
#include <mplot/gl/util_nomx.h>
#include <mplot/gl/texture.h>
#include <mplot/gl/ssbo.h>
#include <mplot/gl/ssbo_nomx.h>
#include <mplot/loadpng.h>

namespace my {

static constexpr int glver = mplot::gl::version_3_1_es;

// Use OpenGL 3.1 ES here
struct compute_manager : public mplot::gl::compute_manager<mplot::gl::version_3_1_es>
struct compute_manager : public mplot::gl::compute_manager<glver>
{
static constexpr int dwidth = 256;
static constexpr int dheight = 65;
Expand Down Expand Up @@ -86,9 +88,12 @@ namespace my {
sm::vec<unsigned int, 2> _dims = mplot::loadpng ("../examples/gl_compute/bike.png", inputvv);
if ((_dims - dims) > 0) { throw std::runtime_error ("Loaded image is not expected size"); }

this->input_ssbo.init (); // could take the image data as arg

// Set that data into the SSBO object (where it is stored in a vec<>)
std::copy (inputvv.begin(), inputvv.end(), this->input_ssbo.data.begin());
this->input_ssbo.init();
sm::vec<float, dsz> data;
std::copy (inputvv.begin(), inputvv.end(), data.begin());
this->input_ssbo.copy_to_gpu (data);
}

~compute_manager()
Expand Down Expand Up @@ -119,8 +124,9 @@ namespace my {
this->compute_program.load_shaders (shaders);

// We'll reuse the vertex/fragment shaders from the shadercompute example
std::string defVtxShdr = mplot::getDefaultVtxShader (glver);
std::vector<mplot::gl::ShaderInfo> vtxshaders = {
{GL_VERTEX_SHADER, "../examples/gl_compute/shader_ssbo.vert.glsl", mplot::defaultVtxShader, 0 },
{GL_VERTEX_SHADER, "../examples/gl_compute/shader_ssbo.vert.glsl", defVtxShdr.c_str(), 0 },
{GL_FRAGMENT_SHADER, "../examples/gl_compute/shader_ssbo.frag.glsl", mplot::defaultFragShader, 0 }
};
this->vtxprog = mplot::gl::LoadShaders (vtxshaders);
Expand All @@ -130,10 +136,12 @@ namespace my {
// Override your one time/non-rendering compute function
void compute() final
{
// To copy updated data:
this->input_ssbo.data[0] = std::abs (std::sin (compstep)); // Make a pixel pulse
// To copy updated data. Would be nice to give a data subrange to update.
sm::vec<float, 2> data_update;
data_update[0] = std::abs (std::sin (compstep)); // Make a pixel pulse
data_update[1] = std::abs (std::cos (compstep));
compstep += 0.0001;
this->input_ssbo.copy_to_gpu();
this->input_ssbo.copy_to_gpu (data_update, 2);

this->measure_compute(); // optional
this->compute_program.use();
Expand All @@ -142,8 +150,14 @@ namespace my {
// To retreive data from the SSBO:
// sm::range<float> ssbo_range = this->input_ssbo.get_range();
// or
this->input_ssbo.copy_from_gpu();
// and access input_ssbo.data.
#if 0
sm::vec<float, 6> data_rtn;
this->input_ssbo.copy_from_gpu (data_rtn, 0);
std::cout << "data_rtn[0-5] = "
<< data_rtn[0] << ", " << data_rtn[1] << ", "
<< data_rtn[2] << ", " << data_rtn[3] << ", "
<< data_rtn[4] << ", " << data_rtn[5] << std::endl;
#endif
}

// Override the render method to do whatever visualization you want
Expand Down Expand Up @@ -194,7 +208,7 @@ namespace my {
// CPU side input data. This will be SSBO index 1.
mplot::gl::ssbo<1, float, dsz> input_ssbo;
// You will need at least one gl::compute_shaderprog
mplot::gl::compute_shaderprog<mplot::gl::version_3_1_es> compute_program;
mplot::gl::compute_shaderprog<glver> compute_program;
};
} // namespace my

Expand Down
10 changes: 6 additions & 4 deletions examples/gl_compute/shadercompute.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
* https://learnopengl.com/Guest-Articles/2022/Compute-Shaders/Introduction
*/


// You have to include the GL headers manually so that you will be sure you have the
// right ones. This is because for OpenGL version 4.3, you would include GL3/gl3.h and
// GL/glext.h whereas if you are targeting OpenGL 3.1 ES, you want to include
Expand All @@ -25,8 +24,10 @@

namespace my {

static constexpr int glver = mplot::gl::version_4_5;

// Specify OpenGL version 4.5 (4.3 is min for compute)
struct compute_manager : public mplot::gl::compute_manager<mplot::gl::version_4_5>
struct compute_manager : public mplot::gl::compute_manager<glver>
{
// Call init in your constructor, ensuring *your* version of load_shaders() is called.
compute_manager()
Expand Down Expand Up @@ -80,8 +81,9 @@ namespace my {
};
this->compute_program.load_shaders (shaders);

std::string defVtxShdr = mplot::getDefaultVtxShader (glver);
std::vector<mplot::gl::ShaderInfo> vtxshaders = {
{GL_VERTEX_SHADER, "../examples/gl_compute/shadercompute.vert.glsl", mplot::defaultVtxShader, 0 },
{GL_VERTEX_SHADER, "../examples/gl_compute/shadercompute.vert.glsl", defVtxShdr.c_str(), 0 },
{GL_FRAGMENT_SHADER, "../examples/gl_compute/shadercompute.frag.glsl", mplot::defaultFragShader, 0 }
};
this->vtxprog = mplot::gl::LoadShaders (vtxshaders);
Expand Down Expand Up @@ -137,7 +139,7 @@ namespace my {
unsigned int vao = 0;
unsigned int vbo = 0;
// You will need at least one gl::compute_shaderprog
mplot::gl::compute_shaderprog<mplot::gl::version_4_5> compute_program;
mplot::gl::compute_shaderprog<glver> compute_program;
};
} // namespace my

Expand Down
5 changes: 3 additions & 2 deletions examples/hexgrid.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,14 +41,15 @@ int main()

// Make some dummy data (a sine wave) to make an interesting surface
std::vector<float> data(hg.num(), 0.0f);
for (unsigned int ri=0; ri<hg.num(); ++ri) {
data[ri] = 0.05f + 0.05f*std::sin(20.0f*hg.d_x[ri]) * std::sin(10.0f*hg.d_y[ri]) ; // Range 0->1
for (unsigned int ri = 0; ri < hg.num(); ++ri) {
data[ri] = 0.05f + 0.05f * std::sin (20.0f * hg.d_x[ri]) * std::sin (10.0f * hg.d_y[ri]) ; // Range 0->1
}

// Add a HexGridVisual to display the HexGrid within the sm::Visual scene
sm::vec<float, 3> offset = { 0.0f, -0.05f, 0.0f };
auto hgv = std::make_unique<mplot::HexGridVisual<float, mplot::gl::version_4_1>>(&hg, offset);
v.bindmodel (hgv);
hgv->wireframe (true);
hgv->cm.setType (mplot::ColourMapType::Ice);
hgv->setScalarData (&data);
hgv->hexVisMode = mplot::HexVisMode::HexInterp; // Or sm::HexVisMode::Triangles for a smoother surface plot
Expand Down
60 changes: 60 additions & 0 deletions examples/scatter_instanced.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/*
* Visualize a test surface
*/
#include <iostream>
#include <fstream>
#include <cmath>
#include <array>

#include <sm/scale>
#include <sm/vec>
#include <sm/vvec>

#include <mplot/Visual.h>
#include <mplot/ColourMap.h>
#include <mplot/InstancedScatterVisual.h>

// Instanced rendering requires OpenGL 4.3 or higher (for the SSBO)
constexpr int glver = mplot::gl::version_4_3;

int main()
{
int rtn = -1;

mplot::Visual<glver> v(1024, 768, "mplot::InstancedScatterVisual");
v.lightingEffects();

sm::vvec<sm::vec<float, 3>> points(20*20);
sm::vvec<float> alpha(20*20, 1.0f);
sm::vvec<float> scale(20*20);
sm::vvec<std::array<float, 3>> clrs(20*20);
size_t k = 0;

mplot::ColourMap<float> cm (mplot::ColourMapType::Plasma);
for (int i = -10; i < 10; ++i) {
for (int j = -10; j < 10; ++j) {
float x = 0.1*i;
float y = 0.1*j;
// z is some function of x, y
float z = x * std::exp(-(x*x) - (y*y));
points[k] = {x, y, z};
scale[k] = 1.0f + z;
clrs[k] = cm.convert (z);
k++;
}
}

auto isv = std::make_unique<mplot::InstancedScatterVisual<glver>> (sm::vec<>{});
v.bindmodel (isv);
isv->radiusFixed = 0.03f;
isv->finalize();
auto isvp = v.addVisualModel (isv);

v.render();
// We set the instance data, which adds points, colours, alpha and scale
isvp->set_instance_data (points, clrs, alpha, scale);

v.keepOpen();

return rtn;
}
1 change: 1 addition & 0 deletions mplot/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ install(
HexGridVisual.h
HSVWheelVisual.h
IcosaVisual.h
InstancedScatterVisual.h
LengthscaleVisual.h
NormalsVisual.h
PointRowsMeshVisual.h
Expand Down
Loading