struct VS_INPUT
{
float4 Position : POSITION;
float3 Normal : NORMAL;
float2 UV : TEXCOORD0;
};
struct VS_OUTPUT
{
float4 Position : POSITION;
float3 Pos : TEXCOORD0;
float3 Normal : TEXCOORD1;
float2 UV : TEXCOORD2;
float2 Scaled : TEXCOORD3;
float2 Clouds : TEXCOORD4;
};
VS_OUTPUT main_vp
(
VS_INPUT i,
uniform float4x4 worldViewProj,
uniform float4x4 world,
uniform float cloudtime
)
{
VS_OUTPUT o;
//Calculate output position
o.Position = mul(worldViewProj, i.Position);
//hand over uvs to pixel shader
o.UV = i.UV;
o.Scaled = i.UV * 512;
//hand over input position and normal to pixel shader
o.Pos = i.Position;
o.Normal = i.Normal;
//Calculate new uvs for fake scattering
float4 tmp = mul(world, i.Position);
o.Clouds.x = (tmp.x+10000)/5000 + (cloudtime/320.0f);
o.Clouds.y = (tmp.z+10000)/5000 + (cloudtime/160.0f);
return o;
}
float4 main_fp
(
VS_OUTPUT i,
//get the 3 nearest lights
uniform float3 lightDiffuse,
uniform float4 lightAtt,
uniform float4 LightPos,
uniform float3 lightDiffuse2,
uniform float4 lightAtt2,
uniform float4 LightPos2,
uniform float3 lightDiffuse3,
uniform float4 lightAtt3,
uniform float4 LightPos3,
//ambientlight color
uniform float4 ambient,
//input textures
uniform sampler2D ground : register(s0),
uniform sampler2D splat1 : register(s1),
uniform sampler2D splat2 : register(s2),
uniform sampler2D splat3 : register(s3),
uniform sampler2D splat4 : register(s4),
uniform sampler2D coverage : register(s5),
uniform sampler2D colerage : register(s6),
uniform sampler2D cloudTex : register(s7)
): COLOR0
{
//We love ogre workaround (normaly the paramters should go directly into an array)
float3 alightDiffuse[3] = {lightDiffuse,lightDiffuse2,lightDiffuse3};
float4 alightAtt[3] = {lightAtt,lightAtt2,lightAtt3};
float4 aLightPos[3] = {LightPos,LightPos2,LightPos3};
//Read in textures for splatintensity and color modulation
float4 coveragemap = tex2D(coverage, i.UV);
float4 coleragemap = tex2D(colerage, i.UV);
float4 wolken = tex2D(cloudTex, i.Clouds);
//Splat textures TEX1 is the ground texture which is splatted all over the ground
float4 TEX1 = tex2D(ground, i.Scaled);
float4 TEX2 = tex2D(splat1, i.Scaled);
float4 TEX3 = tex2D(splat2, i.Scaled);
float4 TEX4 = tex2D(splat3, i.Scaled);
float4 TEX5 = tex2D(splat4, i.Scaled);
float3 normal = normalize(i.Normal);
//Blend textures with intensity and alpha channel
float4 diffColor = lerp(lerp(lerp(lerp(TEX1,TEX2,coveragemap.r*TEX2.a),TEX3,coveragemap.g*TEX3.a),TEX4,coveragemap.b*TEX4.a),TEX5,coveragemap.a*TEX5.a);
//add ambient light and color blending
float4 oColor = diffColor * ambient * coleragemap;
//for every light calculate diffuse lighting
for (int j = 0; j < 3; j++)
{
if (any(alightDiffuse[j]))
{
//Ogre stores type of light in the .w component 0 = directional Lights (POS=DIRECTION), 1 = point lights
float3 lightDir = aLightPos[j].xyz - (i.Pos * aLightPos[j].w);
float dist = length(lightDir);
lightDir = normalize(lightDir);
float iD = saturate(dot(normal, lightDir));
//calculate pointlight attenuation
float att = 1 / (alightAtt[j].y + alightAtt[j].z * dist + alightAtt[j].w * dist * dist);
//add light
oColor.rgb += att * (diffColor.rgb * alightDiffuse[j] * iD);
}
}
//modulate clouds shadows
oColor *= wolken;
return saturate(oColor);
}