setTextureName(textureName); not working

Minor issues with the Ogre API that can be trivial to fix
Post Reply
User avatar
trilobite
Silver Sponsor
Silver Sponsor
Posts: 135
Joined: Thu Jul 13, 2006 9:16 pm
Location: San Juan Capistrano, CA, USA
x 1

setTextureName(textureName); not working

Post by trilobite »

Today, I responded to an earlier post about this issue in the mobile device forum. Wrong forum. Sorry.
http://www.ogre3d.org/forums/viewtopic.php?f=21&t=78351
Not wanting to cross post. Just getting it on record in the appropriate forum.

In short the traditional method of changing a material's texture on the fly is not working.

mMaterial->getBestTechnique()->getPass(0)->getTextureUnitState(0)->setTextureName(textureName);

This no worky no more in 1.9.0

Although the list of material pointers is nicely updated by such calls, live changes in material properties are not being wired to the renderer. Or so it would appear.
Thanks.
User avatar
Wolfmanfx
OGRE Team Member
OGRE Team Member
Posts: 1525
Joined: Fri Feb 03, 2006 10:37 pm
Location: Austria - Leoben
x 99
Contact:

Re: setTextureName(textureName); not working

Post by Wolfmanfx »

Hi,

can you reproduce the same inside the samplebrowser? I will take a look tonight.
User avatar
trilobite
Silver Sponsor
Silver Sponsor
Posts: 135
Joined: Thu Jul 13, 2006 9:16 pm
Location: San Juan Capistrano, CA, USA
x 1

Re: setTextureName(textureName); not working

Post by trilobite »

Problem Confirmed.
I added some test code in the Sample_ShaderSystem in my build of Ogre 1.9.0
The results in this sample reflect the same problem I am having.
attempts to set a new texture name in a material are not reflected in the scene, and do not persist in the list.
Perhaps I am missing something really obvious. I hope so.
Anyways, I have included my testing code below...

TO ENGAGE THIS CODE, TOGGLE THE "POINT LIGHT" CHECK BOX IN THE UPPER LEFT CONTROL PANEL.

here is code:
in ShaderSystem.h

Code: Select all

protected:

	/******************************************************************/
	//test billboard texture swap
	Ogre::MaterialPtr	mpTestMaterial;
	Ogre::String	mstrTestMaterialName;
	Ogre::String	mstrOldTextureName, mstrNewTextureName;
	Ogre::BillboardSet *mpTestBillboard;
	//end test billboard texture swap
	/*****************************************************************/
in ShaderSystem.cpp
mods to two functions...

Code: Select all

//-----------------------------------------------------------------------
void Sample_ShaderSystem::createPointLight()
{
	Light*  light;
	Vector3 dir;

	light = mSceneMgr->createLight(POINT_LIGHT_NAME);
	light->setType(Light::LT_POINT);
	light->setCastShadows(false);
	dir.x = 0.5;
	dir.y = 0.0;
	dir.z = 0.0f;
	dir.normalise();
	light->setDirection(dir);
	light->setDiffuseColour(0.15, 0.65, 0.15);
	light->setSpecularColour(0.5, 0.5, 0.5);	
	light->setAttenuation(200.0, 1.0, 0.0005, 0.0);

	// create pivot node
	mPointLightNode = mSceneMgr->getRootSceneNode()->createChildSceneNode();
	
	/**********************************************************************************************/
	//test billboard texture swap
	// Create billboard set.
	mpTestBillboard = mSceneMgr->createBillboardSet();
	mpTestBillboard->setMaterialName("Examples/Flare3");
	mpTestBillboard->createBillboard(200, 100, 0)->setColour(light->getDiffuseColour());
	mpTestBillboard->setCastShadows(false);

	mPointLightNode->attachObject(mpTestBillboard);
	mPointLightNode->createChildSceneNode(Vector3(200, 100, 0))->attachObject(light);
	mstrOldTextureName = mpTestBillboard->getMaterial()->getBestTechnique()->getPass(0)->getTextureUnitState(0)->getTextureName();
	mstrNewTextureName = "ogrelogo.png";

	/*
	ORIGINAL CODE COMMENTED OUT FOR TESTING
	BillboardSet* bbs;

	// Create billboard set.
	bbs = mSceneMgr->createBillboardSet();
	bbs->setMaterialName("Examples/Flare3");
	bbs->createBillboard(200, 100, 0)->setColour(light->getDiffuseColour());
	bbs->setCastShadows(false);

	mPointLightNode->attachObject(bbs);
	mPointLightNode->createChildSceneNode(Vector3(200, 100, 0))->attachObject(light);
	*/
	// end test billboard texture swap
	/***************************************************************************************/
}
one more...

Code: Select all

void Sample_ShaderSystem::updateLightState(const String& lightName, bool visible)
{
	if (mSceneMgr->hasLight(lightName))
	{		
		// Case it is the point light,
		// toggle its visibility and billboard set visibility.
		if (lightName == POINT_LIGHT_NAME)
		{
			if (visible)
			{
				if (mPointLightNode->isInSceneGraph() == false)
				{
					mSceneMgr->getRootSceneNode()->addChild(mPointLightNode);

					/********************************************************************************************************************/
					//test billboard texture swap
					//this code gets the billboard's texture, confirms the material's texture name, then sets new texture name.
					//afterward, confirmation shows that the material's texture name has been changed.
					//but on the nextr cycle, the material's texture has reverted to the original. not reflecting any change.
					//there is no representation of the change in the scene.
					 if (mpTestBillboard)
					{
						mpTestMaterial = mpTestBillboard->getMaterial();
						if (!mpTestMaterial.isNull())
						{
							mstrOldTextureName = mpTestMaterial->getBestTechnique()->getPass(0)->getTextureUnitState(0)->getTextureName();
							mpTestMaterial->getBestTechnique()->getPass(0)->getTextureUnitState(0)->setTextureName(mstrNewTextureName);
						//	mstrNewTextureName = mstrOldTextureName;
							Ogre::String strConfirmation = mpTestMaterial->getBestTechnique()->getPass(0)->getTextureUnitState(0)->getTextureName();
							int i = 3;
						}
					}
					//end testbillboard texture swap
					/******************************************************************************************************************************/
				}
			 }
			else
			{
				if (mPointLightNode->isInSceneGraph() == true)
				{
					mSceneMgr->getRootSceneNode()->removeChild(mPointLightNode);
				}
			}	
			mSceneMgr->getLight(lightName)->setVisible(visible);
		}
		
		// Case it is the directional light,
		// toggle its visibility and billboard set visibility.
		else if (lightName == DIRECTIONAL_LIGHT_NAME)
		{
			SceneNode::ObjectIterator it = mDirectionalLightNode->getAttachedObjectIterator();

			while (it.hasMoreElements())  
			{
				MovableObject* o = it.getNext();
				o->setVisible(visible);
			}
		}

		// Spot light has no scene node representation.
		else
		{
			mSceneMgr->getLight(lightName)->setVisible(visible);
		}	

		RenderState* schemRenderState = mShaderGenerator->getRenderState(RTShader::ShaderGenerator::DEFAULT_SCHEME_NAME);
		
		int lightCount[3] = {0};

		// Update point light count.
		if (mSceneMgr->getLight(POINT_LIGHT_NAME)->isVisible())
		{
			lightCount[0] = 1;
		}

		// Update directional light count.
		if (mSceneMgr->getLight(DIRECTIONAL_LIGHT_NAME)->isVisible())
		{
			lightCount[1] = 1;
		}

		// Update spot light count.
		if (mSceneMgr->getLight(SPOT_LIGHT_NAME)->isVisible())
		{
			lightCount[2] = 1;
		}

		// Update the scheme light count.
		schemRenderState->setLightCount(lightCount);
		

		// Invalidate the scheme in order to re-generate all shaders based technique related to this scheme.
		mShaderGenerator->invalidateScheme(Ogre::RTShader::ShaderGenerator::DEFAULT_SCHEME_NAME);
	}
}
User avatar
Wolfmanfx
OGRE Team Member
OGRE Team Member
Posts: 1525
Joined: Fri Feb 03, 2006 10:37 pm
Location: Austria - Leoben
x 99
Contact:

Re: setTextureName(textureName); not working

Post by Wolfmanfx »

Hi,

I have reproduced the behaviour and can tell you now its not a bug :)
Here the status: It has nothing todo with OGRE 1.9 the problem is that you use RTSS and think every material change is tracked and updated - it is not!

Lets say you have a material with one technique after RTSS is enabled it created a second technique with the shaderbased stuff. But when you use now

Code: Select all

material->getBestTechnique()
You will not get the org. technqiue.

There are two possibities you can do:
1. Call mShaderGenerator->removeAllShaderBasedTechniques("Examples/Flare3"); which will remove all shaderbased techniques which were generated and injected by rtss. So you can
use material->getBestTechnique() again.
2. Use a technique by an index like this and call mShaderGenerator->invalidateMaterial after you made the changes to your org. technique.

Code: Select all

			   Ogre::MaterialPtr mat = Ogre::MaterialManager::getSingleton().getByName("Examples/Flare3");
			   if(mat->getTechnique(0)->getPass(0)->getTextureUnitState(0)->getTextureName() == "ogrelogo.png")
			   {
				   mat->getTechnique(0)->getPass(0)->getTextureUnitState(0)->setTextureName("flare_alpha.dds");
			   }
			   else
			   {
				   mat->getTechnique(0)->getPass(0)->getTextureUnitState(0)->setTextureName("ogrelogo.png");
			   }
			  mShaderGenerator->invalidateMaterial(RTShader::ShaderGenerator::DEFAULT_SCHEME_NAME, "Examples/Flare3");
But the line with mShaderGenerator->invalidateMaterial should always be called after you make changes to the org. material.

I hope you understand the situation - also keep in mind RTSS is optional you do not need to use if you provide all shaders yourself or use the fixed function pipeline (if possible).
User avatar
trilobite
Silver Sponsor
Silver Sponsor
Posts: 135
Joined: Thu Jul 13, 2006 9:16 pm
Location: San Juan Capistrano, CA, USA
x 1

Re: setTextureName(textureName); not working

Post by trilobite »

Thank you so much for your thoughtful reply and detailed explanation, Wolfmanfx.
Two previous versions of my application used RTSS without a problem, but I see now that it has become a problem.

Well, I think it's time to finally abandon RTSS and deal head-on with shaders... although I am not a shader programmer. I can learn from the many examples now available in the Ogre 1.9.0 source (which, btw were few in number six years ago when I first developed my main application).

In actuality, my application has only a few real needs for fine material operations. So I can deal with that.

Thanks again. Much appreciated.
User avatar
trilobite
Silver Sponsor
Silver Sponsor
Posts: 135
Joined: Thu Jul 13, 2006 9:16 pm
Location: San Juan Capistrano, CA, USA
x 1

Re: setTextureName(textureName); not working

Post by trilobite »

After more than a week of steady troubleshooting and workarounds, I am left with the following:

OGRE 1.9.0
1. cg shaders and RTShader System cannot coexist.
With RTShader System enabled, my cg shaders do not execute -- or if they DO execute, their results are not visible. The only way to display the results of my cg shaders is to disable the RTShader Sysytem. cg shaders and RTShaders are mutually exclusive.

2. Texture swaps execute in code but do not display on materials with associated cg shaders -- while RTShader System is running.
I tried the workaround suggested by Wolfmanfx:
1. Call mShaderGenerator->removeAllShaderBasedTechniques("Examples/Flare3"); which will remove all shaderbased techniques which were generated and injected by rtss. So you can
use material->getBestTechnique() again.
This workaround did not work since the material in question (with my cg shader) was never intentionally applied to the RTShader system by using the following:

Code: Select all

GenerateShaders(someEntity, colorSpecularSetting, rSpecularShinySetting);
Repeat: this was NOT used for the object whose material included my cg code.
This was confirmed because queries of the for the object's materials returned NULL.

Code: Select all

 mShaderGenerator->removeAllShaderBasedTechniques("myMaterial");
And even if I was able to swap the texture for the material in question (despite the code actually showing the the texture was in fact swapped -- but not displaying), I would still have the problem of the associated cg shader not displaying while the RTShader System existed.

the cg code in question is for my moon. Never used the RTShader system on that.
I have used the RTShader system in the past mainly on my terrain for nice specular effects and spotlights.

I have had a very frustrating couple of weeks Ogre 1.9.0 -- trying to hammer out solutions to this problem.
I have tried adapting a phong shader from Nvidia's fx Composer. Crazy hard to do and crazy hard to debug. No success.
I have tried a perpixel shader from Nvidia's cg Tutorial book (ch. 5). No luck. Material displays semi-transparent.
I have tried reverse engineering the actual shader written for my terrain material written to disc by the RTShader System. No luck. Material also displays semi-transparent.
I have tried using shaders from the Ogre examples. But with the myriad of delegates and cascading references, I found it so confusing and bloated that I gave up.

So, I would say, I have given it a solid attempt... with no success.
All I want to do is display phases of my moon (cg shader) and headlight cones on my terrain (perpixel shader).
Please pardon my rant.
Thank you, and Happy New Year.
User avatar
Wolfmanfx
OGRE Team Member
OGRE Team Member
Posts: 1525
Joined: Fri Feb 03, 2006 10:37 pm
Location: Austria - Leoben
x 99
Contact:

Re: setTextureName(textureName); not working

Post by Wolfmanfx »

Hi,

Sorry to hear but I suggest to drop RTSS for project is a better solution - but if you insist to use RTSS with your CG shader provide me repo case and I will look into it (best would be when you adapt one simple sample).
SufferinPup
Greenskin
Posts: 119
Joined: Tue Mar 02, 2010 11:09 pm
x 2

Re: setTextureName(textureName); not working

Post by SufferinPup »

I am having a similar issue with RTSS. I'm attempting to reload all materials on a mesh but getting the following exception the next frame this mesh is rendered:

Code: Select all

OGRE EXCEPTION(3:RenderingAPIException): Attempted to render using the fixed pipeline when it is disabled. in GLRenderSystem::_render at ..\..\..\RenderSystems\GL\src\OgreGLRenderSystem.cpp (line 2843)
Here is my code to reload materials. This works fine for fixed function pipeline in OpenGL so I assumed it was the correct way to do it.

Code: Select all

MaterialManager* mm = MaterialManager::getSingletonPtr();
ResourceGroupManager* rgm = ResourceGroupManager::getSingletonPtr();
for(int s=0;s<mesh->getNumSubMeshes();s++)
{
	SubMesh *smesh = mesh->getSubMesh(s);
	ResourcePtr r = mm->getByName(smesh->getMaterialName());			
	if(r.isNull() == false)
	{
		mm->remove(r);
		mm->parseScript(rgm->openResource(r->getOrigin(), r->getGroup()), r->getGroup());
		mm->load(r->getName(), r->getGroup());					
#ifdef USE_RTSHADER_SYSTEM
		mShaderGenerator->invalidateMaterial(Ogre::RTShader::ShaderGenerator::DEFAULT_SCHEME_NAME,r->getName());
#endif				
		smesh->setMaterialName(r->getName());
	}
}
I've also tried removeAllShaderBasedTechniques(r->getName()) and removeAllShaderBasedTechniques() passing nothing but I get the same exception next frame. I've tried all sorts of different orders to the functions too (when to invalidate, when to set material name, etc.), but nothing I do seems to help.

Any help is appreciated, I'm out of things to try.
Post Reply