Okay... the idea here is to use (2) blendmap TGA's to lay (2) textures over a 1st pass texture. Then, do some lighting (you have to experiment there), and finally blend our shadowmap over all of these.
It's (3) passes to keep only (2) texture operations in a given pass.
Read the comments for some more info:
Code:
///////////////////////////////////////////////////////////
// FFP Terrain MultiTexturing Effect with Shadowmap
//
// From: Steempipe
//
// Notes:
// Use the FFP to tile and blend some terrain textures.
// Then do the lighting and slap a shadowmap on top.
//
//////////////////////////////////////////////////////////
//*****************************************************
//** I had strange results with putting the alphamaps
//** in to the HMP as entSkins.
//** Just load them as mtlSkins.
//*****************************************************
// RGB Channels are blank
// The A channel has the blending weight (pattern)
bmap blendmap = <blendmap.tga>; // Blender for Pass p1
bmap blendmap2 = <blendmap2.tga>; // Blender for Pass p2
// The RGB Channels of this BMP has black for shadow and white will not be rendered
bmap shadow = <shadmap.bmp>; // Shadow for Pass p3
//*****************************************************
//** entSkins 1-3 are tilable textures
//** Be sure to add mipmaps to them in MED
//*****************************************************
function mtl_terrainshad_init()
{
bmap_to_mipmap(mtl.skin1);
bmap_to_mipmap(mtl.skin2);
bmap_to_mipmap(mtl.Skin3);
// Adjusting the texture transform to do some tiling of the textures
// is done in each stage as needed. Not using the <matMtl>.
}
///////////////////////////////////////////////////////////////////////
//The Material
///////////////////////////////////////////////////////////////////////
material mat_terrainshad
{
skin1 = blendmap;
Skin2 = blendmap2;
skin3 = shadow;
// define a material effect string
event = mtl_terrainshad_init;
effect =
"
matrix matMtl;
texture mtlSkin1; // Blending map for Pass P1
texture mtlSkin2; // Blending map for Pass P2
texture mtlSkin3; // The Shadow map
texture entSkin1; // Tileable Tex (ie, Grass)
texture entSkin2; // Tileable Tex (ie, Sand)
texture entSkin3; // Tileable Tex (ie, Shale)
///////////////////////////////////////////////////////////////////////
//The Technique
///////////////////////////////////////////////////////////////////////
technique ffp_terrain_shadow
{
pass P0
//////////////////////////////////////////////////////
//// Lets lay the first texture down. no alpha work
//////////////////////////////////////////////////////
{
alphablendenable=false;
alphatestenable=false;
zenable=true;
zwriteenable=true;
////////////////////////////////////////
// Stage 0
///////////////////////////////////////
Texture[0] = <entSkin1>;
magFilter[0]=linear;
minFilter[0]=linear;
mipFilter[0]=linear;
TextureTransformFlags[0] = Count2;
// Adjust The UV Tiling Scale here
//
TextureTransform[0]=
{
20.0, 0.0, 0.0, 0.0, //u
0.0, 20.0, 0.0, 0.0, //v
0.0, 0.0, 0.0, 0.0,
0.0, 0.0, 0.0, 0.0
};
texcoordindex[0]=0;
ColorArg1[0] = Texture;
ColorOp[0] = selectarg1;
alphaop[0]=disable;
//////////////////////////////////////
//stage 1
//////////////////////////////////////
colorop[1]=disable;
alphaop[1]=disable;
}
pass P1
//////////////////////////////////////////////////////
//// Now we blend another texture using an alphamap
//////////////////////////////////////////////////////
{
//////////////////////////////////////
// Stage 0
//////////////////////////////////////
// We need to enable alphablending
alphablendenable=true;
srcblend=srcalpha;
destblend=invsrcalpha;
// AlphaTestEnable uses the AlphaRef and AlphaFunc to
// determine which pixels get drawn.
// In this case, anything greater that 0 will be drawn.
alphatestenable=true;
alpharef=0x00000000; //Reference Value
alphafunc=Greater; //Comparison Function
zenable=false;
zwriteenable=false;
Texture[0] = <mtlSkin1>;
magFilter[0]=linear;
minFilter[0]=linear;
mipFilter[0]=linear;
//
// We don't want the alphamap to tile
//
TextureTransformFlags[0] = disable;
texcoordindex[0]=0;
ColorArg1[0] = current;
ColorOp[0] = selectarg1;
alphaarg1[0] = texture | alphareplicate;
alphaop[0]=selectarg1;
//////////////////////////////////////////////
// Stage 1
//////////////////////////////////////////////
Texture[1] = <entSkin2>;
// Zenable is supposed to default to true.
// This enables depth testing to determine what pixels
// are visible to the viewer
zenable=true;
zwriteenable=true;
magFilter[1]=linear;
minFilter[1]=linear;
mipFilter[1]=linear;
TextureTransformFlags[1] = Count2;
// Adjust The UV Tiling Scale here
//
TextureTransform[1]=
{
15.0, 0.0, 0.0, 0.0, //u
0.0, 15.0, 0.0, 0.0, //v
0.0, 0.0, 0.0, 0.0,
0.0, 0.0, 0.0, 0.0
};
texcoordindex[1]=1;
ColorArg1[1] = texture;
ColorOp[1] = modulate;
alphaarg1[1] = current | alphareplicate;
alphaop[1]=disable;
///////////////////////////////////////////////
// Stage 2
///////////////////////////////////////////////
colorop[2]=disable;
alphaop[2]=disable;
}
pass P2
////////////////////////////////////////////////////
//// A ditto of Pass p1 but with different a different
//// texture and alphamap
///////////////////////////////////////////////////
{
////////////////////////////////////////
// Stage 0
////////////////////////////////////////
alphablendenable=true;
srcblend=srcalpha;
destblend=invsrcalpha;
alphatestenable=true;
alpharef=0x00000000;
alphafunc=Greater;
Texture[0] = <mtlSkin2>;
zenable=true;
zwriteenable=true;
magFilter[0]=linear;
minFilter[0]=linear;
mipFilter[0]=linear;
TextureTransformFlags[0] = disable;
texcoordindex[0]=1;
ColorArg1[0] = current;
ColorOp[0] = selectarg1;
alphaarg1[0] = texture | alphareplicate;
alphaop[0]=selectarg1;
/////////////////////////////////////////
// Stage 1
/////////////////////////////////////////
Texture[1] = <entSkin3>;
zenable=true;
zwriteenable=true;
magFilter[1]=linear;
minFilter[1]=linear;
mipFilter[1]=linear;
TextureTransformFlags[1] = Count2;
// Adjust The UV Tiling Scale here
//
TextureTransform[1]=
{
10.0, 0.0, 0.0, 0.0, //u
0.0, 10.0, 0.0, 0.0, //v
0.0, 0.0, 0.0, 0.0,
0.0, 0.0, 0.0, 0.0
};
texcoordindex[1]=0;
ColorArg1[1] = texture;
ColorOp[1] = modulate;
alphaarg1[1] = current | alphareplicate;
alphaop[1]=disable;
////////////////////////////////////////
// Stage 2
////////////////////////////////////////
colorop[2]=disable;
alphaop[2]=disable;
} // End of Pass P2
Pass p3
{
////////////////////////////////////////////////////
//// Lets do some lighting and shadows
///////////////////////////////////////////////////
alphablendenable=true;
srcblend=zero;
destblend=srccolor;
zenable=true;
zwriteenable=true;
ditherenable=true;
////////////////////////////////////////
// Stage 0 - Lighting
////////////////////////////////////////
ColorArg1[0] = Diffuse;
ColorOp[0] = Modulate2x;
ColorArg2[0] = Current;
alphaop[0]=disable;
////////////////////////////////////////
// Stage 1 - Lighting
///////////////////////////////////////
Texture[1] = <mtlSkin3>;
magFilter[1]=linear;
minFilter[1]=linear;
mipFilter[1]=linear;
ColorArg1[1] = texture;
ColorOp[1] = Modulate2x;
TextureTransformFlags[1] = disable;
texcoordindex[1]=1;
} // End of Pass P3
} // End of Technique
technique fallback { pass p0 { } } // empty fallback causes normal rendering without effect
"; // end of the effect string
} // End of Material
///////////////////////////////////////////////////////////////////////
//The Action we assign in WED
///////////////////////////////////////////////////////////////////////
action ffp_TerrainShad
{
///////////////////////////////////////
// Assign a suncolor in Map Properties
// for ex. 255, 255, 128
//
//////////////////////////////////
// Adjust these (4) values to your liking
//
sun_angle.pan=30;
sun_angle.tilt=80;
my.ambient=50;
my.albedo=50;
my.unlit=on;
my.transparent=off;
my.material = mat_terrainshad;
}