Texture Splatting Effect Without Pixel Shader

Post those lines of code you feel like sharing or find what you require for your project here; or simply use them as tutorials.
locosoftware
Posts: 15
Joined: Sat Mar 08, 2008 3:15 pm
Location: Shanghai

Texture Splatting Effect Without Pixel Shader

Post by locosoftware »

First I got an idea with http://downloads.gamedev.net/features/h ... ngDemo.zip in Direct3D 9.

The Screenshot is here:
http://lcgamestudio.spaces.live.com/pho ... 2D45F!120/

And can download code:

http://uploader.polorix.net//files/1431 ... atting.zip
and modified engine code here:
http://uploader.polorix.net//files/1431 ... 20Code.zip

And I want to implement it with Irrlicht and without pixel shader.
Here is the code:
1. I added the CD3D9MaterialRenderer_SPLATTING class in CD3D9MaterialRenderer.h file:

Code: Select all

//! For texture splatting without pixelshader
class CD3D9MaterialRenderer_SPLATTING : public CD3D9MaterialRenderer
{
public:

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

	virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial,
		bool resetAllRenderstates, IMaterialRendererServices* services)
	{		
		// Do some normal state settings
		services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);


		if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates)
		{
			pID3DDevice->SetRenderState(D3DRS_LIGHTING, FALSE);
			pID3DDevice->SetRenderState(D3DRS_ZENABLE, TRUE);

			// Allow multiple passes to blend together correctly
			pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
			pID3DDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
			pID3DDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);

			pID3DDevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
			pID3DDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
			pID3DDevice->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR);
			// Prevent some ugliness with the alphamaps
			pID3DDevice->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
			pID3DDevice->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);

			pID3DDevice->SetSamplerState(1, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
			pID3DDevice->SetSamplerState(1, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
			pID3DDevice->SetSamplerState(1, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR);

			pID3DDevice->SetSamplerState(2, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
			pID3DDevice->SetSamplerState(2, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
			pID3DDevice->SetSamplerState(2, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR);

			pID3DDevice->SetSamplerState(3, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
			pID3DDevice->SetSamplerState(3, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
			pID3DDevice->SetSamplerState(3, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR);

			pID3DDevice->SetSamplerState(4, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
			pID3DDevice->SetSamplerState(4, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
			pID3DDevice->SetSamplerState(4, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR);

			// Alphamap: take the alpha from the alphamap, we don't care about the color
			pID3DDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
			pID3DDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);

			// Texture: take the color from the texture, take the alpha from the previous stage
			pID3DDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
			pID3DDevice->SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_TEXTURE);
			pID3DDevice->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
			pID3DDevice->SetTextureStageState(1, D3DTSS_ALPHAARG1, D3DTA_CURRENT);
		}
	}
};

2: Modify the CD3D9Driver::createMaterialRenderers() in CD3D9Driver.cpp:

Code: Select all

{
	// create D3D9 material renderers

	addAndDropMaterialRenderer(new CD3D9MaterialRenderer_SOLID(pID3DDevice, this));

	addAndDropMaterialRenderer(new CD3D9MaterialRenderer_SOLID_2_LAYER(pID3DDevice, this));


	// add the same renderer for all lightmap types

	CD3D9MaterialRenderer_LIGHTMAP* lmr = new CD3D9MaterialRenderer_LIGHTMAP(pID3DDevice, this);
	addMaterialRenderer(lmr); // for EMT_LIGHTMAP:
	addMaterialRenderer(lmr); // for EMT_LIGHTMAP_ADD:
	addMaterialRenderer(lmr); // for EMT_LIGHTMAP_M2:
	addMaterialRenderer(lmr); // for EMT_LIGHTMAP_M4:
	addMaterialRenderer(lmr); // for EMT_LIGHTMAP_LIGHTING:
	addMaterialRenderer(lmr); // for EMT_LIGHTMAP_LIGHTING_M2:
	addMaterialRenderer(lmr); // for EMT_LIGHTMAP_LIGHTING_M4:
	lmr->drop();

	// add remaining fixed function pipeline material renderers

	addAndDropMaterialRenderer(new CD3D9MaterialRenderer_DETAIL_MAP(pID3DDevice, this));
	addAndDropMaterialRenderer(new CD3D9MaterialRenderer_SPHERE_MAP(pID3DDevice, this));
	addAndDropMaterialRenderer(new CD3D9MaterialRenderer_REFLECTION_2_LAYER(pID3DDevice, this));
	addAndDropMaterialRenderer(new CD3D9MaterialRenderer_TRANSPARENT_ADD_COLOR(pID3DDevice, this));
	addAndDropMaterialRenderer(new CD3D9MaterialRenderer_TRANSPARENT_ALPHA_CHANNEL(pID3DDevice, this));
	addAndDropMaterialRenderer(new CD3D9MaterialRenderer_TRANSPARENT_ALPHA_CHANNEL_REF(pID3DDevice, this));
	addAndDropMaterialRenderer(new CD3D9MaterialRenderer_TRANSPARENT_VERTEX_ALPHA(pID3DDevice, this));
	addAndDropMaterialRenderer(new CD3D9MaterialRenderer_TRANSPARENT_REFLECTION_2_LAYER(pID3DDevice, this));

	// add normal map renderers

	s32 tmp = 0;
	video::IMaterialRenderer* renderer = 0;

	renderer = new CD3D9NormalMapRenderer(pID3DDevice, this, tmp,
		MaterialRenderers[EMT_SOLID].Renderer);
	renderer->drop();

	renderer = new CD3D9NormalMapRenderer(pID3DDevice, this, tmp,
		MaterialRenderers[EMT_TRANSPARENT_ADD_COLOR].Renderer);
	renderer->drop();

	renderer = new CD3D9NormalMapRenderer(pID3DDevice, this, tmp,
		MaterialRenderers[EMT_TRANSPARENT_VERTEX_ALPHA].Renderer);
	renderer->drop();


	// add parallax map renderers

	renderer = new CD3D9ParallaxMapRenderer(pID3DDevice, this, tmp,
		MaterialRenderers[EMT_SOLID].Renderer);
	renderer->drop();

	renderer = new CD3D9ParallaxMapRenderer(pID3DDevice, this, tmp,
		MaterialRenderers[EMT_TRANSPARENT_ADD_COLOR].Renderer);
	renderer->drop();

	renderer = new CD3D9ParallaxMapRenderer(pID3DDevice, this, tmp,
		MaterialRenderers[EMT_TRANSPARENT_VERTEX_ALPHA].Renderer);
	renderer->drop();


	// add basic 1 texture blending
	addAndDropMaterialRenderer(new CD3D9MaterialRenderer_ONETEXTURE_BLEND(pID3DDevice, this));



	//===========================Added by Locosoftware=================================
	// add texture splatting (Added by Locosoftware)
	addAndDropMaterialRenderer(new CD3D9MaterialRenderer_SPLATTING(pID3DDevice, this));
	//=================================================================================
}
3: Add a new enumeration EMT_TEXTURE_SPLATTING at last in E_MATERIAL_TYPE: (file: ematerialtypes.h)

Code: Select all

	enum E_MATERIAL_TYPE
	{
		//! Standard solid material. Only first texture is used, which is
		//! supposed to be the diffuse material.
		EMT_SOLID = 0,
........
........
........
		//===========================Added by Locosoftware=================================
		//! Texture splatting effect without pixelshader. The vertex format must include 
		//! two texture coordinates. (Only for Direct3D 9 and 8 now)
		EMT_TEXTURE_SPLATTING ,
		//=================================================================================


		//! This value is not used. It only forces this enumeration to compile in 32 bit.
		EMT_FORCE_32BIT = 0x7fffffff
	};
And finally add string "texture_splatting" in array sBuiltInMaterialTypeNames (file: ematerialtypes.h)

Code: Select all

	//! Array holding the built in material type names
	const char* const sBuiltInMaterialTypeNames[] =
	{
		"solid",
		"solid_2layer",
		"lightmap",
		"lightmap_add",
		"lightmap_m2",
		"lightmap_m4",
		"lightmap_light",
		"lightmap_light_m2",
		"lightmap_light_m4",
		"detail_map",
		"sphere_map",
		"reflection_2layer",
		"trans_add",
		"trans_alphach",
		"trans_alphach_ref",
		"trans_vertex_alpha",
		"trans_reflection_2layer",
		"normalmap_solid",
		"normalmap_trans_add",
		"normalmap_trans_vertexalpha",
		"parallaxmap_solid",
		"parallaxmap_trans_add",
		"parallaxmap_trans_vertexalpha",
		"onetexture_blend",

		"texture_splatting", // added for texture splatting by locosoftware
		0
	};
[/url]
Last edited by locosoftware on Thu Mar 27, 2008 11:33 pm, edited 7 times in total.
locosoftware
Posts: 15
Joined: Sat Mar 08, 2008 3:15 pm
Location: Shanghai

Post by locosoftware »

And to use it:

Code: Select all

#include <irrlicht.h>
#include <iostream>
#include <windows.h>

using namespace irr;

#pragma comment(lib, "Irrlicht.lib")


class CSampleSceneNode : public scene::ISceneNode
{
	core::aabbox3d<f32> Box;
	video::S3DVertex2TCoords Vertices[4];
	video::SMaterial Material;

public:

	CSampleSceneNode(scene::ISceneNode* parent, scene::ISceneManager* mgr, s32 id)
		: scene::ISceneNode(parent, mgr, id)
	{
		Material.setFlag(video::EMF_LIGHTING, false);
		Material.MaterialType = video::EMT_TEXTURE_SPLATTING;
		
		Vertices[0] = video::S3DVertex2TCoords(-20,-20,0, 0,0,-1, video::SColor(255,0,255,255), 0, 1, 0, 1);
		Vertices[1] = video::S3DVertex2TCoords(-20,20,0, 0,0,-1, video::SColor(255,255,0,255), 0, 0, 0, 0);
		Vertices[2] = video::S3DVertex2TCoords(20,20,0, 0,0,-1, video::SColor(255,255,255,0), 1, 0, 1, 0);
		Vertices[3] = video::S3DVertex2TCoords(20,-20,0, 0,0,-1, video::SColor(255,0,255,0), 1, 1, 1, 1);

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

	virtual void OnRegisterSceneNode()
	{
		if (IsVisible)
			SceneManager->registerNodeForRendering(this);

		ISceneNode::OnRegisterSceneNode();
	}



	virtual void render()
	{
		u16 indices[] = {	0,1,2, 0,2,3	};
		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;
	}
};


int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
			LPSTR lpCmdLine, int nCmdShow)
{

	// create device

	IrrlichtDevice *device =
		createDevice(video::EDT_DIRECT3D9, core::dimension2d<s32>(800, 600), 32, false);
		
	if (device == 0)
		return 1; // could not create selected driver.

	// create engine and camera

	device->setWindowCaption(L"Texture Splatting");

	video::IVideoDriver* driver = device->getVideoDriver();
	scene::ISceneManager* smgr = device->getSceneManager();

	smgr->addCameraSceneNode(0, core::vector3df(0,0,-30), core::vector3df(0,0,0));


	CSampleSceneNode *myNode = 
		new CSampleSceneNode(smgr->getRootSceneNode(), smgr, 666);


	//scene::ISceneNode *myNode = smgr->addCubeSceneNode(50);
	//video::ITexture* texAlpha1 = driver->getTexture("../media/combinedalphamap.tga")

	video::ITexture* texAlpha1 = driver->getTexture("../media/alphamap1.tga");
	video::ITexture* texAlpha2 = driver->getTexture("../media/alphamap2.tga");
	video::ITexture* texAlpha3 = driver->getTexture("../media/alphamap3.tga");
	video::ITexture* texAlpha4 = driver->getTexture("../media/alphamap4.tga");

	video::ITexture* tex1 = driver->getTexture("../media/texture1.png");
	video::ITexture* tex2 = driver->getTexture("../media/texture2.png");
	video::ITexture* tex3 = driver->getTexture("../media/texture3.png");
	video::ITexture* tex4 = driver->getTexture("../media/texture4.png");



	u32 frames=0;
	while(device->run())
	{
		driver->beginScene(true, true, video::SColor(0,0,0,255));
		{
			myNode->getMaterial(0).TextureLayer[0].TextureWrap = video::ETC_CLAMP;
			myNode->getMaterial(0).setTexture(0,texAlpha1);

			myNode->getMaterial(0).TextureLayer[1].TextureWrap = video::ETC_REPEAT;
			myNode->getMaterial(0).setTexture(1,tex1);
			
			smgr->drawAll();
		}

		{
			myNode->getMaterial(0).TextureLayer[0].TextureWrap = video::ETC_CLAMP;
			myNode->getMaterial(0).setTexture(0,texAlpha2);

			myNode->getMaterial(0).TextureLayer[1].TextureWrap = video::ETC_REPEAT;
			myNode->getMaterial(0).setTexture(1,tex2);
			
			smgr->drawAll();
		}

		{
			myNode->getMaterial(0).TextureLayer[0].TextureWrap = video::ETC_CLAMP;
			myNode->getMaterial(0).setTexture(0,texAlpha3);

			myNode->getMaterial(0).TextureLayer[1].TextureWrap = video::ETC_REPEAT;
			myNode->getMaterial(0).setTexture(1,tex3);
			
			smgr->drawAll();
		}

		{
			myNode->getMaterial(0).TextureLayer[0].TextureWrap = video::ETC_CLAMP;
			myNode->getMaterial(0).setTexture(0,texAlpha4);

			myNode->getMaterial(0).TextureLayer[1].TextureWrap = video::ETC_REPEAT;
			myNode->getMaterial(0).setTexture(1,tex4);

			smgr->drawAll();
		}


		driver->endScene();
		if (++frames==100)
		{
			core::stringw str = L"Irrlicht Engine [";
			str += driver->getName();
			str += L"] FPS: ";
			str += (s32)driver->getFPS();

			device->setWindowCaption(str.c_str());
			frames=0;
		}
	}

	device->drop();
	
	return 0;
}


This effect can be used with terrain.
Last edited by locosoftware on Thu Mar 27, 2008 9:49 pm, edited 1 time in total.
locosoftware
Posts: 15
Joined: Sat Mar 08, 2008 3:15 pm
Location: Shanghai

Post by locosoftware »

Here is the D3D8 implementation:
1.Add the CD3D8MaterialRenderer_SPLATTING class in CD3D8MaterialRenderer.h file:

Code: Select all

//=====================================locosoftware added=================================================

//! For texture splatting without pixelshader
class CD3D8MaterialRenderer_SPLATTING : public CD3D8MaterialRenderer
{
public:

	CD3D8MaterialRenderer_SPLATTING(IDirect3DDevice8* p, video::IVideoDriver* d)
		: CD3D8MaterialRenderer(p, d) {}

	virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial,
		bool resetAllRenderstates, IMaterialRendererServices* services)
	{
		// Do some normal state settings
		services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);

		pID3DDevice->SetRenderState(D3DRS_LIGHTING, FALSE);
		pID3DDevice->SetRenderState(D3DRS_ZENABLE, TRUE);

		// Allow multiple passes to blend together correctly
		pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
		pID3DDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
		pID3DDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);

		// Note! In D3D9 is SetSamplerState, but in D3D8 it is SetTextureStageState function
		pID3DDevice->SetTextureStageState(0, D3DTSS_MINFILTER, D3DTEXF_LINEAR);
		pID3DDevice->SetTextureStageState(0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR);
		pID3DDevice->SetTextureStageState(0, D3DTSS_MIPFILTER, D3DTEXF_LINEAR);
		// Prevent some ugliness with the alphamaps
		pID3DDevice->SetTextureStageState(0, D3DTSS_ADDRESSU, D3DTADDRESS_CLAMP);
		pID3DDevice->SetTextureStageState(0, D3DTSS_ADDRESSV, D3DTADDRESS_CLAMP);

		pID3DDevice->SetTextureStageState(1, D3DTSS_MINFILTER, D3DTEXF_LINEAR);
		pID3DDevice->SetTextureStageState(1, D3DTSS_MAGFILTER, D3DTEXF_LINEAR);
		pID3DDevice->SetTextureStageState(1, D3DTSS_MIPFILTER, D3DTEXF_LINEAR);

		pID3DDevice->SetTextureStageState(2, D3DTSS_MINFILTER, D3DTEXF_LINEAR);
		pID3DDevice->SetTextureStageState(2, D3DTSS_MAGFILTER, D3DTEXF_LINEAR);
		pID3DDevice->SetTextureStageState(2, D3DTSS_MIPFILTER, D3DTEXF_LINEAR);

		pID3DDevice->SetTextureStageState(3, D3DTSS_MINFILTER, D3DTEXF_LINEAR);
		pID3DDevice->SetTextureStageState(3, D3DTSS_MAGFILTER, D3DTEXF_LINEAR);
		pID3DDevice->SetTextureStageState(3, D3DTSS_MIPFILTER, D3DTEXF_LINEAR);

		pID3DDevice->SetTextureStageState(4, D3DTSS_MINFILTER, D3DTEXF_LINEAR);
		pID3DDevice->SetTextureStageState(4, D3DTSS_MAGFILTER, D3DTEXF_LINEAR);
		pID3DDevice->SetTextureStageState(4, D3DTSS_MIPFILTER, D3DTEXF_LINEAR);

		// Alphamap: take the alpha from the alphamap, we don't care about the color
		pID3DDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
		pID3DDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);

		// Texture: take the color from the texture, take the alpha from the previous stage
		pID3DDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
		pID3DDevice->SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_TEXTURE);
		pID3DDevice->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
		pID3DDevice->SetTextureStageState(1, D3DTSS_ALPHAARG1, D3DTA_CURRENT);
	}
};
//===============================================================================================

2: Modify the CD3D8Driver::createMaterialRenderers() at last in CD3D9Driver.cpp:

Code: Select all

void CD3D8Driver::createMaterialRenderers()
{
	// create D3D8 material renderers

	addAndDropMaterialRenderer(new CD3D8MaterialRenderer_SOLID(pID3DDevice, this));
	addAndDropMaterialRenderer(new CD3D8MaterialRenderer_SOLID_2_LAYER(pID3DDevice, this));

	// add the same renderer for all lightmap types
	CD3D8MaterialRenderer_LIGHTMAP* lmr = new CD3D8MaterialRenderer_LIGHTMAP(pID3DDevice, this);
	addMaterialRenderer(lmr); // for EMT_LIGHTMAP:
	addMaterialRenderer(lmr); // for EMT_LIGHTMAP_ADD:
	addMaterialRenderer(lmr); // for EMT_LIGHTMAP_M2:
	addMaterialRenderer(lmr); // for EMT_LIGHTMAP_M4:
	addMaterialRenderer(lmr); // for EMT_LIGHTMAP_LIGHTING:
	addMaterialRenderer(lmr); // for EMT_LIGHTMAP_LIGHTING_M2:
	addMaterialRenderer(lmr); // for EMT_LIGHTMAP_LIGHTING_M4:
	lmr->drop();

	// add remaining material renderers
	addAndDropMaterialRenderer(new CD3D8MaterialRenderer_DETAIL_MAP(pID3DDevice, this));
	addAndDropMaterialRenderer(new CD3D8MaterialRenderer_SPHERE_MAP(pID3DDevice, this));
	addAndDropMaterialRenderer(new CD3D8MaterialRenderer_REFLECTION_2_LAYER(pID3DDevice, this));
	addAndDropMaterialRenderer(new CD3D8MaterialRenderer_TRANSPARENT_ADD_COLOR(pID3DDevice, this));
	addAndDropMaterialRenderer(new CD3D8MaterialRenderer_TRANSPARENT_ALPHA_CHANNEL(pID3DDevice, this));
	addAndDropMaterialRenderer(new CD3D8MaterialRenderer_TRANSPARENT_ALPHA_CHANNEL_REF(pID3DDevice, this));
	addAndDropMaterialRenderer(new CD3D8MaterialRenderer_TRANSPARENT_VERTEX_ALPHA(pID3DDevice, this));
	addAndDropMaterialRenderer(new CD3D8MaterialRenderer_TRANSPARENT_REFLECTION_2_LAYER(pID3DDevice, this));

	// add normal map renderers
	s32 tmp = 0;
	video::IMaterialRenderer* renderer = 0;

	renderer = new CD3D8NormalMapRenderer(pID3DDevice, this, tmp,
		MaterialRenderers[EMT_SOLID].Renderer);
	renderer->drop();

	renderer = new CD3D8NormalMapRenderer(pID3DDevice, this, tmp,
		MaterialRenderers[EMT_TRANSPARENT_ADD_COLOR].Renderer);
	renderer->drop();

	renderer = new CD3D8NormalMapRenderer(pID3DDevice, this, tmp,
		MaterialRenderers[EMT_TRANSPARENT_VERTEX_ALPHA].Renderer);
	renderer->drop();

	// add parallax map renderers

	renderer = new CD3D8ParallaxMapRenderer(pID3DDevice, this, tmp,
		MaterialRenderers[EMT_SOLID].Renderer);
	renderer->drop();

	renderer = new CD3D8ParallaxMapRenderer(pID3DDevice, this, tmp,
		MaterialRenderers[EMT_TRANSPARENT_ADD_COLOR].Renderer);
	renderer->drop();

		renderer = new CD3D8ParallaxMapRenderer(pID3DDevice, this, tmp,
		MaterialRenderers[EMT_TRANSPARENT_VERTEX_ALPHA].Renderer);
	renderer->drop();

	// add basic 1 texture blending
	addAndDropMaterialRenderer(new CD3D8MaterialRenderer_ONETEXTURE_BLEND(pID3DDevice, this));

	
	//===========================Added by Locosoftware=================================
	// add texture splatting (Added by Locosoftware)
	addAndDropMaterialRenderer(new CD3D8MaterialRenderer_SPLATTING(pID3DDevice, this));
	//=================================================================================
}
Unfortunately I don't known how to implement an OpenGL one.
And I hope this code can be added in new version of Irrlicht for convenience.
Halifax
Posts: 1424
Joined: Sun Apr 29, 2007 10:40 pm
Location: $9D95

Post by Halifax »

Could we get some screenshots, please?
TheQuestion = 2B || !2B
locosoftware
Posts: 15
Joined: Sat Mar 08, 2008 3:15 pm
Location: Shanghai

Post by locosoftware »

Halifax wrote:Could we get some screenshots, please?

The Screenshot is here:
http://lcgamestudio.spaces.live.com/pho ... 2D45F!120/

And can download code:

http://uploader.polorix.net//files/1431 ... atting.zip
and modified engine code here:
http://uploader.polorix.net//files/1431 ... 20Code.zip

The engine.dll is the Irrlicht.dll.
Halifax
Posts: 1424
Joined: Sun Apr 29, 2007 10:40 pm
Location: $9D95

Post by Halifax »

Yeah, I think this would be a great solution for Irrlicht as an out-of-the-box solution. And then if people wanted to provide their own pixel shader methods, then they could.

The only thing I have to say is that BlindSide's solution might beat you out, given the screenshot that he posted. :lol:
TheQuestion = 2B || !2B
locosoftware
Posts: 15
Joined: Sat Mar 08, 2008 3:15 pm
Location: Shanghai

Post by locosoftware »

I curiously want to know BlindSide's solution. :shock:
BlindSide
Admin
Posts: 2821
Joined: Thu Dec 08, 2005 9:09 am
Location: NZ!

Post by BlindSide »

It's coming along (I just need to fix those damn gridlines caused by "fract()"). I'll come up with a hacky solution (lol) tomorrow.

My solution offcourse needs pixel shaders level 2.0.

About this material: This is pretty neat, have you seen the ONE_TEXTURE_BLEND material? That can only blend 2 textures, but I think that a few more materials like TWO and THREE texture blends should be added so an effect like your's can be achieved in Irrlicht.

Infact I think that the blending mode should be part of the TextureLayer, so we can easily define how each texture should be blended on top of the other.

PS: It shouldn't be hard to make an OpenGL version, just take a look at the detail map material renderer for example (or one texture blend) and it should be obvious what the method in OpenGL is, then maybe we can add this material to the Irrlicht core ;)
ShadowMapping for Irrlicht!: Get it here
Need help? Come on the IRC!: #irrlicht on irc://irc.freenode.net
locosoftware
Posts: 15
Joined: Sat Mar 08, 2008 3:15 pm
Location: Shanghai

Post by locosoftware »

I think that I should write a class for texture splattiong without pixel shader for easy to use and can add any number of texture to be blended. Of cource, this solution is slower than pixel shader one.
arras
Posts: 1622
Joined: Mon Apr 05, 2004 8:35 am
Location: Slovakia
Contact:

Post by arras »

This is pretty neat, have you seen the ONE_TEXTURE_BLEND material? That can only blend 2 textures, ...
ONE_TEXTURE_BLEND blends only one texture not two. On top of already rendered pixels (background). You can archive more textures if you simply render same geometry with different textures and alpha. But that of course may be slow.
sio2
Competition winner
Posts: 1003
Joined: Thu Sep 21, 2006 5:33 pm
Location: UK

Post by sio2 »

Code: Select all

smgr->drawAll(); 
Does this still advance the internals? Cos there's four per-scene in the above code.
BlindSide
Admin
Posts: 2821
Joined: Thu Dec 08, 2005 9:09 am
Location: NZ!

Post by BlindSide »

arras wrote:
This is pretty neat, have you seen the ONE_TEXTURE_BLEND material? That can only blend 2 textures, ...
ONE_TEXTURE_BLEND blends only one texture not two. On top of already rendered pixels (background). You can archive more textures if you simply render same geometry with different textures and alpha. But that of course may be slow.
It blends two textures together, or did I get that wrong?
ShadowMapping for Irrlicht!: Get it here
Need help? Come on the IRC!: #irrlicht on irc://irc.freenode.net
locosoftware
Posts: 15
Joined: Sat Mar 08, 2008 3:15 pm
Location: Shanghai

Post by locosoftware »

I modified the demo code:

Code: Select all

#include <irrlicht.h>
#include <iostream>
#include <windows.h>

using namespace irr;

#pragma comment(lib, "Irrlicht.lib")


class CSampleSceneNode : public scene::ISceneNode
{
	core::aabbox3d<f32> Box;
	video::S3DVertex2TCoords Vertices[4];
	video::SMaterial Material;

	video::ITexture* texAlpha1;
	video::ITexture* texAlpha2;
	video::ITexture* texAlpha3;
	video::ITexture* texAlpha4;

	video::ITexture* tex1;
	video::ITexture* tex2;
	video::ITexture* tex3;
	video::ITexture* tex4;

public:

	CSampleSceneNode(scene::ISceneNode* parent, scene::ISceneManager* mgr, s32 id)
		: scene::ISceneNode(parent, mgr, id)
	{
		Material.setFlag(video::EMF_LIGHTING, false);
		Material.MaterialType = video::EMT_TEXTURE_SPLATTING;
		
		Vertices[0] = video::S3DVertex2TCoords(-20,-20,0, 0,0,-1, video::SColor(255,0,255,255), 0, 1, 0, 1);
		Vertices[1] = video::S3DVertex2TCoords(-20,20,0, 0,0,-1, video::SColor(255,255,0,255), 0, 0, 0, 0);
		Vertices[2] = video::S3DVertex2TCoords(20,20,0, 0,0,-1, video::SColor(255,255,255,0), 1, 0, 1, 0);
		Vertices[3] = video::S3DVertex2TCoords(20,-20,0, 0,0,-1, video::SColor(255,0,255,0), 1, 1, 1, 1);

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

		video::IVideoDriver* driver = SceneManager->getVideoDriver();


		texAlpha1 = driver->getTexture("../media/alphamap1.tga");
		texAlpha2 = driver->getTexture("../media/alphamap2.tga");
		texAlpha3 = driver->getTexture("../media/alphamap3.tga");
		texAlpha4 = driver->getTexture("../media/alphamap4.tga");

		tex1 = driver->getTexture("../media/texture1.png");
		tex2 = driver->getTexture("../media/texture2.png");
		tex3 = driver->getTexture("../media/texture3.png");
		tex4 = driver->getTexture("../media/texture4.png");
	}

	virtual void OnRegisterSceneNode()
	{
		if (IsVisible)
			SceneManager->registerNodeForRendering(this);

		ISceneNode::OnRegisterSceneNode();
	}



	virtual void render()
	{
		u16 indices[] = {	0,1,2, 0,2,3	};
		video::IVideoDriver* driver = SceneManager->getVideoDriver();


		driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);

		
		{
			Material.TextureLayer[0].TextureWrap = video::ETC_CLAMP;
			Material.setTexture(0,texAlpha1);

			Material.TextureLayer[1].TextureWrap = video::ETC_REPEAT;
			Material.setTexture(1,tex1);

			driver->setMaterial(Material);
			driver->drawIndexedTriangleList(&Vertices[0], 4, &indices[0], 2);
		}


		{
			Material.TextureLayer[0].TextureWrap = video::ETC_CLAMP;
			Material.setTexture(0,texAlpha2);

			Material.TextureLayer[1].TextureWrap = video::ETC_REPEAT;
			Material.setTexture(1,tex2);
			
			driver->setMaterial(Material);
			driver->drawIndexedTriangleList(&Vertices[0], 4, &indices[0], 2);
		}


		{
			Material.TextureLayer[0].TextureWrap = video::ETC_CLAMP;
			Material.setTexture(0,texAlpha3);

			Material.TextureLayer[1].TextureWrap = video::ETC_REPEAT;
			Material.setTexture(1,tex3);
			
			driver->setMaterial(Material);
			driver->drawIndexedTriangleList(&Vertices[0], 4, &indices[0], 2);
		}


		{
			Material.TextureLayer[0].TextureWrap = video::ETC_CLAMP;
			Material.setTexture(0,texAlpha4);

			Material.TextureLayer[1].TextureWrap = video::ETC_REPEAT;
			Material.setTexture(1,tex4);

			driver->setMaterial(Material);
			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;
	}
};


int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
			LPSTR lpCmdLine, int nCmdShow)
{

	// create device

	IrrlichtDevice *device =
		createDevice(video::EDT_DIRECT3D9, core::dimension2d<s32>(800, 600), 32, false);
		
	if (device == 0)
		return 1; // could not create selected driver.

	// create engine and camera

	device->setWindowCaption(L"Texture Splatting");

	video::IVideoDriver* driver = device->getVideoDriver();
	scene::ISceneManager* smgr = device->getSceneManager();

	smgr->addCameraSceneNode(0, core::vector3df(0,0,-30), core::vector3df(0,0,0));


	CSampleSceneNode *myNode = 
		new CSampleSceneNode(smgr->getRootSceneNode(), smgr, 666);



	u32 frames=0;
	while(device->run())
	{
		driver->beginScene(true, true, video::SColor(0,0,0,255));

		smgr->drawAll();

		driver->endScene();
		if (++frames==100)
		{
			core::stringw str = L"Irrlicht Engine [";
			str += driver->getName();
			str += L"] FPS: ";
			str += (s32)driver->getFPS();

			device->setWindowCaption(str.c_str());
			frames=0;
		}
	}

	device->drop();
	
	return 0;
}

[/url]
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

BlindSide wrote:
arras wrote:
This is pretty neat, have you seen the ONE_TEXTURE_BLEND material? That can only blend 2 textures, ...
ONE_TEXTURE_BLEND blends only one texture not two. On top of already rendered pixels (background). You can archive more textures if you simply render same geometry with different textures and alpha. But that of course may be slow.
It blends two textures together, or did I get that wrong?
No, arras is right. It takes one texture and allows arbitrary blend modes for background blending.
sio2
Competition winner
Posts: 1003
Joined: Thu Sep 21, 2006 5:33 pm
Location: UK

Re: Texture Splatting Effect Without Pixel Shader

Post by sio2 »

locosoftware wrote:First I got an idea with http://downloads.gamedev.net/features/h ... ngDemo.zip in Direct3D 9.
The pixel shader codepath in that demo uses a single draw call. The fixed-function path uses four. If your game is transform limited then the shader path is more optimal.
Post Reply