Switching on dynamic lighting for EMT_SOLID_2_LAYER?

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!
Post Reply
Robat
Posts: 10
Joined: Tue May 16, 2006 7:51 am
Location: Hamburg

Switching on dynamic lighting for EMT_SOLID_2_LAYER?

Post by Robat »

Hi,

I have looked into the source code of the file C3D9MaterialRenderer.h and wanted to modify the shader properties for the material EMT_SOLID_2_LAYER. I want to have the material being lit by dynamic light. By default, the material ignores the material flag EMF_LIGHTING = true. The material blends to textures based on the vertex alpha of the first texture. The source code that comes with irrlicht is the following:

Code: Select all

//! Solid 2 layer material renderer
class CD3D9MaterialRenderer_SOLID_2_LAYER : public CD3D9MaterialRenderer
{
public:

	CD3D9MaterialRenderer_SOLID_2_LAYER(IDirect3DDevice9* p, video::IVideoDriver* d)
		: CD3D9MaterialRenderer(p, d) {}

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

			pID3DDevice->SetTextureStageState( 1, D3DTSS_TEXCOORDINDEX, 0);
			pID3DDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_BLENDDIFFUSEALPHA);

			pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);	
			
		}

		services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
	}
};
I wanted to add the following line according to the directx9 documentation, but it didn't have any effect. Probably because this parameter is true by default.

Code: Select all

//added by Robert
			
pID3DDevice->SetRenderState(D3DRS_LIGHTING, TRUE);
Does anyone of you know how I could switch on dynamic light?
In Spain rain falls mainly on the plain.
Robat
Posts: 10
Joined: Tue May 16, 2006 7:51 am
Location: Hamburg

Post by Robat »

Ok, I have investigated a bit and it seems quite clear to me now:

The first texture layer of the material uses the following params:

Code: Select all

pID3DDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
			pID3DDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
			pID3DDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE); //takes dynamic lighting into account
			pID3DDevice->SetTextureStageState(0, D3DTSS_ALPHAOP,  D3DTOP_DISABLE);
modulating both the diffuse color of the mesh (incorporates dynamic lighting) and the texture color per texel.

When I set a second texture layer that uses the vertex alpha for blending, it doesn't use dynamic lighting for its texture, so the pure texel color of texture2 is replacing the "shadowed" parts of the mesh. :( Hoped I would have found a solution.

Code: Select all

pID3DDevice->SetTextureStageState( 1, D3DTSS_TEXCOORDINDEX, 0);
			pID3DDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_BLENDDIFFUSEALPHA);
In Spain rain falls mainly on the plain.
Robat
Posts: 10
Joined: Tue May 16, 2006 7:51 am
Location: Hamburg

Post by Robat »

Got it, adding a third layer helps: :D

Code: Select all

			pID3DDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
			pID3DDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);

			pID3DDevice->SetTextureStageState( 1, D3DTSS_TEXCOORDINDEX, 0);
			pID3DDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_BLENDDIFFUSEALPHA);
			
			pID3DDevice->SetTextureStageState(2, D3DTSS_TEXCOORDINDEX, 0);
			pID3DDevice->SetTextureStageState(2, D3DTSS_COLOROP, D3DTOP_MODULATE);
			pID3DDevice->SetTextureStageState(2, D3DTSS_COLORARG1, D3DTA_CURRENT);
			pID3DDevice->SetTextureStageState(2, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
If anyone was interested in this topic, please leave a comment :)
In Spain rain falls mainly on the plain.
JeffL
Competition winner
Posts: 14
Joined: Wed Dec 14, 2005 10:42 am
Location: San Jose, CA
Contact:

Post by JeffL »

Interesting. Thanks for the info. Do you know why the third layer helped?
Robat
Posts: 10
Joined: Tue May 16, 2006 7:51 am
Location: Hamburg

Post by Robat »

I think that the vertexalpha blending mode in the second layer only accepts two parameters or colorargs, first one is the result from layer 1 (texture 1), second parameter is the texture from layer 2, blending mode vertex alpha. If I wanted to add dynamic lighting (shadowing the blended two textures with a light), I would need a third parameter for the same layer. But this is not possible by default.
So I add a third layer where I blend the result from layer two (param: D3DTA_CURRENT) with the diffuse color of the dynamic light :).

That's it, I think :).

Robert
In Spain rain falls mainly on the plain.
Robat
Posts: 10
Joined: Tue May 16, 2006 7:51 am
Location: Hamburg

Post by Robat »

The preceding code worked for me when I modified the existing material EMT_SOLID_2_LAYER inside the CD3D9MaterialRenderer.h. Now I tried to add my own material to the materialtype enumeration, modifying the following files:

SMaterial.h
CD3D9MaterialRenderer.h

Afterwards I recompiled the source and replaced the irrlicht.dll.

I tried to follow the documentation, but I got an issue when I implemented the following code into my terrain.cpp-file. Sorry, if this is more of a programming question, but does anybody know how I can declare the class CD3D9MaterialRenderer_SOLID_2_LAYER_DIFFUSE* in the file terrain.cpp? This is the only error I get.

Code: Select all

// add our material renderer 
			SExposedVideoData dat = pDriver->getExposedVideoData(); 
			IDirect3DDevice9* pID3DDevice = dat.D3D9.D3DDev9; 
			CD3D9MaterialRenderer_SOLID_2_LAYER_DIFFUSE* myMat = new CD3D9MaterialRenderer_SOLID_2_LAYER_DIFFUSE( pID3DDevice, pDriver ); 
			s32 myMaterialType = pDriver->addMaterialRenderer(myMat); 
			myMat->drop(); 

			mTerrainSceneNode->getMaterial(0).MaterialType = EMT_SOLID_2_LAYER_DIFFUSE;


In Spain rain falls mainly on the plain.
Post Reply