diff --git a/examples/breadcrumbs.cpp b/examples/breadcrumbs.cpp index c99e9e4e..a19d0634 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,16 @@ 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); + + // 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 = 0.6f * std::log (2.0f + v.get_d_to_rotation_centre()); + 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 */ 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..32fc566a 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,17 @@ 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 = {}; + + /*! + * 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 67fdb9a4..0ef20f85 100644 --- a/mplot/VisualModelImplMX.h +++ b/mplot/VisualModelImplMX.h @@ -70,9 +70,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); @@ -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; 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);