From b790f6615cd9d31e0eaf06373fd28814aa816ef7 Mon Sep 17 00:00:00 2001 From: Seb James Date: Tue, 24 Feb 2026 10:53:30 +0000 Subject: [PATCH 1/4] Enables an additional scaling matrix for instanced scaling (a scale/transformation to apply to all instances) --- examples/breadcrumbs.cpp | 6 ++++++ mplot/VisualDefaultShaders.h | 3 ++- mplot/VisualModelBase.h | 9 +++++++++ mplot/VisualModelImplMX.h | 10 ++++++++++ 4 files changed, 27 insertions(+), 1 deletion(-) diff --git a/examples/breadcrumbs.cpp b/examples/breadcrumbs.cpp index c99e9e4e..47406a9e 100644 --- a/examples/breadcrumbs.cpp +++ b/examples/breadcrumbs.cpp @@ -88,6 +88,7 @@ int main() sm::vvec> col = { mplot::colour::blue, mplot::colour::springgreen }; sm::vvec alph = { 0.5f, 1.0f }; + // A scaling vector to make sequential instances have a different size sm::vvec scl = { 1.0f, 1.2f }; while (!v.readyToFinish()) { @@ -103,6 +104,11 @@ int main() // 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); + // As well as scl, we have an applied-to-all instances scale (iscl) that is passed to the + // s_matrix in the instance shader + float iscl = 1.5f + 0.5f * std::sin (sm::mathconst::two_pi * (static_cast(i % 360) / 360.0f)); + isvp->set_instance_scale (iscl); + v.render(); v.waitevents (0.018); diff --git a/mplot/VisualDefaultShaders.h b/mplot/VisualDefaultShaders.h index 41d8c33d..235452d3 100644 --- a/mplot/VisualDefaultShaders.h +++ b/mplot/VisualDefaultShaders.h @@ -15,6 +15,7 @@ namespace mplot "uniform mat4 p_matrix;\n" "uniform float alpha;\n"; const char* defaultVtxShader_instance_uniforms = + "uniform mat4 s_matrix;\n" // scaling matrix "uniform int instance_count = 0;\n" "uniform int instance_start = -1;\n" "uniform int instparam_count = 0;\n"; @@ -56,7 +57,7 @@ namespace mplot " float s = iparam[ippos_i + idx * 5 + 4];\n" " vec3 p_three = vec3(position) * s;\n" " vec4 p_scaled = vec4(p_three, 1.0);\n" - " gl_Position = (p_matrix * v_matrix * m_matrix * (p_scaled + iposv));\n" + " gl_Position = (p_matrix * v_matrix * m_matrix * ((s_matrix * p_scaled) + iposv));\n" " vertex.color = vec4(iparam[ippos_i + idx * 5], iparam[ippos_i + idx * 5 + 1], iparam[ippos_i + idx * 5 + 2], iparam[ippos_i + idx * 5 + 3]);\n" " vertex.fragpos = vec3(m_matrix * p_scaled);\n" " } else {\n" diff --git a/mplot/VisualModelBase.h b/mplot/VisualModelBase.h index b190f448..b2dea8a0 100644 --- a/mplot/VisualModelBase.h +++ b/mplot/VisualModelBase.h @@ -828,6 +828,9 @@ namespace mplot std::function&, const float, const float)> insert_instparam_data; std::function*)> instanced_needs_update; + //! Set the scaling matrix for all instances + virtual void set_instance_scale (const float scl) = 0; + //! Set up the instance positions (with default params for colour, rotn, scale) virtual void set_instance_data (const sm::vvec>& position) = 0; @@ -908,6 +911,12 @@ namespace mplot */ sm::mat scenematrix = {}; + /*! + * Instance scaling. This matrix can be used to control the scale of all instances of an + * instanced VisualModel + */ + sm::mat instscale = {}; + //! Contains the positions within the vbo array of the different vertex buffer objects enum VBOPos { posnVBO, normVBO, colVBO, idxVBO, numVBO }; diff --git a/mplot/VisualModelImplMX.h b/mplot/VisualModelImplMX.h index 67fdb9a4..14144723 100644 --- a/mplot/VisualModelImplMX.h +++ b/mplot/VisualModelImplMX.h @@ -70,6 +70,12 @@ namespace mplot model->releaseContext = &mplot::VisualBase::release_context; } + void set_instance_scale (const float scl) final + { + this->instscale.set_identity(); + this->instscale.scale (scl); + } + void set_instance_data (const sm::vvec>& position) final { sm::vvec> c = { mplot::colour::crimson }; @@ -301,6 +307,10 @@ namespace mplot GLint loc_m = _glfn->GetUniformLocation (this->get_gprog(this->parentVis), static_cast("m_matrix")); if (loc_m != -1) { _glfn->UniformMatrix4fv (loc_m, 1, GL_FALSE, this->viewmatrix.arr.data()); } + // the instance scaling matrix (applied to all instances) + GLint loc_s = _glfn->GetUniformLocation (this->get_gprog(this->parentVis), static_cast("s_matrix")); + if (loc_s != -1) { _glfn->UniformMatrix4fv (loc_s, 1, GL_FALSE, this->instscale.arr.data()); } + if constexpr (debug_render) { std::cout << "VisualModel::render: scenematrix:\n" << this->scenematrix << std::endl; std::cout << "VisualModel::render: model viewmatrix:\n" << this->viewmatrix << std::endl; From f25188f3304d1f62a341dfbcd96851cb8ac37048 Mon Sep 17 00:00:00 2001 From: Seb James Date: Tue, 24 Feb 2026 11:11:55 +0000 Subject: [PATCH 2/4] Demonstrating use of distance to rotation centre to scale instances --- examples/breadcrumbs.cpp | 5 +++++ mplot/VisualBase.h | 3 +++ 2 files changed, 8 insertions(+) diff --git a/examples/breadcrumbs.cpp b/examples/breadcrumbs.cpp index 47406a9e..36f2d851 100644 --- a/examples/breadcrumbs.cpp +++ b/examples/breadcrumbs.cpp @@ -109,6 +109,11 @@ int main() float iscl = 1.5f + 0.5f * std::sin (sm::mathconst::two_pi * (static_cast(i % 360) / 360.0f)); isvp->set_instance_scale (iscl); + // Can set scale of the black spheres based on distance to rotation centre. As they get + // further away, they get larger so you can still see them. + float iscl2 = v.get_d_to_rotation_centre() * 0.1f; + isvp2->set_instance_scale (iscl2); + v.render(); v.waitevents (0.018); diff --git a/mplot/VisualBase.h b/mplot/VisualBase.h index eb9c557b..f27809af 100644 --- a/mplot/VisualBase.h +++ b/mplot/VisualBase.h @@ -990,6 +990,9 @@ namespace mplot public: + //! Getter for d_to_rotation_centre + float get_d_to_rotation_centre() const { return this->d_to_rotation_centre; } + /* * Generic callback handlers */ From 94620b334008a5651c20d41922d38b4a812c16fa Mon Sep 17 00:00:00 2001 From: Seb James Date: Tue, 24 Feb 2026 12:49:59 +0000 Subject: [PATCH 3/4] Adds instcolour for setting instance colour --- mplot/VisualModelBase.h | 5 +++++ mplot/VisualModelImplMX.h | 2 +- mplot/VisualModelImplNoMX.h | 8 +++++++- 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/mplot/VisualModelBase.h b/mplot/VisualModelBase.h index b2dea8a0..32fc566a 100644 --- a/mplot/VisualModelBase.h +++ b/mplot/VisualModelBase.h @@ -917,6 +917,11 @@ namespace mplot */ sm::mat instscale = {}; + /*! + * The colour for all instances. This is used if you don't set colour in your instance params. + */ + std::array instcolour = mplot::colour::yellow; + //! Contains the positions within the vbo array of the different vertex buffer objects enum VBOPos { posnVBO, normVBO, colVBO, idxVBO, numVBO }; diff --git a/mplot/VisualModelImplMX.h b/mplot/VisualModelImplMX.h index 14144723..0ef20f85 100644 --- a/mplot/VisualModelImplMX.h +++ b/mplot/VisualModelImplMX.h @@ -78,7 +78,7 @@ namespace mplot void set_instance_data (const sm::vvec>& position) final { - sm::vvec> c = { mplot::colour::crimson }; + sm::vvec> c = { this->instcolour }; sm::vvec a = { 1.0f }; sm::vvec s = { 1.0f }; this->set_instance_data (position, c, a, s); diff --git a/mplot/VisualModelImplNoMX.h b/mplot/VisualModelImplNoMX.h index 00d0cb47..b0ecf07e 100644 --- a/mplot/VisualModelImplNoMX.h +++ b/mplot/VisualModelImplNoMX.h @@ -66,9 +66,15 @@ namespace mplot model->releaseContext = &mplot::VisualBase::release_context; } + void set_instance_scale (const float scl) final + { + this->instscale.set_identity(); + this->instscale.scale (scl); + } + void set_instance_data (const sm::vvec>& position) final { - sm::vvec> c = { mplot::colour::crimson }; + sm::vvec> c = { this->instcolour }; sm::vvec a = { 1.0f }; sm::vvec s = { 1.0f }; this->set_instance_data (position, c, a, s); From 7464ea06801e83d9bfa4e7a0b109256db56b911a Mon Sep 17 00:00:00 2001 From: Seb James Date: Tue, 24 Feb 2026 12:54:57 +0000 Subject: [PATCH 4/4] better scaling --- examples/breadcrumbs.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/breadcrumbs.cpp b/examples/breadcrumbs.cpp index 36f2d851..a19d0634 100644 --- a/examples/breadcrumbs.cpp +++ b/examples/breadcrumbs.cpp @@ -111,7 +111,7 @@ int main() // Can set scale of the black spheres based on distance to rotation centre. As they get // further away, they get larger so you can still see them. - float iscl2 = v.get_d_to_rotation_centre() * 0.1f; + float iscl2 = 0.6f * std::log (2.0f + v.get_d_to_rotation_centre()); isvp2->set_instance_scale (iscl2); v.render();