Using a Custom Hlms with Ignition Rendering

I’m looking into developing a custom Hlms for a port of an ocean simulation from Gazebo11 to Ignition and would like to understand the recommended way to incorporate custom materials and other rendering classes when the code sits outside the main Ignition code base (in a plugin library for example).

The first question is how to switch a visual to use a different Hlms in a nice way, for example using HlmsUnlit rather than HlmPbs. Here is a work-around approach that renders a sphere using Unlit and the rest of the scene using Pbs (with a custom shader using ShaderParams)

  // create red material
  MaterialPtr red = _scene->CreateMaterial();
  red->SetAmbient(0.5, 0.0, 0.0);
  red->SetDiffuse(1.0, 0.0, 0.0);
  red->SetSpecular(0.5, 0.5, 0.5);

  // create sphere geometry
  auto sphereGeometry = _scene->CreateSphere();

#if 1

  // ogre2 material
  auto redOgreMat = std::dynamic_pointer_cast<Ogre2Material>(red);
  auto redOgreUnlit = redOgreMat->UnlitDatablock();

  // switch to unlit material
  MaterialPtr matUnlit;
  matUnlit = _scene->CreateMaterial();
  auto ogreMat = std::dynamic_pointer_cast<Ogre2Material>(matUnlit);
  auto ogreDatablock = ogreMat->UnlitDatablock();
  ogreDatablock->setColour(Ogre::ColourValue(M_PI, 0.0, 0.0, 1.0));
  // igndbg << "Unlit material name [" << *ogreDatablock->getNameStr() << "]\n";

  auto ogreGeom = std::dynamic_pointer_cast<Ogre2Geometry>(sphereGeometry);
  auto ogreObject = ogreGeom->OgreObject();
  auto ogreItem = dynamic_cast<Ogre::Item *>(ogreObject);


  // create sphere visual
  VisualPtr sphere = _scene->CreateVisual();
  sphere->SetOrigin(0.0, -0.5, 0.0);
  sphere->SetLocalPosition(20, 0, 5);
  sphere->SetLocalRotation(0, 0, 0);
  sphere->SetLocalScale(10, 10, 10);

There’s a couple of probs with the approach:

  • It’s by-passing almost all the Ignition rendering machinery and all the lifetime control of objects that comes with that.
  • There is a some less than robust link library path additions to the CMakeLists.txt to located the render engine plugin headers and libraries for include and link deps.

It would be nice to be able to specify a new HlmsDatablock (or an Ignition equivalent abstraction of this) on the material and set it on the Geometry or Visual directly rather than burrow down to the Ogre2 internals.

The second question has to do with extending the various rendering types and how you then add them to the scene. Most of the object types: Visual, Geometry, Material etc can be (and are) subclassed to create specific types. However the Scene and BaseScene<> need to know about these types because the methods to add / register an object are not accessible outside the Scene class (specifically the method that gets a new object id) . This makes it difficult to add new extension objects defined in a plugin library to the scene. It’s possible by a few workarounds (you can subclass objects to get access to protected members and so on) but it feels like you’re working against the design rather than with it.

Would this work? Load and run visual plugin (system) on GUI side by iche033 · Pull Request #1275 · ignitionrobotics/ign-gazebo · GitHub . It’s been released and announced just a while ago: New Ignition releases 2022-03-01 (Citadel, Edifice, Fortress) .

The ShaderParam plugin could provide visuals for some of the wave generation methods (such as the trochoid waves used in the ignition-rendering wave example) but it does not use the full power of Ogre2 Hlms for providing visuals that cover large areas in the way that HlmsTerra does for terrain using heightmaps. An ocean is a bit like a terrain, except that it’s time varying and in addition to the height varying the horizontal positions of the vertices are also displaced, so the handling of the skirts used when tiling the ocean is a little different to Terra, or different enough that I don’t think I can reuse it (but I hope to borrow the concepts).