MATERIAL* mtl_terrainmulti3 =
{
effect = "
//enable: Skin4 Mask on Green
//help: Skin 4 contains a texture masked by the Skin1 green channel.
//help: Dynamic lights are disabled when a shadow map is enabled.
#define GREENMASK
//enable: Shadow Map on Blue
//help: Terrain contains a shadow map on the Skin1 blue channel.
//help: Dynamic lights are disabled when a shadow map is enabled.
//#define SHADOWMAP
//enable: DirectX Lighting
//help: Use the DirectX Lighting Formula for dynamic Lights.
//help: Otherwise use the Conitec Formula that produces smoother light.
//#define DXLIGHTING
float4x4 matWorld;
float4x4 matWorldInv;
float4x4 matWorldView;
float4x4 matWorldViewProj;
float4 vecSunDir;
float4 vecSunDiffuse = float4(200.f/255.f, 200.f/255.f, 200.f/255.f, 1.f);
float4 vecFog;
float4 vecLight;
Texture entSkin1; // Red/green for blending, blue for shadow
Texture entSkin2; // Basic tiled terrain texture
Texture entSkin3; // Red masked tiled texture
Texture entSkin4; // Green masked tiled texture
float4 vecSkill41;
float4 vecLightPos[8]; // preset this with light positions (xyz) and ranges (w)
float4 vecLightColor[8]; // preset this with light colors
float3 vecFalloff = float3(0.f, 0.f, 1.5f);
sampler sMaskTex = sampler_state
{
Texture = <entSkin1>;
MipFilter = LINEAR;
MinFilter = LINEAR;
MagFilter = LINEAR;
AddressU = Wrap;
Addressv = Wrap;
};
sampler sBaseTex = sampler_state
{
Texture = <entSkin2>;
MipFilter = LINEAR;
MinFilter = LINEAR;
MagFilter = LINEAR;
AddressU = Wrap;
Addressv = Wrap;
};
sampler sRedTex = sampler_state
{
Texture = <entSkin3>;
MipFilter = LINEAR;
MinFilter = LINEAR;
MagFilter = LINEAR;
AddressU = Wrap;
Addressv = Wrap;
};
#ifdef GREENMASK
sampler sGreenTex = sampler_state
{
Texture = <entSkin4>;
MipFilter = LINEAR;
MinFilter = LINEAR;
MagFilter = LINEAR;
AddressU = Wrap;
Addressv = Wrap;
};
#endif
//////////////////////////////////////////////////////////////////////
// return the sun light on the surface
float4 DoSunLight(float3 N)
{
// modulate the sunlight by the surface angle
return vecSunDiffuse * dot(N,-vecSunDir);
}
// return the dynamic light on the surface
float4 DoPointLight(float3 P, float3 N, int i)
{
// calculate the light ray pointing from the light to the surface
float3 D = (float3)vecLightPos[i]-P;
// calculate the angle between surface and light ray
float NdotL = dot(N,normalize(D));
// modulate the light by the surface angle
float4 Color = vecLightColor[i] * NdotL;
// calculate the light attenuation factor, DX uses a really strange formula here
float fac = 0.f;
if (NdotL >= 0.f && vecLightPos[i].w > 0.f)
{
// get the distance factor
float LD = length(D)/vecLightPos[i].w;
#ifdef DXLIGHTING
if (LD < 1.3f)
fac = 1.f/(vecFalloff.x + vecFalloff.y*LD + vecFalloff.z*LD*LD);
#else // linear Lighting
if (LD < 1.f)
fac = 1.f - LD;
#endif
}
return Color * fac;
}
float DoFog(float3 Pos)
{
// convert the vector position to view space to get it's depth (.z)
float3 P = mul(Pos,matWorldView);
// apply the linear fog formula
return saturate((vecFog.y-P.z) * vecFog.z);
}
//////////////////////////////////////////////////////////////////////
struct TMULTI_VS_OUT // Output to the pixelshader fragment
{
float4 Pos : POSITION;
float4 Color: COLOR0;
float Fog: FOG;
float2 MaskCoord : TEXCOORD0;
float2 BaseCoord : TEXCOORD1;
float2 RedCoord : TEXCOORD2;
#ifdef GREENMASK
float2 GreenCoord : TEXCOORD3;
#endif
};
TMULTI_VS_OUT TMulti_VS(
float4 inPos : POSITION,
float3 inNormal : NORMAL,
float2 inTexCoord0 : TEXCOORD0)
{
TMULTI_VS_OUT Out;
// transform the vector position to screen coordinates
Out.Pos = mul(inPos,matWorldViewProj);
// rotate and normalize the normal
float3 N = normalize(mul(inNormal,matWorldInv));
//float3 N = normalize(inNormal);
float3 P = mul(inPos,matWorld);
// Add ambient and sun light
Out.Color = vecSkill41.w + DoSunLight(N);
// Add 6 dynamic lights (maximum for vs 1.1)
for (int i=0; i<6; i++)
Out.Color += DoPointLight(P,N,i);
// Add fog
Out.Fog = DoFog(inPos);
// scale the texture coordinates for the masked textures
Out.MaskCoord = inTexCoord0.xy;
Out.BaseCoord = inTexCoord0.xy * vecSkill41.x;
Out.RedCoord = inTexCoord0.xy * vecSkill41.y;
#ifdef GREENMASK
Out.GreenCoord = inTexCoord0.xy * vecSkill41.z;
#endif
return Out;
}
float4 TMulti_PS(TMULTI_VS_OUT In): COLOR
{
// retrieve the pixels for the textures and the masks
float4 MaskColor = tex2D(sMaskTex,In.MaskCoord);
float4 BaseColor = tex2D(sBaseTex,In.BaseCoord);
float4 RedColor = tex2D(sRedTex,In.RedCoord);
// blend the red and green textures over the base texture
#ifdef GREENMASK
float4 GreenColor = tex2D(sGreenTex,In.GreenCoord);
float4 BaseRed = lerp(BaseColor,RedColor,MaskColor.r);
float4 FinalColor = lerp(BaseRed,GreenColor,MaskColor.g);
#else
float4 FinalColor = lerp(BaseColor,RedColor,MaskColor.r);
#endif
// Add the vertex light or shadow map, plus the entity ambient
#ifdef SHADOWMAP
FinalColor *= MaskColor.b + vecSkill41.w;
#else
FinalColor *= In.Color;
#endif
FinalColor.a = 1.0f; // prevent transparency
return FinalColor;
}
technique tmulti3
{
pass one
{
sampler[0] = (sMaskTex);
sampler[1] = (sBaseTex);
sampler[2] = (sRedTex);
#ifdef GREENMASK
sampler[3] = (sGreenTex);
#endif
VertexShader = compile vs_1_1 TMulti_VS();
PixelShader = compile ps_1_1 TMulti_PS();
}
}
";
}
// C-Script stuff /////////////////////////////////////////////////////
#define ScaleSkin2,SKILL2;
#define ScaleSkin3,SKILL3;
#define ScaleSkin4,SKILL4;
// uses: ScaleSkin2 ScaleSkin3 ScaleSkin4
action terrain_multi3
{
if (d3d_shaderversion < 1111) {
if (ent_skins(my) >= 5) {
my.skin = 5; } // use skin 5 for non-shader hardware
return; }
my.material = mtl_terrainmulti3;
if (my.ScaleSkin2) {
my.skill41 = my.ScaleSkin2; }
else {
//entry: Skin2 default scale
//help: Number of tiles in x/y direction for Skin 2 (Base Texture).
//help: Set this to 1 for an untiled texture.
my.skill41 = 15; }
if (my.ScaleSkin3) {
my.skill42 = my.ScaleSkin3; }
else {
// entry: Skin3 default scale
// help: Number of tiles in x/y direction for Skin 3 (red masked texture).
my.skill42 = 15; }
if (my.ScaleSkin4) {
my.skill43 = my.ScaleSkin4; }
else {
// entry: Skin4 default scale
// help: Number of tiles in x/y direction for Skin 4 (green masked texture).
my.skill43 = 15; }
my.skill41 = float(my.skill41);
my.skill42 = float(my.skill42);
my.skill43 = float(my.skill43);
my.skill44 = float(my.ambient/100);
}