Using OgreBites::SGTechniqueResolverListener to have different ways of texturing the rendered scene

A place for users of OGRE to discuss ideas and experiences of utilitising OGRE in their games / demos / applications.
bro
Gnoblar
Posts: 21
Joined: Fri May 20, 2022 6:15 am
x 5

Using OgreBites::SGTechniqueResolverListener to have different ways of texturing the rendered scene

Post by bro »

Hello,

I'm trying to use OgreBites::SGTechniqueResolverListener to create alternative rendering for the materials in my scene.
I defined a couple of schemes and for each of them I have a class inheriting SGTechniqueResolverListener in which i have specific implementations of handleSchemeNotFound. These listeners are registered into the MaterialManager. I then have different viewports connected to the same camera viewing the scene. Each viewport refers to a scheme.
It works rather well if variations of the technique consists in changing the ambiant, the diffuse, the specular or the emissive colors.
But trying to modify the texture units does not work.

Example (which is working):
The viewport in the upper right corner shows the scene with per material instance color.

Image

It corresponds to the following SGTechniqueResolverListener derivation:

Code: Select all

TechniqueResolverListener::TechniqueResolverListener(Ogre::RTShader::ShaderGenerator* shaderGenerator)
  : OgreBites::SGTechniqueResolverListener{shaderGenerator}, m_key{0u}
{
}

Ogre::Technique* TechniqueResolverListener::handleSchemeNotFound(
    unsigned short schemeIndex,
    const Ogre::String& schemeName,
    Ogre::Material* originalMaterial,
    unsigned short lodIndex,
    const Ogre::Renderable* rend)
{
  const auto color = getColor(fmt::format("{}/{}", originalMaterial->getGroup(), originalMaterial->getName()));
  Ogre::Technique* pTech = OgreBites::SGTechniqueResolverListener::handleSchemeNotFound(
      schemeIndex, schemeName, originalMaterial, lodIndex, rend);


  if (pTech != nullptr) {
    for (auto* pass : pTech->getPasses()) {
        pass->setLightingEnabled(false);
        pass->setDiffuse(Ogre::ColourValue::Black);
        pass->setSpecular(Ogre::ColourValue::Black);
        pass->setAmbient(Ogre::ColourValue::Black);
        pass->setSelfIllumination(color);
        pass->setColourWriteEnabled(true);
    }
  }

  return pTech;
}

What i fail to achieve:
I want to change the texture-units of the passes (actually only one) to only keep the transparency and force the color (from the texture) to be white
So I changed my code to:

Code: Select all

Ogre::Technique* TechniqueResolverListener::handleSchemeNotFound(
    unsigned short schemeIndex,
    const Ogre::String& schemeName,
    Ogre::Material* originalMaterial,
    unsigned short lodIndex,
    const Ogre::Renderable* rend)
{
  const auto color = getColor(fmt::format("{}/{}", originalMaterial->getGroup(), originalMaterial->getName()));
  Ogre::Technique* pTech = OgreBites::SGTechniqueResolverListener::handleSchemeNotFound(
      schemeIndex, schemeName, originalMaterial, lodIndex, rend);


  if (pTech != nullptr) {
    for (auto* pass : pTech->getPasses()) {

//-----
      for (auto* tex_unit : pass->getTextureUnitStates()) {
        tex_unit->setColourOperationEx(
            Ogre::LBX_MODULATE, Ogre::LBS_MANUAL, Ogre::LBS_CURRENT, Ogre::ColourValue::White);
        tex_unit->setAlphaOperation(Ogre::LBX_MODULATE, Ogre::LBS_TEXTURE, Ogre::LBS_CURRENT);
      }  
//-----
pass->setLightingEnabled(false); pass->setDiffuse(Ogre::ColourValue::Black); pass->setSpecular(Ogre::ColourValue::Black); pass->setAmbient(Ogre::ColourValue::Black); pass->setSelfIllumination(color); pass->setColourWriteEnabled(true); } } return pTech; }

but textures are not impacted : i don't get the 'flat color aspect' i expect. :(

Any idea?

BTW, my context is: Ogre 14.2.6 Feodra40, GL3+

bro
Gnoblar
Posts: 21
Joined: Fri May 20, 2022 6:15 am
x 5

Re: Using OgreBites::SGTechniqueResolverListener to have different ways of texturing the rendered scene

Post by bro »

I have an ugly way of making it to (partially) work:
I modify the technique #0 before calling OgreBites::SGTechniqueResolverListener::handleSchemeNotFound
so that when the system creates the shaders then the texture units are in the desired state.

Code: Select all

Ogre::Technique* TechniqueResolverListener::handleSchemeNotFound(
    unsigned short schemeIndex,
    const Ogre::String& schemeName,
    Ogre::Material* originalMaterial,
    unsigned short lodIndex,
    const Ogre::Renderable* rend)
{
  const auto color =
      getColor(fmt::format("{}/{}", originalMaterial->getGroup(), originalMaterial->getName()));

  auto* ref_tech = originalMaterial->getTechnique(0);

  for (auto* pass : ref_tech->getPasses()) {
    for (auto* tex_unit : pass->getTextureUnitStates()) {
      tex_unit->setColourOperationEx(
          Ogre::LBX_MODULATE, Ogre::LBS_MANUAL, Ogre::LBS_CURRENT, Ogre::ColourValue::White);
      tex_unit->setAlphaOperation(Ogre::LBX_MODULATE, Ogre::LBS_TEXTURE, Ogre::LBS_CURRENT);
    }
  }

  Ogre::Technique* pTech = OgreBites::SGTechniqueResolverListener::handleSchemeNotFound(
      schemeIndex, schemeName, originalMaterial, lodIndex, rend);

  if (pTech != nullptr) {
    for (auto* pass : pTech->getPasses()) {
        pass->setLightingEnabled(false);
        pass->setDiffuse(Ogre::ColourValue::Black);
        pass->setSpecular(Ogre::ColourValue::Black);
        pass->setAmbient(Ogre::ColourValue::Black);
        pass->setSelfIllumination(color);
        pass->setColourWriteEnabled(true);
    }
  }

  return pTech;
}

i really don't like this way since then the technique #0 (default) of the original material gets dirty (no longer in its original state).

i say it's partially working since this hack is only ok if default render is called before alternative render: if handleSchemeNotFound is called for the non default scheme first it corrupts the texturing and i get white texturing on the main/default scene.

paroj
OGRE Team Member
OGRE Team Member
Posts: 2142
Joined: Sun Mar 30, 2014 2:51 pm
x 1151

Re: Using OgreBites::SGTechniqueResolverListener to have different ways of texturing the rendered scene

Post by paroj »

you need a src technique for each scheme that the RTSS should handle. See:
https://github.com/OGRECave/ogre/blob/1 ... erial#L163

bro
Gnoblar
Posts: 21
Joined: Fri May 20, 2022 6:15 am
x 5

Re: Using OgreBites::SGTechniqueResolverListener to have different ways of texturing the rendered scene

Post by bro »

Perfect clue!

in handleSchemeNotFound method, instead of using base method (of OgreBites::SGTechniqueResolverListener) and try to modify the returned technique, i re-implemented it this way:
1/ create a source technique in the material for the requested scheme based on the default technique (0) + modif i desire
2/ create the shader from this technique
the whole being inspired from SGTechniqueResolverListener::handleSchemeNotFound (using the proper createShaderBasedTechnique overload)

Final implem is:

Code: Select all

Ogre::Technique* TechniqueResolverListener::handleSchemeNotFound(
    unsigned short schemeIndex,
    const Ogre::String& schemeName,
    Ogre::Material* originalMaterial,
    unsigned short lodIndex,
    const Ogre::Renderable* rend)
{
  const auto color = getColor(fmt::format("{}/{}", originalMaterial->getGroup(), originalMaterial->getName()));

  const auto src_tech_name = fmt::format("SourceTechniqueOf_{}", schemeName);

  auto* src_tech = originalMaterial->getTechnique(src_tech_name);
  if (src_tech == nullptr) {
    src_tech = originalMaterial->createTechnique();
    *src_tech = *originalMaterial->getTechnique(0);
    src_tech->setName(src_tech_name);

// setup the source technique
for (auto* pass : src_tech->getPasses()) {
  for (auto* tex_unit : pass->getTextureUnitStates()) {
    tex_unit->setColourOperationEx(
        Ogre::LBX_MODULATE, Ogre::LBS_MANUAL, Ogre::LBS_CURRENT, Ogre::ColourValue::White);
    tex_unit->setAlphaOperation(Ogre::LBX_MODULATE, Ogre::LBS_TEXTURE, Ogre::LBS_CURRENT);
  }

  pass->setLightingEnabled(true);
  pass->setColourWriteEnabled(true);

  pass->setDiffuse(Ogre::ColourValue::Black);
  pass->setSpecular(Ogre::ColourValue::Black);
  pass->setAmbient(Ogre::ColourValue::Black);
  pass->setSelfIllumination(color);
}
  }

  mShaderGenerator->createShaderBasedTechnique(src_tech, schemeName);
  mShaderGenerator->validateMaterial(schemeName, *originalMaterial);

  for (auto* tech : originalMaterial->getTechniques()) {
    if (tech->getSchemeName() == schemeName) {
      return tech;
    }
  }
  return nullptr;
}

It works like a charm :D

Thanks a lot.