[not a bug]EMT_LIGHTMAP not works for EDT_DIRECT3D8/9

You discovered a bug in the engine, and you are sure that it is not a problem of your code? Just post it in here. Please read the bug posting guidelines first.
Post Reply
greenya
Posts: 1012
Joined: Sun Jan 21, 2007 1:46 pm
Location: Ukraine
Contact:

[not a bug]EMT_LIGHTMAP not works for EDT_DIRECT3D8/9

Post by greenya »

Hello!

The EMT_LIGHTMAP material type not works for Drirect3D renderer.

Lets write the code:

Code: Select all

#include "../irrlicht-svn/trunk/include/irrlicht.h"
#pragma comment(lib, "../irrlicht-svn/trunk/lib/Win32-visualstudio/Irrlicht.lib")

using namespace irr;
using namespace core;

int main()
{
	// irr device and pointers
	IrrlichtDevice *irrDevice = createDevice(video::EDT_DIRECT3D9);
	video::IVideoDriver *irrVideo = irrDevice->getVideoDriver();
	scene::ISceneManager *irrScene = irrDevice->getSceneManager();

	// SENSE CODE IS HERE
	// {{{{{{{{{{{{{{{{{{{{

	scene::ISceneNode *n1 = irrScene->addCubeSceneNode(100);
	n1->setPosition(vector3df(0,0,200));
	n1->setMaterialType(video::EMT_LIGHTMAP);
	n1->setMaterialTexture(0, irrVideo->getTexture("media/diffuseMap.jpg"));
	n1->setMaterialTexture(1, irrVideo->getTexture("media/lightMap.jpg"));
	n1->setMaterialFlag(video::EMF_LIGHTING, false);
	
	irrScene->addCameraSceneNodeFPS();

	// }}}}}}}}}}}}}}}}}}}}

	// show time!
	while(irrDevice->run())
	if (irrDevice->isWindowActive())
	{
		irrVideo->beginScene(true, true, video::SColor(0x204060));
		irrScene->drawAll();
		irrVideo->endScene();
	}

	// drop time!
	irrDevice->drop();

	return 0;
}
This produces next result (EDT_DIRECT3D8/9):
Image

Same code with EDT_OPENGL produces:
Image

P.S.:
Textures used in the code:
diffuseMap.jpg is a copy of media/detailmap3.jpg
lightMap.jpg is:
Image
Bersi
Posts: 53
Joined: Tue Sep 04, 2007 8:23 pm

Post by Bersi »

Same for me but the problem occurs in OpenGL also. Found out that the 4 corner-pixels produce the color.

Example:

All 4 corners are black: lightmap is full black
2 corners are black and 2 are white: lightmap is full grey
2 are red and 2 are green: lightmap is yellow

and so on.


The rest of the lightmap texture doesn't affect the appearance in the game. I use irrlicht 1.3.1.


@greenya: Try to set the first pixel to red and you will see what I mean. ;)
greenya
Posts: 1012
Joined: Sun Jan 21, 2007 1:46 pm
Location: Ukraine
Contact:

Post by greenya »

Bersi wrote: @greenya: Try to set the first pixel to red and you will see what I mean. ;)
Yes, you right.

Direct3D
Image

OpenGL
Image
Bersi
Posts: 53
Joined: Tue Sep 04, 2007 8:23 pm

Post by Bersi »

Perhaps the corners have something to do with the 4 vertices of a quad. But this is only a guess.
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

lightmaps need a second set of texture coords (vertex2T). OpenGL uses the first set of coords if no second set exists. This will have to be added to the d3d drivers, too.
Bersi
Posts: 53
Joined: Tue Sep 04, 2007 8:23 pm

Post by Bersi »

How can I add a second set of texture coords?
Bersi
Posts: 53
Joined: Tue Sep 04, 2007 8:23 pm

Post by Bersi »

Ok it works now. You have to use video::S3DVertex2TCoords instead of video::S3DVertex and set the second set of TCoords. And it only works with irrlicht 1.4. ;)
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

No, lightmaps also worked before. 1.4 also has some initial support for resuing the first set of texture coords for the second layer (e.g. for detail map, which already worked for d3d in earlier releases IIRC).
greenya
Posts: 1012
Joined: Sun Jan 21, 2007 1:46 pm
Location: Ukraine
Contact:

Post by greenya »

can anybody write an additional piece of code (to the code i provided at the top of the thread) to get light maps working in d3d ?
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

The Cube scene node is simply not really a good example for this. It does not support second set of texture coords, nor access to the meshbuffers. So you have to replace the mesh or change the cube scene node's code.
Bersi
Posts: 53
Joined: Tue Sep 04, 2007 8:23 pm

Post by Bersi »

Here is an example. It's a simple wall oder quad scene node I am using at my current project.

Code: Select all

class SceneNodeWall : public scene::ISceneNode
	{
	private:
		video::S3DVertex2TCoords Vertices[4];
		video::SMaterial Material;
		core::aabbox3d<f32> Box;
		
	public:
		SceneNodeWall(scene::ISceneNode* parent, scene::ISceneManager* mgr, s32 id, Ambersun::byte X, Ambersun::byte Y, Ambersun::byte Width, Ambersun::AmberDirection Direction)
		: scene::ISceneNode(parent, mgr, id)
		{
			Material.Wireframe = false;
			Material.Lighting = true;
			Material.MaterialType = video::EMT_SOLID;
			
			Vertices[0] = video::S3DVertex2TCoords(0.0f, 0.0f, 64.0f,				0.0f,0.0f,1.0f, video::SColor(255,255,255,255), 0.0f,0.0f, 0.0f,0.0f);
			Vertices[1] = video::S3DVertex2TCoords(Width * -64.0f, 0.0f, 64.0f,		0.0f,0.0f,1.0f, video::SColor(255,255,255,255), 1.0f,0.0f, 1.0f,0.0f); 
			Vertices[2] = video::S3DVertex2TCoords(Width * -64.0f, -128.0f, 64.0f,	0.0f,0.0f,1.0f, video::SColor(255,255,255,255), 1.0f,1.0f, 1.0f,1.0f);
			Vertices[3] = video::S3DVertex2TCoords(0.0f, -128.0f, 64.0f,			0.0f,0.0f,1.0f, video::SColor(255,255,255,255), 0.0f,1.0f, 0.0f,1.0f);

			setAutomaticCulling(scene::EAC_FRUSTUM_BOX);
			Box.reset(Vertices[0].Pos);
			for (s32 i=1; i<4; ++i)
				Box.addInternalPoint(Vertices[i].Pos);

			float PosX = X * (-64.0f);
			float PosY = 0.0f;
			float PosZ = Y * (64.0f);

			switch(Direction)
			{
			case Ambersun::AmberDown:
			default:
				setPosition(core::vector3d<float>(PosX,PosY,PosZ));
				break;
			case Ambersun::AmberUp:
				setRotation(core::vector3d<float>(180.0f, 0.0f, 180.0f));
				setPosition(core::vector3d<float>(PosX - 64.0f, PosY, PosZ + 64.0f));
				break;
			case Ambersun::AmberRight:
				setRotation(core::vector3d<float>(180.0f, 270.0f, 180.0f));
				setPosition(core::vector3d<float>(PosX, PosY, PosZ + 64.0f));
				break;
			case Ambersun::AmberLeft:
				setRotation(core::vector3d<float>(180.0f, 90.0f, 180.0f));
				setPosition(core::vector3d<float>(PosX - 64.0f, PosY, PosZ));
				break;
			}

			setVisible(true);
		}
		
		virtual void OnRegisterSceneNode()
		{
			if(IsVisible)
				SceneManager->registerNodeForRendering(this);
			
			ISceneNode::OnRegisterSceneNode();
		}
		
		virtual void render()
		{
			u16 indices[] = { 0,1,2, 2,3,0};
			video::IVideoDriver* driver = SceneManager->getVideoDriver();
			
			driver->setMaterial(Material);
			driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
			driver->drawIndexedTriangleList(&Vertices[0], 4, &indices[0], 2);
		}
		
		virtual const core::aabbox3d<f32>& getBoundingBox() const
		{
			return Box;
		}
		
		virtual u32 getMaterialCount()
		{
			return 1;
		}
		
		virtual video::SMaterial& getMaterial(u32 i)
		{
			return Material;
		}
		
		void setMaterialTexture(video::ITexture* Texture)
		{
			Material.TextureLayer[0].Texture = Texture;
		}

		void setLightmapTexture(video::ITexture* Texture)
		{
			Material.MaterialType = video::EMT_LIGHTMAP;
			Material.TextureLayer[1].Texture = Texture;
			Material.TextureLayer[1].TextureWrap = video::ETC_CLAMP;
		}
	};

The important code is inside the constructor where the vertices get their infos.
greenya
Posts: 1012
Joined: Sun Jan 21, 2007 1:46 pm
Location: Ukraine
Contact:

Post by greenya »

Bersi, thanks for the example.
But, as i understand, t-coordinates are hardcoded -- so it is only usable for box-like object (the wall -- good example).

but, if i have some complex mapping generated by an editor -- how can i make working lightmaps working with direct3d8/9 renderers?

Simply:
referring to my code above,
what should i add to the created node after following lines: (?)

Code: Select all

   ...

   scene::ISceneNode *n1 = irrScene->addCubeSceneNode(100);
   n1->setPosition(vector3df(0,0,200));
   n1->setMaterialType(video::EMT_LIGHTMAP);
   n1->setMaterialTexture(0, irrVideo->getTexture("media/diffuseMap.jpg"));
   n1->setMaterialTexture(1, irrVideo->getTexture("media/lightMap.jpg"));
   n1->setMaterialFlag(video::EMF_LIGHTING, false);

   ...
Post Reply