//---------------------------------------------------------------------
	MaterialPtr TerrainMaterialGeneratorA::SM2Profile::generate(const Terrain* terrain)
	{
		// re-use old material if exists
		MaterialPtr mat = terrain->_getMaterial();
		if (mat.isNull())
		{
			MaterialManager& matMgr = MaterialManager::getSingleton();

			// it's important that the names are deterministic for a given terrain, so
			// use the terrain pointer as an ID
			const String& matName = terrain->getMaterialName();
			mat = matMgr.getByName(matName);
			if (mat.isNull())
			{
				mat = matMgr.create(matName, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
			}
		}
		// clear everything
		mat->removeAllTechniques();
		
		// Automatically disable normal & parallax mapping if card cannot handle it
		// We do this rather than having a specific technique for it since it's simpler
		GpuProgramManager& gmgr = GpuProgramManager::getSingleton();
		if (!gmgr.isSyntaxSupported("ps_4_0") && !gmgr.isSyntaxSupported("ps_3_0") && !gmgr.isSyntaxSupported("ps_2_x")
			&& !gmgr.isSyntaxSupported("fp40") && !gmgr.isSyntaxSupported("arbfp1") && !gmgr.isSyntaxSupported("glsl")
            && !gmgr.isSyntaxSupported("glsles"))
		{
			setLayerNormalMappingEnabled(false);
			setLayerParallaxMappingEnabled(false);
		}

		addTechnique(mat, terrain, HIGH_LOD);

		// LOD
		if(mCompositeMapEnabled)
		{
			addTechnique(mat, terrain, LOW_LOD);
			Material::LodValueList lodValues;
			lodValues.push_back(TerrainGlobalOptions::getSingleton().getCompositeMapDistance());
			mat->setLodLevels(lodValues);
			Technique* lowLodTechnique = mat->getTechnique(1);
			lowLodTechnique->setLodIndex(1);
		}

		updateParams(mat, terrain);

		return mat;

	}
	//---------------------------------------------------------------------
	MaterialPtr TerrainMaterialGeneratorC::SM2Profile::generate(const Terrain* terrain)
	{
		// re-use old material if exists
		MaterialPtr mat = terrain->_getMaterial();
		if (mat.isNull())
		{
			MaterialManager& matMgr = MaterialManager::getSingleton();
 
			// it's important that the names are deterministic for a given terrain, so
			// use the terrain pointer as an ID
			const String& matName = terrain->getMaterialName();
			mat = matMgr.getByName(matName);
			if (mat.isNull())
			{
				mat = matMgr.create(matName, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
			}
		}
		// clear everything
		mat->removeAllTechniques();
 
		addTechnique(mat, terrain, HIGH_LOD);
 
		// LOD
		if(mCompositeMapEnabled)
		{
			addTechnique(mat, terrain, LOW_LOD);
			Material::LodValueList lodValues;
			lodValues.push_back(TerrainGlobalOptions::getSingleton().getCompositeMapDistance());
			mat->setLodLevels(lodValues);
			Technique* lowLodTechnique = mat->getTechnique(1);
			lowLodTechnique->setLodIndex(1);
		}
 
		updateParams(mat, terrain);
 
		return mat;
 
	}
void TerrainMaterial::Profile::createMaterial(const String& matName, const Terrain* terrain, bool renderCompositeMap)
{
	sh::Factory::getInstance().destroyMaterialInstance(matName);

	MaterialPtr mat = MaterialManager::getSingleton().getByName(matName);
	if (!mat.isNull())
		MaterialManager::getSingleton().remove(matName);

	mMaterial = sh::Factory::getInstance().createMaterialInstance(matName);

	if (!renderCompositeMap)
	{
		MaterialPtr ogreMat = static_cast<sh::OgreMaterial*>(mMaterial->getMaterial())->getOgreMaterial();

		Material::LodValueList list;
		list.push_back(TerrainGlobalOptions::getSingleton().getCompositeMapDistance());
		ogreMat->setLodLevels(list);
	}

	mMaterial->setProperty("allow_fixed_function", sh::makeProperty<sh::BooleanValue>(new sh::BooleanValue(false)));

	sh::MaterialInstancePass* p = mMaterial->createPass();

	p->setProperty("vertex_program",   STR("terrain_vertex"));
	p->setProperty("fragment_program", STR("terrain_fragment"));

	p->mShaderProperties.setProperty("composite_map", sh::makeProperty<sh::BooleanValue>(new sh::BooleanValue(renderCompositeMap)));

	typedef sh::MaterialInstanceTextureUnit* MatTex;

	//  global normal map ?-
	MatTex normalMap = p->createTextureUnit("normalMap");
	normalMap->setProperty("direct_texture",   STR(terrain->getTerrainNormalMap()->getName()));
	normalMap->setProperty("tex_address_mode", STR("clamp"));

	//  light map
	MatTex lightMap = p->createTextureUnit("lightMap");
	lightMap->setProperty("direct_texture",   STR(terrain->getLightmap()->getName()));
	lightMap->setProperty("tex_address_mode", STR("clamp"));

	uint maxLayers = getMaxLayers(terrain),
		numBlendTextures = std::min(terrain->getBlendTextureCount(maxLayers), terrain->getBlendTextureCount()),  // = 1
		numLayers = std::min(maxLayers, static_cast<uint>(terrain->getLayerCount()));

	p->mShaderProperties.setProperty("num_layers",    STR(toStr(numLayers)));
	p->mShaderProperties.setProperty("num_blendmaps", STR(toStr(numBlendTextures)));

	//  blend maps
	for (uint i = 0; i < numBlendTextures; ++i)
	{
		MatTex blendTex = p->createTextureUnit("blendMap" + toStr(i));
		blendTex->setProperty("direct_texture",   STR("blendmapRTT"));
		blendTex->setProperty("tex_address_mode", STR("clamp"));
	}

	//  layer diffuse+spec
	for (uint i = 0; i < numLayers; ++i)
	{
		MatTex diffuseTex = p->createTextureUnit("diffuseMap" + toStr(i));
		diffuseTex->setProperty("direct_texture", STR(terrain->getLayerTextureName(i, 0)));
		p->mShaderProperties.setProperty("blendmap_component_" + toStr(i),
			STR(toStr(i / 4) + "." + getComponent(i % 4)));
	}

	//  layer normal+height
	for (uint i = 0; i < numLayers; ++i)
	{
		MatTex normalTex = p->createTextureUnit("normalMap" + toStr(i));
		normalTex->setProperty("direct_texture", STR(terrain->getLayerTextureName(i, 1)));
	}

	//  shadow
	if (!renderCompositeMap)
	{
		for (int i = 0; i < 3; ++i)
		{
			MatTex shadowTex = p->createTextureUnit("shadowMap" + toStr(i));
			shadowTex->setProperty("content_type", STR("shadow"));
		}
	}

	//  composite map
	MatTex compositeMap = p->createTextureUnit("compositeMap");
	compositeMap->setProperty("direct_texture", STR(terrain->getCompositeMap()->getName()));

	//  uv multipliers ?-
	uint numUVMul = numLayers / 4;
	if (numLayers % 4)
		++numUVMul;
	for (int i = 0; i < numUVMul; ++i)
	{
		int ii = i * 4;
		sh::Vector4* uvMul = new sh::Vector4(
			terrain->getLayerUVMultiplier(ii),     terrain->getLayerUVMultiplier(ii + 1),
			terrain->getLayerUVMultiplier(ii + 2), terrain->getLayerUVMultiplier(ii + 3) );

		for (int j=0; j<4; ++j)
		{
			p->mShaderProperties.setProperty("uv_component_" + toStr(i*4+j), STR(
				toStr(i) + "." + getComponent(j) ));
		}
		p->mShaderProperties.setProperty("uv_mul_" + toStr(i), sh::makeProperty<sh::Vector4>(uvMul));
	}
	p->mShaderProperties.setProperty("num_uv_mul", STR(toStr(numUVMul)));

	p->mShaderProperties.setProperty("shadowtexture_offset", STR(toStr(0)));
}