Overriding shaders. The quick way.

Post those lines of code you feel like sharing or find what you require for your project here; or simply use them as tutorials.
Post Reply
Mel
Competition winner
Posts: 2292
Joined: Wed May 07, 2008 11:40 am
Location: Granada, Spain

Overriding shaders. The quick way.

Post by Mel »

This is in the "IVideoDriver.h" file, located in the include directory of Irrlicht.

Code: Select all

	struct SOverrideMaterial
	{
		//! The Material values
		SMaterial Material;
		//! Which values are taken for override
		/** OR'ed values from E_MATERIAL_FLAGS. */
		u32 EnableFlags;
		//! Set in which render passes the material override is active.
		/** OR'ed values from E_SCENE_NODE_RENDER_PASS. */
		u16 EnablePasses;
		//! Global enable flag, overwritten by the SceneManager in each pass
		/** The Scenemanager uses the EnablePass array and sets Enabled to
		true if the Override material is enabled in the current pass. */
		bool Enabled;

		//! Default constructor
		SOverrideMaterial() : EnableFlags(0), EnablePasses(0), Enabled(false) {}

		//! Apply the enabled overrides
		void apply(SMaterial& material)
		{
			if (Enabled)
			{


//This is something a bit bold, but it works for me
				material.MaterialType = Material.MaterialType;
//This is something a bit bold, but it works for me


				for (u32 i=0; i<32; ++i)
				{
					const u32 num=(1<<i);
					if (EnableFlags & num)
					{
						switch (num)
						{
						case EMF_WIREFRAME: material.Wireframe = Material.Wireframe; break;
						case EMF_POINTCLOUD: material.PointCloud = Material.PointCloud; break;
						case EMF_GOURAUD_SHADING: material.GouraudShading = Material.GouraudShading; break;
						case EMF_LIGHTING: material.Lighting = Material.Lighting; break;
						case EMF_ZBUFFER: material.ZBuffer = Material.ZBuffer; break;
						case EMF_ZWRITE_ENABLE: material.ZWriteEnable = Material.ZWriteEnable; break;
						case EMF_BACK_FACE_CULLING: material.BackfaceCulling = Material.BackfaceCulling; break;
						case EMF_FRONT_FACE_CULLING: material.FrontfaceCulling = Material.FrontfaceCulling; break;
						case EMF_FOG_ENABLE: material.FogEnable = Material.FogEnable; break;
						case EMF_NORMALIZE_NORMALS: material.NormalizeNormals = Material.NormalizeNormals; break;
						case EMF_ANTI_ALIASING: material.AntiAliasing = Material.AntiAliasing; break;
						case EMF_COLOR_MASK: material.ColorMask = Material.ColorMask; break;
						case EMF_USE_MIP_MAPS: material.UseMipMaps = Material.UseMipMaps; break;
						case EMF_BILINEAR_FILTER: material.TextureLayer[0].BilinearFilter = Material.TextureLayer[0].BilinearFilter; break;
						case EMF_TRILINEAR_FILTER: material.TextureLayer[0].TrilinearFilter = Material.TextureLayer[0].TrilinearFilter; break;
						case EMF_ANISOTROPIC_FILTER: material.TextureLayer[0].AnisotropicFilter = Material.TextureLayer[0].AnisotropicFilter; break;
						case EMF_TEXTURE_WRAP:
							material.TextureLayer[0].TextureWrapU = Material.TextureLayer[0].TextureWrapU;
							material.TextureLayer[0].TextureWrapV = Material.TextureLayer[0].TextureWrapV;
							break;
						}
					}
				}
			}
		}

	};
This way, overriding a shader becomes a matter of picking the overridematerial's Material, changing its MaterialType to the shader we need, enabling the Scene Render Passes we are interested in, the other parameters that currently were changed, and enabling the override.

A word of caution: You have to disable all the passes after when you don't need the override anymore! Or else, it may work unexpectedly.

This is a quick patch, and i don't give any explicit warranty for it.

After you change the material override, you have to recompile. Make sure you may step back the changes done if things get out of hands!!.
"There is nothing truly useless, it always serves as a bad example". Arthur A. Schmitt
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

Yes, support for more features in OverrideMaterial is planned. I did not include e.g. material type and textures, because of the major state confusion this can lead to. I need to double and triple check all consequences berfore this goes into the engine. Maybe you can simply bring up some most wishes features for this thing, just to see where it is used and which things are most urgent.
Mel
Competition winner
Posts: 2292
Joined: Wed May 07, 2008 11:40 am
Location: Granada, Spain

Post by Mel »

For the moment, i think the most urgent place where a material type override can be useful is in the shadowmap generation. Currently the way it was usually done (Xeffects for example) was to store all the shaders of the shadow casters inside a vector, render the shadowmap, and afterwards, restore the shaders, or even, change again the shaders for the shadow casters and receivers, and render the shadowmapping deferred. This way is faster and safer. And it really doesn't need you to change the textures. Although it is a fast fix, if you aren't careful with it you may mess things big time.

Overriding textures can be messy. The only reason i can think of when you want to override textures is to either replace a null texture with somethinng useful, or to place the shadowmap without having to set it in all the places that use it manually, perhaps. For instance, for a builtin shadowmap this materialType and texture override can be very useful.
"There is nothing truly useless, it always serves as a bad example". Arthur A. Schmitt
fmx

Post by fmx »

I dont know how XEffects does it, but in my projects I used a specialised Shadow SMaterial to render out the shadow pass objects, simply switching the materials at rendertime without worrying about screwing up the original material properties.

Personally, I would avoid Overriding materials in this way because it could potentially result in lots of copying per-node-per-Material-per-frame.
One alternative is to consider replacing the whole material system altogether with something more flexible...
stefbuet
Competition winner
Posts: 495
Joined: Sun Dec 09, 2007 4:13 pm
Location: france

Post by stefbuet »

XEffects loops all nodes and stores its material , switchs to another material to render shadow maps, renders all objects and switchs back to the initial material manually.
JLouisB
Posts: 67
Joined: Tue Jul 24, 2012 12:36 pm
Location: France

Re: Overriding shaders. The quick way.

Post by JLouisB »

Good patch, simple and useful.
Is it possible to integrate this into the trunk ?

You just have to add :

Code: Select all

material.MaterialType = Material.MaterialType;
in SOverrideMaterial.h l58 after the

Code: Select all

if (Enabled)
{
CuteAlien
Admin
Posts: 9648
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Re: Overriding shaders. The quick way.

Post by CuteAlien »

Hm, that's not enough as then it overrides the material type always when an OverrideMaterial is used. So needs some flag on top of that. And test if it works. But I suppose it should be fine.
Note that Irrlicht has also a way to swap materials now, so you can replace for example a standard materials by a shader (IVideoDriver.:swapMaterialRenderers). Just in case you need it for something like that.

edit: Actually everything not in E_MATERIAL_FLAGS is missing (not much and pretty esoteric stuff). Maybe should add an enum.
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
JLouisB
Posts: 67
Joined: Tue Jul 24, 2012 12:36 pm
Location: France

Re: Overriding shaders. The quick way.

Post by JLouisB »

Yes, so there is a patch where I have added a bool to set if the material type is copied or not :
https://www.dropbox.com/s/f1z265d10yssf ... patch?dl=0
This is tested it works well

I don't need any more than the material type for the moment, but it would be logical and useful that the other properties of the materials could be also copied.
If you are ok to integrate this feature, I can prepare and test a patch to manage also the other properties of the material (with an enum similar to the flags system), just tell me.

I didn't know about swapMaterialRenderers, thanks, but using the overrideMaterial makes more sense in my case
CuteAlien
Admin
Posts: 9648
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Re: Overriding shaders. The quick way.

Post by CuteAlien »

I've implemented it a bit different. I also got a use-case actually (for z-prepass) and a single flag was still not enough as I want to override alpha and non alpha material-types differently. So now it's an array (in svn r5859).

And yeah, swapMaterialRenderers also didn't work for me in this case because with swapping around I can never replace several materials by a single one. But it's quite useful in other situations (re-loading and replacing shaders, or replacing all fixed-function materials by shaders without going over all nodes).
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
JLouisB
Posts: 67
Joined: Tue Jul 24, 2012 12:36 pm
Location: France

Re: Overriding shaders. The quick way.

Post by JLouisB »

Cool, thank you for this quick solution :)
CuteAlien
Admin
Posts: 9648
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Re: Overriding shaders. The quick way.

Post by CuteAlien »

Np, to tell truth - I just needed this today as well :-)

edit: What I also want is to be able to set active textures outside of materials. SOverrideMaterial is some bad hack around that, but restricted to max textures allowed by SMaterial instead of max textures allowed by graphic card. Drivers should have a function for that, seriously missing feature right now.
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
Post Reply