[EDIT]
Got this fixed, check out code + demo here:
http://forum.thegamecreators.com/?m=forum_view&t=208719&b=6&p=0
[/EDIT]
Hello!
OK, I've got this shader from EVOLVED:
(this is the original)
//====================================================
// Cubic Shadow Mapping
//====================================================
// By EVOLVED
// www.evolved-software.com
//====================================================
//--------------
// un-tweaks
//--------------
matrix WorldVP:WorldViewProjection;
matrix World:World;
matrix ViewInv:ViewInverse;
//--------------
// Tweaks
//--------------
float3 Ambient={0.1f,0.1f, 0.1f};
float4 LightPosition={0.0f,150.0f,0.0f,1.0f};
float3 LightColor={1.0f,1.0f,1.0f};
float LightRange=350.0f;
float4 FogColor={0.8f,0.8f,0.8f,1.0f};
float FogRange=2500.0f;
float Alpha=1.0f;
//--------------
// Textures
//--------------
texture BaseTX <string Name="";>;
sampler2D Base = sampler_state
{
texture = <BaseTX>;
};
texture NormalTX <string Name="";>;
sampler2D Normal = sampler_state
{
texture = <NormalTX>;
};
texture DepthMapTX <string Name="";>;
sampler DepthMap = sampler_state
{
Texture = <DepthMapTX>;
};
//--------------
// structs
//--------------
struct IN_Depth
{
float4 Pos:POSITION;
};
struct OUT_Depth
{
float4 OPos:POSITION;
float3 Depth:TEXCOORD1;
};
struct IN_NormalMap
{
float4 Pos:POSITION;
float2 UV:TEXCOORD;
float3 Normal:NORMAL;
float3 Tangent:TANGENT;
float3 Binormal:BINORMAL;
};
struct OUT_NormalMap
{
float4 OPos:POSITION;
float2 Tex:TEXCOORD0;
float3 LightVec:TEXCOORD1;
float3 Attenuation:TEXCOORD2;
float3 ViewVec:TEXCOORD3;
float3 ShadowMap:TEXCOORD4;
float Fog:FOG;
};
//--------------
// vertex shaders
//--------------
OUT_Depth VS_Depth(IN_Depth IN)
{
OUT_Depth OUT;
OUT.OPos = mul(IN.Pos,WorldVP);
float3 WPos=mul(IN.Pos,World);
float3 LightPos=LightPosition-WPos;
OUT.Depth=-(LightPos/LightRange);
return OUT;
}
OUT_NormalMap VS_NormalMap(IN_NormalMap IN)
{
OUT_NormalMap OUT;
OUT.OPos=mul(IN.Pos,WorldVP);
OUT.Tex=IN.UV;
float3x3 TBN={IN.Tangent,IN.Binormal,IN.Normal};
TBN=transpose(mul(TBN,World));
float3 WPos=mul(IN.Pos,World);
float3 LightPos=LightPosition-WPos;
float3 ViewPos=ViewInv[3].xyz-WPos;
OUT.LightVec=mul(LightPos,TBN);
OUT.Attenuation=-(LightPos/LightRange);
OUT.ViewVec=mul(ViewPos,TBN);
OUT.ShadowMap=-LightPos;
OUT.Fog=1-saturate(dot(ViewPos/FogRange,ViewPos/FogRange));
return OUT;
}
//--------------
// pixel shaders
//--------------
float4 PS_Depth(OUT_Depth IN) : COLOR
{
return float4(length(IN.Depth)+0.011f,0,0,1);
}
float4 PS_NormalMap(OUT_NormalMap IN) : COLOR
{
float4 Texture=tex2D(Base,IN.Tex);
float3 NormalMap=tex2D(Normal,IN.Tex)*2-1;
float3 LightV=normalize(IN.LightVec);
float3 ViewV=normalize(IN.ViewVec);
NormalMap=normalize(NormalMap);
float Normal=saturate(dot(reflect(-ViewV,NormalMap),LightV));
Normal=pow(Normal,16)+saturate(dot(NormalMap,LightV));
float3 Light=LightColor*(1-dot(IN.Attenuation,IN.Attenuation));
float Depth=length(IN.Attenuation);
float shadowmap=1-(texCUBE(DepthMap,IN.ShadowMap+float3(-0.8f,-0.8f,0.8f)) < Depth ? 0.111f:0.0f);
shadowmap=shadowmap-(texCUBE(DepthMap,IN.ShadowMap+float3(0.0f,-0.8f,-0.8f)) < Depth ? 0.111f:0.0f);
shadowmap=shadowmap-(texCUBE(DepthMap,IN.ShadowMap+float3(0.8f,-0.8f,0.0f)) < Depth ? 0.111f:0.0f);
shadowmap=shadowmap-(texCUBE(DepthMap,IN.ShadowMap+float3(-0.8f,0.0f,0.8f)) < Depth ? 0.111f:0.0f);
shadowmap=shadowmap-(texCUBE(DepthMap,IN.ShadowMap+float3(0.0f,0.0f,0.0f)) < Depth ? 0.111f:0.0f);
shadowmap=shadowmap-(texCUBE(DepthMap,IN.ShadowMap+float3(0.8f,0.0f,0.8f)) < Depth ? 0.111f:0.0f);
shadowmap=shadowmap-(texCUBE(DepthMap,IN.ShadowMap+float3(-0.8f,0.8f,0.0f)) < Depth ? 0.111f:0.0f);
shadowmap=shadowmap-(texCUBE(DepthMap,IN.ShadowMap+float3(0.0f,0.8f,0.8f)) < Depth ? 0.111f:0.0f);
shadowmap=shadowmap-(texCUBE(DepthMap,IN.ShadowMap+float3(0.8f,0.8f,-0.8f)) < Depth ? 0.111f:0.0f);
return float4(Texture*((Normal*Light*shadowmap)+Ambient),Texture.w*Alpha);
}
//--------------
// techniques
//--------------
technique DepthMap
{
pass p1
{
VertexShader = compile vs_2_0 VS_Depth();
PixelShader = compile ps_2_0 PS_Depth();
}
}
technique ShadowMapping
{
pass p1
{
vertexShader = compile vs_2_0 VS_NormalMap();
pixelShader = compile ps_2_0 PS_NormalMap();
FOGCOLOR=(FogColor);
FOGENABLE=TRUE;
}
}
Which does exactly what I want, but I Need more lights (4-6 would be good but when the method is known any number is possible)
I've been playing with it trying to add additional lights by using multiple passes:
//====================================================
// Cubic Shadow Mapping
//====================================================
// By EVOLVED
// www.evolved-software.com
//====================================================
//--------------
// un-tweaks
//--------------
matrix WorldVP:WorldViewProjection;
matrix World:World;
matrix ViewInv:ViewInverse;
//--------------
// Tweaks
//--------------
float3 Ambient={0.1f,0.1f, 0.1f};
float4 FogColor={0.8f,0.8f,0.8f,1.0f};
float FogRange=2500.0f;
float Alpha=1.0f;
//L0
float4 LPos_0={0.0f,150.0f,0.0f,1.0f};
float3 LCol_0={1.0f,1.0f,1.0f};
float LRng_0=350.0f;
//L1
float4 LPos_1={0.0f,150.0f,0.0f,1.0f};
float3 LCol_1={1.0f,1.0f,1.0f};
float LRng_1=350.0f;
//--------------
// Textures
//--------------
texture BaseTX <string Name="";>;
sampler2D Base = sampler_state
{
texture = <BaseTX>;
};
texture NormalTX <string Name="";>;
sampler2D Normal = sampler_state
{
texture = <NormalTX>;
};
texture DepthMapTX_0 <string Name="";>;
sampler DepthMap_0 = sampler_state
{
Texture = <DepthMapTX_0>;
};
texture DepthMapTX_1 <string Name="";>;
sampler DepthMap_1 = sampler_state
{
Texture = <DepthMapTX_1>;
};
//--------------
// structs
//--------------
struct IN_Depth
{
float4 Pos:POSITION;
};
struct OUT_Depth
{
float4 OPos:POSITION;
float3 Depth:TEXCOORD1;
};
struct IN_NormalMap
{
float4 Pos:POSITION;
float2 UV:TEXCOORD;
float3 Normal:NORMAL;
float3 Tangent:TANGENT;
float3 Binormal:BINORMAL;
};
struct OUT_NormalMap
{
float4 OPos:POSITION;
float2 Tex:TEXCOORD0;
float3 LightVec:TEXCOORD1;
float3 Attenuation:TEXCOORD2;
float3 ViewVec:TEXCOORD3;
float3 ShadowMap:TEXCOORD4;
float Fog:FOG;
};
//--------------
// vertex shaders
//--------------
OUT_Depth VS_Light0(IN_Depth IN)
{
OUT_Depth OUT;
OUT.OPos = mul(IN.Pos,WorldVP);
float3 WPos=mul(IN.Pos,World);
float3 LightPos=LPos_0-WPos;
OUT.Depth=-(LightPos/LRng_0);
return OUT;
}
OUT_Depth VS_Light1(IN_Depth IN)
{
OUT_Depth OUT;
OUT.OPos = mul(IN.Pos,WorldVP);
float3 WPos=mul(IN.Pos,World);
float3 LightPos=LPos_1-WPos;
OUT.Depth=-(LightPos/LRng_1);
return OUT;
}
OUT_NormalMap VS_NormalMap_L0(IN_NormalMap IN)
{
OUT_NormalMap OUT;
OUT.OPos=mul(IN.Pos,WorldVP);
OUT.Tex=IN.UV;
float3x3 TBN={IN.Tangent,IN.Binormal,IN.Normal};
TBN=transpose(mul(TBN,World));
float3 WPos=mul(IN.Pos,World);
float3 LightPos=LPos_0-WPos;
float3 ViewPos=ViewInv[3].xyz-WPos;
OUT.LightVec=mul(LightPos,TBN);
OUT.Attenuation=-(LightPos/LRng_0);
OUT.ViewVec=mul(ViewPos,TBN);
OUT.ShadowMap=-LightPos;
OUT.Fog=1-saturate(dot(ViewPos/FogRange,ViewPos/FogRange));
return OUT;
}
OUT_NormalMap VS_NormalMap_L1(IN_NormalMap IN)
{
OUT_NormalMap OUT;
OUT.OPos=mul(IN.Pos,WorldVP);
OUT.Tex=IN.UV;
float3x3 TBN={IN.Tangent,IN.Binormal,IN.Normal};
TBN=transpose(mul(TBN,World));
float3 WPos=mul(IN.Pos,World);
float3 LightPos=LPos_1-WPos;
float3 ViewPos=ViewInv[3].xyz-WPos;
OUT.LightVec=mul(LightPos,TBN);
OUT.Attenuation=-(LightPos/LRng_1);
OUT.ViewVec=mul(ViewPos,TBN);
OUT.ShadowMap=-LightPos;
OUT.Fog=1-saturate(dot(ViewPos/FogRange,ViewPos/FogRange));
return OUT;
}
//--------------
// pixel shaders
//--------------
float4 PS_Light0(OUT_Depth IN) : COLOR
{
return float4(length(IN.Depth)+0.011f,0,0,1);
}
float4 PS_Light1(OUT_Depth IN) : COLOR
{
return float4(length(IN.Depth)+0.011f,0,0,1);
}
float4 PS_NormalMap_L0(OUT_NormalMap IN) : COLOR
{
float4 Texture=tex2D(Base,IN.Tex);
float3 NormalMap=tex2D(Normal,IN.Tex)*2-1;
float3 LightV=normalize(IN.LightVec);
float3 ViewV=normalize(IN.ViewVec);
NormalMap=normalize(NormalMap);
float Normal=saturate(dot(reflect(-ViewV,NormalMap),LightV));
Normal=pow(Normal,16)+saturate(dot(NormalMap,LightV));
float3 Light=LCol_0*(1-dot(IN.Attenuation,IN.Attenuation));
float Depth=length(IN.Attenuation);
float shadowmap=1-(texCUBE(DepthMap_0,IN.ShadowMap+float3(-0.8f,-0.8f,0.8f)) < Depth ? 0.111f:0.0f);
shadowmap=shadowmap-(texCUBE(DepthMap_0,IN.ShadowMap+float3(0.0f,-0.8f,-0.8f)) < Depth ? 0.111f:0.0f);
shadowmap=shadowmap-(texCUBE(DepthMap_0,IN.ShadowMap+float3(0.8f,-0.8f,0.0f)) < Depth ? 0.111f:0.0f);
shadowmap=shadowmap-(texCUBE(DepthMap_0,IN.ShadowMap+float3(-0.8f,0.0f,0.8f)) < Depth ? 0.111f:0.0f);
shadowmap=shadowmap-(texCUBE(DepthMap_0,IN.ShadowMap+float3(0.0f,0.0f,0.0f)) < Depth ? 0.111f:0.0f);
shadowmap=shadowmap-(texCUBE(DepthMap_0,IN.ShadowMap+float3(0.8f,0.0f,0.8f)) < Depth ? 0.111f:0.0f);
shadowmap=shadowmap-(texCUBE(DepthMap_0,IN.ShadowMap+float3(-0.8f,0.8f,0.0f)) < Depth ? 0.111f:0.0f);
shadowmap=shadowmap-(texCUBE(DepthMap_0,IN.ShadowMap+float3(0.0f,0.8f,0.8f)) < Depth ? 0.111f:0.0f);
shadowmap=shadowmap-(texCUBE(DepthMap_0,IN.ShadowMap+float3(0.8f,0.8f,-0.8f)) < Depth ? 0.111f:0.0f);
return float4(Texture*((Normal*Light*shadowmap)+Ambient),Texture.w*Alpha);
}
float4 PS_NormalMap_L1(OUT_NormalMap IN) : COLOR
{
float4 Texture=tex2D(Base,IN.Tex);
float3 NormalMap=tex2D(Normal,IN.Tex)*2-1;
float3 LightV=normalize(IN.LightVec);
float3 ViewV=normalize(IN.ViewVec);
NormalMap=normalize(NormalMap);
float Normal=saturate(dot(reflect(-ViewV,NormalMap),LightV));
Normal=pow(Normal,16)+saturate(dot(NormalMap,LightV));
float3 Light=LCol_1*(1-dot(IN.Attenuation,IN.Attenuation));
float Depth=length(IN.Attenuation);
float shadowmap=1-(texCUBE(DepthMap_1,IN.ShadowMap+float3(-0.8f,-0.8f,0.8f)) < Depth ? 0.111f:0.0f);
shadowmap=shadowmap-(texCUBE(DepthMap_1,IN.ShadowMap+float3(0.0f,-0.8f,-0.8f)) < Depth ? 0.111f:0.0f);
shadowmap=shadowmap-(texCUBE(DepthMap_1,IN.ShadowMap+float3(0.8f,-0.8f,0.0f)) < Depth ? 0.111f:0.0f);
shadowmap=shadowmap-(texCUBE(DepthMap_1,IN.ShadowMap+float3(-0.8f,0.0f,0.8f)) < Depth ? 0.111f:0.0f);
shadowmap=shadowmap-(texCUBE(DepthMap_1,IN.ShadowMap+float3(0.0f,0.0f,0.0f)) < Depth ? 0.111f:0.0f);
shadowmap=shadowmap-(texCUBE(DepthMap_1,IN.ShadowMap+float3(0.8f,0.0f,0.8f)) < Depth ? 0.111f:0.0f);
shadowmap=shadowmap-(texCUBE(DepthMap_1,IN.ShadowMap+float3(-0.8f,0.8f,0.0f)) < Depth ? 0.111f:0.0f);
shadowmap=shadowmap-(texCUBE(DepthMap_1,IN.ShadowMap+float3(0.0f,0.8f,0.8f)) < Depth ? 0.111f:0.0f);
shadowmap=shadowmap-(texCUBE(DepthMap_1,IN.ShadowMap+float3(0.8f,0.8f,-0.8f)) < Depth ? 0.111f:0.0f);
return float4(Texture*((Normal*Light*shadowmap)+Ambient),Texture.w*Alpha);
}
//--------------
// techniques
//--------------
technique DepthMap_L0
{
pass p1
{
VertexShader = compile vs_2_0 VS_Light0();
PixelShader = compile ps_2_0 PS_Light0();
}
}
//2 lights
technique DepthMap_L1
{
pass p1
{
VertexShader = compile vs_2_0 VS_Light1();
PixelShader = compile ps_2_0 PS_Light1();
}
}
technique ShadowMapping_L0
{
pass p1
{
vertexShader = compile vs_2_0 VS_NormalMap_L0();
pixelShader = compile ps_2_0 PS_NormalMap_L0();
FOGCOLOR=(FogColor);
FOGENABLE=TRUE;
}
}
technique ShadowMapping_L1
{
pass p1
{
vertexShader = compile vs_2_0 VS_NormalMap_L0();
pixelShader = compile ps_2_0 PS_NormalMap_L0();
// FOGCOLOR=(FogColor);
// FOGENABLE=TRUE;
}
pass p2
{
vertexShader = compile vs_2_0 VS_NormalMap_L1();
pixelShader = compile ps_2_0 PS_NormalMap_L1();
AlphaBlendEnable = True;
// SrcBlend = One;
// DestBlend = One;
// FOGCOLOR=(FogColor);
// FOGENABLE=TRUE;
}
}
However, using this the object is shaded by one light (light 1) while its shadow is made by the other light (light 0), the normal mapping works properly for both lights.
I think it would be better to pass both shadow maps (from light0 and light1) through the vertex shader to the Pixel shader and mix them there instead of doing 2 passes, however, when I make any Change to the 'OUT_NormalMap' structure the shader stops working
Code & media attached.
So, my questions are:
1. Which is the best way to do this?
2. Why can't I add variables to the 'OUT_NormalMap' structure?
3. Does anyone know of a good Editor for shaders (currently I'm using Notepad! lol. )?
Thanks,
Bruce