[RTSS] Create Shader versions of FFP techniques at load-time

Problems building or running the engine, queries about how to use features etc.
Post Reply
JDX_John
Gnome
Posts: 397
Joined: Sat Nov 08, 2008 1:59 pm
x 2

[RTSS] Create Shader versions of FFP techniques at load-time

Post by JDX_John »

Instead of using a material listener and waiting until a material is used for render, I want to find ALL fixed-function render-paths in materials at load/start-time, and replace them with shaderised versions.

One reason for this is I already use multiple schemes for different viewports, so the logic used in the sample isn't applicable.

I don't really know how to go about this but I think I see a few specific sub-problems that need solving:

1a)How to iterate over materials looking for techniques that use fixed-function. Is it sensible to use some sort of listener to catch materials as they are being loaded by ResourceManager, or manually iterate every material in MaterialManager after loading my resources?

1b)How to tell a technique/pass uses fixed-function?

2)Should I be looking at the technique level, or at individual passes? A technique might contain one shader-based pass and one fixed-function pass. Is ShaderGenerator::createShaderBasedTechnique safe/optimal to use, or should I somehow iterate each pass checking if it uses fixed-function, and create a new Pass using RTSS API?

3)How to actually replace a pass/technique with a new one I created?

Sorry for long post, hope it makes sense. If this is a useful thing to do I'm happy to share code I come up with, but since I don't know RTSS well it's possible my whole idea is stupid!
Alexiss
Halfling
Posts: 74
Joined: Wed Aug 10, 2011 2:11 pm
x 11

Re: [RTSS] Create Shader versions of FFP techniques at load-

Post by Alexiss »

I may have understood you wrong, but from what I understand, what you're trying to do seem very similar to the MaterialGenerator in the Deferred shading demo.
If you haven't already done so, it could be interesting to check how it works. There's a very complete Wiki entry, and the source code is rather easy to pick up.
JDX_John
Gnome
Posts: 397
Joined: Sat Nov 08, 2008 1:59 pm
x 2

Re: [RTSS] Create Shader versions of FFP techniques at load-

Post by JDX_John »

In my case I have concrete fixed-function materials, so it's similar but not identical. I've been doing some testing, instead of using a material-listener I do this hacky code which iterates all materials after loading:

Code: Select all

    Ogre::RTShader::ShaderGenerator &sg = Ogre::RTShader::ShaderGenerator::getSingleton();
    Ogre::MaterialManager::ResourceMapIterator it = Ogre::MaterialManager::getSingleton().getResourceIterator();
    while(it.hasMoreElements())
    {
        Ogre::MaterialPtr m = it.getNext();
        
        size_t num = m->getNumTechniques();
        for(size_t i = 0;i<num;++i)
        {
            Ogre::Technique *t = m->getTechnique(i);
            bool ff = !isProgrammable(t);
            string schemeName = t->getSchemeName(),dummyScheme=schemeName+"_RTSS_DUMMY";

            if(ff)
            {
                bool success = sg.createShaderBasedTechnique(m->getName(), t->getSchemeName(), dummyScheme);
                if(success)
                {
                    if(sg.validateMaterial(dummyScheme, m->getName()))
                    {
                        Ogre::Technique *newTech = m->getTechnique(m->getNumTechniques()-1);
                        if(newTech)
                        {
                            *t = *newTech;
                            t->setSchemeName(schemeName);
                            m->removeTechnique(m->getNumTechniques()-1);
                        }
                    }
                }//if(success)
            }//if(ff)
        }//loop
    }
This is doing what I expect... but there is some rendering weirdness. When I use a listener from the Ogre sample app I get this output on my iPad simulator:
Screen Shot 2012-10-15 at 21.35.43.png
Screen Shot 2012-10-15 at 21.35.43.png (54.43 KiB) Viewed 828 times
But when I use the code above, it looks like this:
Screen Shot 2012-10-15 at 21.15.26.png
Screen Shot 2012-10-15 at 21.15.26.png (37.78 KiB) Viewed 828 times
You can see there IS colour, but only for specific materials. I'm not sure if it's maybe a texture thing, but I get no errors and clearly SOME technique is working since it is rendering in black... these materials are 100% fixed-function and I'm using GLES2 so it would be rendered at all without a technique existing.

I saw the same issue when I didn't add my sceneManager to RTShaderGenerator, and I never understood that either. Perhaps they're related? Or maybe a lighting thing... the red/blue materials are unlit from memory.
JDX_John
Gnome
Posts: 397
Joined: Sat Nov 08, 2008 1:59 pm
x 2

Re: [RTSS] Create Shader versions of FFP techniques at load-

Post by JDX_John »

Thought I'd bump this as it's really not an area I know where to look so I'm a bit stuck. Here is the other way I was doing things using a listener:

Code: Select all

        if(ShaderGenerator::initialize())
        {
            ShaderGenerator &sg = ShaderGenerator::getSingleton();
            std::string cachePath = Paths::getTmpPath();
            logStream()<<"RTShader cache path: "<<cachePath;
            logStream()<<"RTShader language: "<<sg.getTargetLanguage();
            sg.setShaderCachePath(cachePath);
            sg.addSceneManager(m_sceneManager);
            
            Ogre::MaterialManager::getSingleton().addListener(new RTSSDefaultTechniqueListener());
        }

Code: Select all

Ogre::Technique* RTSSDefaultTechniqueListener::handleSchemeNotFound(
	unsigned short schemeIndex,const Ogre::String& schemeName, Ogre::Material* originalMaterial,
	unsigned short lodIndex,const Ogre::Renderable* rend)
{
    logStream()<<"handleSchemeNotFound(schemeIndex="<<schemeIndex<<", schemeName="<<schemeName<<", material="<<originalMaterial->getName();
	Ogre::Technique* generatedTech = NULL;
	
	// Case this is the default shader generator scheme.
	if (schemeName == Ogre::RTShader::ShaderGenerator::DEFAULT_SCHEME_NAME)
	{
		bool techniqueCreated;
		
		// Create shader generated technique for this material.
		techniqueCreated = m_ShaderGenerator.createShaderBasedTechnique(
																		 originalMaterial->getName(), 
																		 Ogre::MaterialManager::DEFAULT_SCHEME_NAME, 
																		 schemeName);   
		
		// Case technique registration succeeded.
		if (techniqueCreated)
		{
			logStream()<<"Created RTSS technique for material "<< originalMaterial->getName();
			// Force creating the shaders for the generated technique.
			m_ShaderGenerator.validateMaterial(schemeName, originalMaterial->getName());
			
			// Grab the generated technique.
			Ogre::Material::TechniqueIterator itTech = originalMaterial->getTechniqueIterator();
			
			while (itTech.hasMoreElements())
			{
				Ogre::Technique* curTech = itTech.getNext();
				
				if (curTech->getSchemeName() == schemeName)
				{
					generatedTech = curTech;
					break;
				}
			}            
		}
		else
			logStream()<<"Could not created RTSS technique for material "<< originalMaterial->getName();
	}
	else logStream()<<schemeName<<" is not an eligible scheme for RTSS generation for material "<< originalMaterial->getName();
	
	return generatedTech;
}
JDX_John
Gnome
Posts: 397
Joined: Sat Nov 08, 2008 1:59 pm
x 2

Re: [RTSS] Create Shader versions of FFP techniques at load-

Post by JDX_John »

Looking deeper, how RTSS does things is 10x more complex than I first thought. All those internal SceneManager and renderable listeners, setting an Ogre::Any on generated passes, etc. Using bits of RTSS piecemeal would seem a tougher job than I thought...
Post Reply