Creating custom material renderer

You are an experienced programmer and have a problem with the engine, shaders, or advanced effects? Here you'll get answers.
No questions about C++ programming or topics which are answered in the tutorials!
arras
Posts: 1622
Joined: Mon Apr 05, 2004 8:35 am
Location: Slovakia
Contact:

Creating custom material renderer

Post by arras »

I am trying to create custom material renderer. Since it's the firsth time, just to get started somewhere, I try to coppy one of the Irrlicht own material renderers.
Here's code:

Code: Select all

class MyMaterialRenderer : public video::IMaterialRenderer
{
public:

	MyMaterialRenderer(IDirect3DDevice9* d3ddev, video::IVideoDriver* driver)
		: pID3DDevice(d3ddev), Driver(driver)
	{
	}

	~MyMaterialRenderer()
	{
	}

	virtual bool setVariable(bool vertexShader, const c8* name, const f32* floats, int count)
	{
		os::Printer::log("Invalid material to set variable in.");
		return false;
	}

	virtual void OnSetMaterial(video::SMaterial& material, const video::SMaterial& lastMaterial,
		bool resetAllRenderstates, video::IMaterialRendererServices* services)
	{
		if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates)
		{
			pID3DDevice->SetTextureStageState (0, D3DTSS_COLOROP, D3DTOP_MODULATE);
			pID3DDevice->SetTextureStageState (0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
			pID3DDevice->SetTextureStageState (0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
			pID3DDevice->SetTextureStageState (0, D3DTSS_ALPHAOP,  D3DTOP_SELECTARG1);
			pID3DDevice->SetTextureStageState (0, D3DTSS_ALPHAARG1,  D3DTA_DIFFUSE);

			pID3DDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
			pID3DDevice->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE);

			pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
			pID3DDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);
			pID3DDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
		}

		material.ZWriteEnable = false;
		services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
	}

	virtual bool isTransparent()
	{
		return true;
	}

protected:

	IDirect3DDevice9* pID3DDevice;
	video::IVideoDriver* Driver;
};
As you see it is just a coppy of CD3D9MaterialRenderer_TRANSPARENT_VERTEX_ALPHA.

However if I try compile code, I get bunch of compile error messages which relate to IDirect3DDevice9 as it seems to be undefined for compiler.
37 main.cpp invalid use of undefined type `struct IDirect3DDevice9'
10 irrlicht-1.3\include\SExposedVideoData.h forward declaration of `struct IDirect3DDevice9'
37 main.cpp `D3DTSS_COLOROP' undeclared (first use this function)
37 main.cpp `D3DTOP_MODULATE' undeclared (first use this function)
...and so on...
Howe to correct it? Is it defined in d3d9.h file? ...If yes where can I find that file?
FuzzYspo0N
Posts: 914
Joined: Fri Aug 03, 2007 12:43 pm
Location: South Africa
Contact:

Post by FuzzYspo0N »

You need the directX SDK,

And you need to set your project up to see the include files for Direct3D

Thats what it means by d3d9.h (it comes with DX sdk)

or am i wrong is it something else?
xDan
Competition winner
Posts: 673
Joined: Thu Mar 30, 2006 1:23 pm
Location: UK
Contact:

Post by xDan »

Unless you actually want to use direct3d, then you only need to overload the methods in the IMaterialRenderer class. I.e. you don't need "IDirect3DDevice9* pID3DDevice; " or that constructor etc...
arras
Posts: 1622
Joined: Mon Apr 05, 2004 8:35 am
Location: Slovakia
Contact:

Post by arras »

Well if I dont want to use DirectX then there are two possibilities: software renderer and OpenGL. I took second. I did the same as firsth time, just coppied some code from Irrlicht OGL material renderer and compiled:

Code: Select all

class MyMaterialRenderer : public video::IMaterialRenderer
{
public:

	MyMaterialRenderer(video::COpenGLDriver* driver)
		: Driver(driver)
	{
	}
	
	virtual void OnSetMaterial(video::SMaterial& material, const video::SMaterial& lastMaterial,
		bool resetAllRenderstates, video::IMaterialRendererServices* services)
	{
		Driver->disableTextures(1);
		Driver->setTexture(0, material.Textures[0]);
		if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates)
		{
			glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);

			glDisable(GL_BLEND);
			glDisable(GL_ALPHA_TEST);
		}
		Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
	}

protected:

	video::COpenGLDriver* Driver;
};
Again error, this time compiler does not know nothing about COpenGLDriver. Does it mean COpenGLDriver.h and .cpp are not part of Irrlicht.dll?

Am I doing something wrong?
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

Why don't you use a generic IVideoDriver? The methods you use are all exposed via the interface. And gl* functions are accessible from gl.h. Only extensions would require access to the OpenGL driver.
xDan
Competition winner
Posts: 673
Joined: Thu Mar 30, 2006 1:23 pm
Location: UK
Contact:

Post by xDan »

Well if I dont want to use DirectX then there are two possibilities: software renderer and OpenGL.
Sorry, I meant as I think Hybrid is saying. I.e. not using Opengl, direct3d or software specific stuff, just use methods of the IVideoDriver from device->getVideoDriver().

Contents of COpenGLDriver is internal irrlicht stuff. You'll notice "COpenGLDriver* Driver" is not a part of the IMaterialRenderer class.
arras
Posts: 1622
Joined: Mon Apr 05, 2004 8:35 am
Location: Slovakia
Contact:

Post by arras »

Excuse me, I am just trying to learn howe to extend Irrlicht with custom material. I dont realy get something here probably so I would realy appreciate your help (or anybody else).

From what I got out of API I concluded that:

Firsth I need to derive a class from IMaterialRenderer and override the methods I want.

Second use IVideoDriver::addMaterialRenderer() function to add that material renderer to videodriver.

Third set the MaterialType member of the SMaterial structure to the value returned by function above.

To get idea of howe such derived material renderer should look like I took look at Irrlicht source (since there is no tutorial nor any info in API). Namely CD3D8MaterialRenderer.h, CD3D9MaterialRenderer.h, COpenGLMaterialRenderer.h, CSoftware2MaterialRenderer.h. To get started I just tryed to create custom material renderer as a coppy of some material renderers found in those files ...with unfortunate results been posted here already.

Now afther looking at the interface of IVideoDriver, I have no idea howe can I create custom material using IVideoDriver where in its interface I can get acces to methods I need.

Can you point me in to right direction?

Please be patient with me if you can :wink:
arras
Posts: 1622
Joined: Mon Apr 05, 2004 8:35 am
Location: Slovakia
Contact:

Post by arras »

xDan >> are you trying to explain me that to create custom material (let say material which can take 3 textures and blend them together using RGB components of vertex color) I dont need DX or OGL specific stuff and I just can use generic IVideoDriver somehowe?
Howe?

Yes I noticed that IMaterialRenderer does not contain any drivers but as I understand IMaterialRenderer is not realy used to render something. As I understand it's just part of framework which provide some common functions just like ISceneNode do.
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

Ok, you're right. The methods used are not exposed. So it wouldn't help here. You'll either have to copy the header files to the include directory or put your material into the library.
So for a first test: Use the code you already have and add it to the Irrlicht project/makefile. Also add the addMaterialRenderer for your material into the Irrlicht code and recompile the library. I guess we need a proper documentation of this process. but I don't think that it will be easily possible to add new materials without touching Irrlicht code and recompiling the library.
arras
Posts: 1622
Joined: Mon Apr 05, 2004 8:35 am
Location: Slovakia
Contact:

Post by arras »

Hmmm ...that's what I wanted to avoid. I was thinking to create new material for my terrain node and I dont think all those who would be interested to use it would be willing to recompile dll. But thanks a lott anyway, I'll try it.
Also add the addMaterialRenderer for your material into the Irrlicht code and recompile the library
I am not realy understanding whole Irrlicht structure so just to be sure ...do you mean COpenGLDriver::createMaterialRenderers() or CD3D9Driver::createMaterialRenderers() function with addAndDropMaterialRenderer?

[EDIT:] Aslo, howe to set such material type to SMaterial of some node, Irrlicht do it using MATERIAL_TYPE enumeration ...this would require some more changes to original Irrlicht code ...right?
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

Yes, that's right. I think you have all things mentioned.
However, now that I think about it: The shader materials allow for some flexibility and material addition in the user-space. Maybe you can find some hints there.
arras
Posts: 1622
Joined: Mon Apr 05, 2004 8:35 am
Location: Slovakia
Contact:

Post by arras »

That means to learn shaders. Arrr ...am not the youngest one anymore, thought I can peacefuly finish my days without carreing bout those pestsky little critters :?
Sean H.
Posts: 21
Joined: Mon Aug 06, 2007 12:25 am

Post by Sean H. »

arras it's not that hard to add new materials. But you will need to make changes to the irrlicht dll. you will also have to decide whether you want your material to support opengl, d3d, or both. I suggest using opengl as it can be used for mac and linux as well.

Take a look at source/irrlicht/COpenGLMaterialRenderer.h. Then take a look at void COpenGLDriver::createMaterialRenderers() in source/irrlicht/COpenGLDriver.cpp. That should put you in the right direction.
arras
Posts: 1622
Joined: Mon Apr 05, 2004 8:35 am
Location: Slovakia
Contact:

Post by arras »

Thanks Sean H. I am already on that direction, just read my second to last post. Problem is:

Howe to set new material type to SMaterial of some scene node once I add it in to COpenGLDriver. Normaly you use MATERIAL_TYPE enumeration. Do I need to add another enumeration for may custom material? ...this would require modifying some more files. Enumeration is just simple triger, there must be code which sets right material based on that enum at the video driver.

I was thinking just to add custom material to Irrlicht.dll as a single class. Then use IVideoDriver::addMaterialRenderer() to add it.

But even if it would work, problem is that I would need to recompile whole Irrlicht.dll each time I change my material. And since I just started to learn this stuff, I would of course need to change code each few seconds since its extremly unprobable that I will get my material runing as I need at the firsth try.

If you have some ideas or much better if you already made your own custom material and managed to add it to Irrlicht, I would be very thankfull if you would be willing to share you experience with me (and all who read this).
vitek
Bug Slayer
Posts: 3919
Joined: Mon Jan 16, 2006 10:52 am
Location: Corvallis, OR

Post by vitek »

No, you don't need to recompile the Irrlicht.dll every time. You can create your material renderer outside the engine. You should read the documentation for IVideoDriver::addMaterialRenderer(). Note that there will be a cast involved...

Travis
Post Reply