Terrain Help

Post your questions, suggestions and experiences regarding to Image manipulation, 3d modeling and level editing for the Irrlicht engine here.
Post Reply
Ktrainers
Posts: 10
Joined: Sun Mar 23, 2008 5:46 pm

Terrain Help

Post by Ktrainers »

Can anyone tell me exactly how to read in a blend map to create multi-textured terrain using irrlicht? I created some terrain using the scenemanager->addTerrainSceneNode() method which is nice cause it reads in a heightmap on its own, but it seems like when you make terrain this way you can only stretch one texture over the whole mesh. I want to be able to have dirt textures, grass textures, stone textures, etc. on my terrain. Can anyone show me how to do this with Irrlicht?
JP
Posts: 4526
Joined: Tue Sep 13, 2005 2:56 pm
Location: UK
Contact:

Post by JP »

I don't think there's any standard way of doing this really... i think someone posted something they were working on which did this sort of thing though so you should be able to search for it.
Image Image Image
Ktrainers
Posts: 10
Joined: Sun Mar 23, 2008 5:46 pm

Post by Ktrainers »

You dont happen to remember what it is or who did it do you?
BlindSide
Admin
Posts: 2821
Joined: Thu Dec 08, 2005 9:09 am
Location: NZ!

Post by BlindSide »

You can create a shader specifically for this or use the EMT_ONETEXTURE_BLEND with the EBF_SRC_ALPHA blend factor and store the blendmap in the first textures alpha channel.

The first method is faster and should be able to run on fixed function hardware but you can only lerp between 2 textures. (Eg. Grass and rock.).

Another method is one proposed by arras to skew the texcoords of each terrain vertex to create a lookup from a big texture containing multiple textures inside it, but if you want a smooth transition you would have to create "boundary textures" for the edges and the corners and this can get pretty messy quickly.

I recommend reading up on shaders then storing the desired strength of each texture in each component of the vertex color, then using the vertex color (which will be interpolated smoothly accross all fragments) to decide how to mix between the different textures in the pixel shader.

I might decide to release something thats similar to this (but better) soon, but no promises.
ShadowMapping for Irrlicht!: Get it here
Need help? Come on the IRC!: #irrlicht on irc://irc.freenode.net
Ktrainers
Posts: 10
Joined: Sun Mar 23, 2008 5:46 pm

Post by Ktrainers »

Thanks for the help! That would be pretty amazing and very helpful if you could release something like that. I've been reading up on Pixel shaders and I understand how to write them but what I'm confused about is how you interface the compiled pixel shader with the Irrlicht application. That is, how you get the information from the shader to the functions that actually render the mesh. Any help in that area would be greatly appreciated.

Thanks
Ktrainers
Posts: 10
Joined: Sun Mar 23, 2008 5:46 pm

Post by Ktrainers »

Okay, so I've written a pixel shader and it seems to work to some degree, but there is still a problem. It does use the blend map to determine where the textures are to be placed on the terrain, however the textures lose all of their details. For example, instead of having a dirt road that has cracks, twigs, and other detail like it does in the .jpg texture file, it just comes up as a brown color on the terrain with no detail at all. This gives my terrain a very smooth look with no realism at all. I was wondering if anyone could tell me, why I'm losing the detail in my textures.

I add a terrain Scene Node and set the material textures and the material type with the following code:

Code: Select all

scene::ITerrainSceneNode* terrain = smgr->addTerrainSceneNode( 
		"media/terrain-heightmap.bmp",
		0,						// parent node
		-1,						// node id
		core::vector3df(0.f, 0.f, 0.f),			// position
		core::vector3df(0.f, 0.f, 0.f),			// rotation
		core::vector3df(40.0f, 4.4f, 40.0f),		// scale
		video::SColor ( 255, 255, 255, 255 ),	// vertexColor,
		5,						// maxLOD
		scene::ETPS_17,					// patchSize
		5							// smoothFactor
		);

terrain->setMaterialTexture(0,driver->getTexture("media/blend_hm17.jpg"));	terrain->setMaterialTexture(1,driver->getTexture("media/grass.jpg"));
terrain->setMaterialTexture(2,driver->getTexture("media/dirt.jpg"));
terrain->setMaterialTexture(3,driver->getTexture("media/stone.jpg"));

s32 newMaterialType = driver->getGPUProgrammingServices()->addHighLevelShaderMaterialFromFiles( 0,0,video::EVST_VS_2_0,"TerrainPS.psh","ps_main",video::EPST_PS_2_0,0video::EMT_SOLID);

terrain->setMaterialType((video::E_MATERIAL_TYPE)newMaterialType);

My pixel Shader looks like this:

Code: Select all

float4x4 matViewProjection : ViewProjection;
float texScale = 10.0;


sampler AlphaMap = sampler_state
{

MinFilter = LINEAR;
	MagFilter = LINEAR;
	MipFilter = LINEAR;
   ADDRESSU = WRAP;
   ADDRESSV = WRAP;
   ADDRESSW = WRAP;
};

sampler TextureOne = sampler_state
{
  
   MipFilter = LINEAR;
   MinFilter = LINEAR;
   MagFilter = LINEAR;
   ADDRESSU = WRAP;
   ADDRESSV = WRAP;
   ADDRESSW = WRAP;
};

sampler TextureTwo = sampler_state
{
   
   MipFilter = LINEAR;
   MinFilter = LINEAR;
   MagFilter = LINEAR;
   ADDRESSU = WRAP;
   ADDRESSV = WRAP;
   ADDRESSW = WRAP;
};

sampler TextureThree = sampler_state
{
   
   MipFilter = LINEAR;
   MinFilter = LINEAR;
   MagFilter = LINEAR;
   ADDRESSU = WRAP;
   ADDRESSV = WRAP;
   ADDRESSW = WRAP;
};




struct PS_OUTPUT
{
   float4 diffuse : COLOR0;
};



PS_OUTPUT ps_main(float shade : TEXCOORD0,
		  float2 tiledTexC : TEXCOORD1,
		  float2 nonTiledTexC : TEXCOORD0) : COLOR
{
   PS_OUTPUT output = (PS_OUTPUT)0;

	// Layer maps are tiled
	
	    float3 c0 = tex2D(TextureOne, mul(tiledTexC,texScale));
	    float3 c1 = tex2D(TextureTwo, mul(tiledTexC,texScale));
    	    float3 c2 = tex2D(TextureThree, mul(tiledTexC,texScale));
    
    
      // Blendmap is not tiled.
    float3 B = tex2D(AlphaMap, nonTiledTexC);
  
  
  // Find the inverse of all the blend weights so that we can
  	// scale the total color to the range [0, 1].
      float totalInverse = 1.0f / (B.r + B.g + B.b);
      
      c0 *= B.r * totalInverse;
     c1 *= B.g * totalInverse;
      c2 *= B.b * totalInverse;
      
    float3 final = (c0 + c1 + c2);//* shade;


   output.diffuse = float4(final,1.0f);

   return output;
}

technique Default_DirectX_Effect
{
   pass Pass_0
   {
      PixelShader = compile ps_2_0 ps_main();
   }
}
Any help with this would be greatly appreciated!
Thanks!
Post Reply