@GG I've added normal mapping to your shadow shader/with alpha. I am having a few issues with it. I don't understand how you are calculating the depth. I thought all you did for depth was ouput the Z value to a texture. Your doing something I don't quite understand yet. Is there anyway to change this to something like -
float4 worldPosition = mul(float4(input.Position.xyz,1), World);
output.Depth.x = output.Position.z;
output.Depth.y = output.Position.w;
//or
output.Depth = input.Depth.x / input.Depth.y;
//and then reconstruct like this?
//read depth
float depthVal = tex2D(depthSampler,texCoord).r;
I could be wrong but I think that would be a better way to go about it. I'm not really a master of shaders yet, but I'm getting much better.
I was wondering if you could explain in words, the step by step process that is happening with this shader. Well anyways any help would be very useful. If I didn't do the normal mapping correctly please feel free to adjust any bad code.
HERE IS THE SHADER:
// Green Gandalf's basic shadow mapping shader with alpha mapping
// Created 21 October 2009, edited 23 October 2009.
// Uses ideas and some code from:
// MS DX9 SDK shadow mapping demo "ShadowMap.fx"
// nVidia shadow mapping demo "shadRPortHW.fx"
// EVOLVED's shadow mapping demo "ShadowMapping.fx"
// plus some suggestions from Math89.
// Tested using DBPro objects with "set object transparency objId, 6".
float4x4 wvp : WorldViewProjection;
float4x4 mw : World;
float4x4 winv : WorldInverse;
float4x4 lightProjMatrix : LightViewProjection;
float4x4 texMat = { 0.5, 0.0, 0.0, 0.5,
0.0,-0.5, 0.0, 0.5,
0.0, 0.0, 0.5, 0.5,
0.0, 0.0, 0.0, 1.0};
float4 filterSamples[16] = {-1.5, -1.5, 0.0, 0.0,
-0.5, -1.5, 0.0, 0.0,
0.5, -1.5, 0.0, 0.0,
1.5, -1.5, 0.0, 0.0,
-1.5, -0.5, 0.0, 0.0,
-0.5, -0.5, 0.0, 0.0,
0.5, -0.5, 0.0, 0.0,
1.5, -0.5, 0.0, 0.0,
-1.5, 0.5, 0.0, 0.0,
-0.5, 0.5, 0.0, 0.0,
0.5, 0.5, 0.0, 0.0,
1.5, 0.5, 0.0, 0.0,
-1.5, 1.5, 0.0, 0.0,
-0.5, 1.5, 0.0, 0.0,
0.5, 1.5, 0.0, 0.0,
1.5, 1.5, 0.0, 0.0
};
//float shadowMapSize = 512.0;
//float filterWidth = 0.001953125; // = 1.0/512;
float shadowMapSize = 1024.0;
//float filterWidth = 0.0009765625;// = 1.0/1024.0;
//float shadowMapSize = 2048.0;
float4 ambient = {0.5, 0.5, 0.5, 1.0};
float4 lightCol = {1.0, 1.0, 1.0, 1.0};
float4 lightDir = {0.0f, -1.0f, 0.0f, 1.0f};
float4 lightPos = {0.0, 0.0, 0.0, 0.001}; // 4th entry is reciprocal of light range
float nearDist = 0.0; // estimate of distance of closest object to the light
float lightProjScale = 0.002; // reciprocal of max likely distance of shadow from light less nearDist (default 500 - 0)
float alphaMin = 0.1;
float specLevel = 0.025;
float specExpon=1.0;
texture baseTexture < string ResourceName=""; >;
sampler baseSample = sampler_state
{ texture = <baseTexture>;
minFilter = linear;
magFilter = linear;
mipFilter = linear;
addressU = wrap;
addressV = wrap;
};
texture baseNormal < string ResourceName=""; >;
sampler normalSample = sampler_state
{ texture = <baseNormal>;
minFilter = linear;
magFilter = linear;
mipFilter = linear;
addressU = wrap;
addressV = wrap;
};
sampler baseSampleAlpha = sampler_state
{ texture = <baseTexture>;
minFilter = linear;
magFilter = linear;
mipFilter = linear; // default mipmapping makes alpha mapped leaves disappear in the distance
addressU = wrap;
addressV = wrap;
};
texture shadowMap < string ResourceName=""; >;
sampler depthSample = sampler_state
{ texture = <shadowMap>;
minFilter = none;
magFilter = none;
mipFilter = none;
addressU = clamp;
addressV = clamp;
};
struct VSInput
{ float4 pos : position;
float2 UV : texcoord0;
float3 normal : normal;
float3 Tangent : TANGENT;
float3 Binormal : BINORMAL;
};
struct VSOutDepth
{ float4 pos : position;
float depth : texcoord0;
float2 UV : texcoord1;
};
struct VSOutScene
{ float4 pos : position;
float2 UV : texcoord0;
float4 lightProj : texcoord1;
float3 normal : texcoord2;
float depth : texcoord3;
float3 lightDir : texcoord4;
float3 Light : TEXCOORD5;
float3 View : TEXCOORD6;
};
struct PSOutput { float4 col : color; };
VSOutDepth VSDepth( VSInput In, VSOutDepth Out )
{ float4 sPos = mul(In.pos, wvp);
Out.pos = sPos;
Out.depth = (sPos.z - nearDist) * lightProjScale; // try to aim for values in range 0.0 to 1.0
// float4 WPosP = mul(In.pos,mw);
// float4 Proj = mul(sPos,ProjMatrix);
//Out.depth = Proj.z;
return Out;
}
VSOutDepth VSDepthAlpha( VSInput In, VSOutDepth Out )
{ float4 sPos = mul(In.pos, wvp);
Out.pos = sPos;
Out.depth = (sPos.z - nearDist) * lightProjScale; // try to aim for values in range 0.0 to 1.0
Out.UV = In.UV;
return Out;
}
VSOutScene VSScene( VSInput In, VSOutScene Out )
{ Out.pos = mul(In.pos, wvp);
Out.UV = In.UV;
float4 wPos = mul(In.pos, mw);
float4 lightProj = mul(wPos, lightProjMatrix);
Out.lightProj = mul(texMat, lightProj); // convert to coords for projective texture lookup
Out.normal = mul(In.normal, (float3x3) mw );
Out.depth = (Out.lightProj.z - nearDist) * lightProjScale - 0.01;
Out.lightDir = lightPos.xyz - wPos.xyz;
float3x3 TSM = {In.Tangent,In.Binormal,In.normal};
TSM=transpose(TSM);
float3 temp=-mul(lightDir.xyz,winv);
Out.Light=mul(temp,TSM);
temp=mul(lightPos,winv)-In.pos;
Out.View=mul(temp,TSM);
return Out;
}
PSOutput PSDepth( VSOutDepth In, PSOutput Out)
{ Out.col = In.depth;
return Out;
}
PSOutput PSDepthAlpha( VSOutDepth In, PSOutput Out)
{ float alpha = tex2D(baseSampleAlpha, In.UV).a;
clip(alpha - alphaMin);
Out.col = float4 (In.depth.xxx, 1.0);
return Out;
}
PSOutput PSScene0( VSOutScene In, PSOutput Out)
{ // no filtering of shadow edges
float4 base = tex2D(baseSample, In.UV);
float shadow = tex2Dproj(depthSample, In.lightProj).r < In.depth ? 0.0 : 1.0;
float attenuation = saturate(1.0 - length(In.lightDir) * lightPos.w);
//float diffuse = saturate(dot(normalize(In.lightDir), normalize(In.normal))) * attenuation;
float3 normal = 2 * tex2D(normalSample, In.UV) - 1.0;
float3 tempLightDir = normalize(In.Light);
float3 tempViewDir = normalize(In.View);
float diffuse = saturate(dot(normal, tempLightDir));
float3 reflect = 2 * diffuse * normal - tempLightDir;
float specular = diffuse * specLevel * pow(saturate(dot(reflect, tempViewDir)),specExpon);
Out.col = saturate( base * (ambient + diffuse * lightCol* shadow ) +specular );
return Out;
}
PSOutput PSScene0Alpha( VSOutScene In, PSOutput Out)
{ // no filtering of shadow edges
float4 base = tex2D(baseSampleAlpha, In.UV);
float shadow = tex2Dproj(depthSample, In.lightProj).r < In.depth ? 0.0 : 1.0;
float attenuation = saturate(1.0 - length(In.lightDir) * lightPos.w);
//float diffuse = saturate(dot(normalize(In.lightDir), normalize(In.normal))) * attenuation;
// float specular = diffuse * specLevel * pow(saturate(dot(reflect, tempViewDir)),specExpon);
///float4 light = saturate(lightCol * diffuse * shadow + ambient);
//Out.col = float4(base.rgb * light.rgb, base.a);
float3 normal = 2 * tex2D(normalSample, In.UV) - 1.0;
float3 tempLightDir = normalize(In.Light);
float3 tempViewDir = normalize(In.View);
float diffuse = saturate(dot(normal, tempLightDir));
float3 reflect = 2 * diffuse * normal - tempLightDir;
float specular = diffuse * specLevel * pow(saturate(dot(reflect, tempViewDir)),specExpon);
Out.col = saturate( base * (ambient + diffuse * lightCol* shadow ) +specular );
return Out;
}
PSOutput PSScene8( VSOutScene In, PSOutput Out)
{ // 4x4 PCF with bi-linear filtered shadow map lookup
float4 base = tex2D(baseSample, In.UV);
float2 texelPos = shadowMapSize * In.lightProj.xy / In.lightProj.w + float2(-0.5, 0.5) ;
float2 lerps = frac( texelPos );
// start with central 4 texels
float offsetScale = 1.0/shadowMapSize * In.lightProj.w;
float shadow = (tex2Dproj(depthSample, In.lightProj + filterSamples[5] * offsetScale).r < In.depth ? 1.0 : 0.0)
+ (tex2Dproj(depthSample, In.lightProj + filterSamples[6] * offsetScale).r < In.depth ? 1.0 : 0.0)
+ (tex2Dproj(depthSample, In.lightProj + filterSamples[9] * offsetScale).r < In.depth ? 1.0 : 0.0)
+ (tex2Dproj(depthSample, In.lightProj + filterSamples[10] * offsetScale).r < In.depth ? 1.0 : 0.0);
// next add in the 4 corners
float a1 = lerp(tex2Dproj(depthSample, In.lightProj + filterSamples[0] * offsetScale).r < In.depth ? 1.0 : 0.0,
tex2Dproj(depthSample, In.lightProj + filterSamples[3] * offsetScale).r < In.depth ? 1.0 : 0.0,
lerps.x);
float a2 = lerp(tex2Dproj(depthSample, In.lightProj + filterSamples[12] * offsetScale).r < In.depth ? 1.0 : 0.0,
tex2Dproj(depthSample, In.lightProj + filterSamples[15] * offsetScale).r < In.depth ? 1.0 : 0.0,
lerps.x);
shadow += lerp(a1, a2, lerps.y);
// now add left and right edges
a1 = (tex2Dproj(depthSample, In.lightProj + filterSamples[4] * offsetScale).r < In.depth ? 1.0 : 0.0)
+ (tex2Dproj(depthSample, In.lightProj + filterSamples[8] * offsetScale).r < In.depth ? 1.0 : 0.0);
a2 = (tex2Dproj(depthSample, In.lightProj + filterSamples[7] * offsetScale).r < In.depth ? 1.0 : 0.0)
+ (tex2Dproj(depthSample, In.lightProj + filterSamples[11] * offsetScale).r < In.depth ? 1.0 : 0.0);
shadow += lerp(a1, a2, lerps.x);
// finally add in top and bottom edges
a1 = (tex2Dproj(depthSample, In.lightProj + filterSamples[1] * offsetScale).r < In.depth ? 1.0 : 0.0)
+ (tex2Dproj(depthSample, In.lightProj + filterSamples[2] * offsetScale).r < In.depth ? 1.0 : 0.0);
a2 = (tex2Dproj(depthSample, In.lightProj + filterSamples[13] * offsetScale).r < In.depth ? 1.0 : 0.0)
+ (tex2Dproj(depthSample, In.lightProj + filterSamples[14] * offsetScale).r < In.depth ? 1.0 : 0.0);
shadow += lerp(a1, a2, lerps.y);
// calculate weighted mean
//invert shadow and lighten to make it look correct
shadow = 1.0 - shadow * 0.111111111;
float3 normal = 2 * tex2D(normalSample, In.UV) - 1.0;
float3 tempLightDir = normalize(In.Light);
float3 tempViewDir = normalize(In.View);
float diffuse = saturate(dot(normal, tempLightDir));
float3 reflect = 2 * diffuse * normal - tempLightDir;
float specular = diffuse * specLevel * pow(saturate(dot(reflect, tempViewDir)),specExpon);
Out.col = saturate( base * (ambient + diffuse * lightCol * shadow) +specular );
return Out;
}
PSOutput PSScene8Alpha( VSOutScene In, PSOutput Out)
{ // 4x4 PCF with bi-linear filtered shadow map lookup
float4 base = tex2D(baseSampleAlpha, In.UV);
float2 texelPos = shadowMapSize * In.lightProj.xy / In.lightProj.w + float2(-0.5, 0.5) ;
float2 lerps = frac( texelPos );
// start with central 4 texels
float offsetScale = 1.0/shadowMapSize * In.lightProj.w;
float shadow = (tex2Dproj(depthSample, In.lightProj + filterSamples[5] * offsetScale).r < In.depth ? 1.0 : 0.0)
+ (tex2Dproj(depthSample, In.lightProj + filterSamples[6] * offsetScale).r < In.depth ? 1.0 : 0.0)
+ (tex2Dproj(depthSample, In.lightProj + filterSamples[9] * offsetScale).r < In.depth ? 1.0 : 0.0)
+ (tex2Dproj(depthSample, In.lightProj + filterSamples[10] * offsetScale).r < In.depth ? 1.0 : 0.0);
// next add in the 4 corners
float a1 = lerp(tex2Dproj(depthSample, In.lightProj + filterSamples[0] * offsetScale).r < In.depth ? 1.0 : 0.0,
tex2Dproj(depthSample, In.lightProj + filterSamples[3] * offsetScale).r < In.depth ? 1.0 : 0.0,
lerps.x);
float a2 = lerp(tex2Dproj(depthSample, In.lightProj + filterSamples[12] * offsetScale).r < In.depth ? 1.0 : 0.0,
tex2Dproj(depthSample, In.lightProj + filterSamples[15] * offsetScale).r < In.depth ? 1.0 : 0.0,
lerps.x);
shadow += lerp(a1, a2, lerps.y);
// now add left and right edges
a1 = (tex2Dproj(depthSample, In.lightProj + filterSamples[4] * offsetScale).r < In.depth ? 1.0 : 0.0)
+ (tex2Dproj(depthSample, In.lightProj + filterSamples[8] * offsetScale).r < In.depth ? 1.0 : 0.0);
a2 = (tex2Dproj(depthSample, In.lightProj + filterSamples[7] * offsetScale).r < In.depth ? 1.0 : 0.0)
+ (tex2Dproj(depthSample, In.lightProj + filterSamples[11] * offsetScale).r < In.depth ? 1.0 : 0.0);
shadow += lerp(a1, a2, lerps.x);
// finally add in top and bottom edges
a1 = (tex2Dproj(depthSample, In.lightProj + filterSamples[1] * offsetScale).r < In.depth ? 1.0 : 0.0)
+ (tex2Dproj(depthSample, In.lightProj + filterSamples[2] * offsetScale).r < In.depth ? 1.0 : 0.0);
a2 = (tex2Dproj(depthSample, In.lightProj + filterSamples[13] * offsetScale).r < In.depth ? 1.0 : 0.0)
+ (tex2Dproj(depthSample, In.lightProj + filterSamples[14] * offsetScale).r < In.depth ? 1.0 : 0.0);
shadow += lerp(a1, a2, lerps.y);
// calculate weighted mean
shadow = 1.0 - shadow * 0.111111111;
// float attenuation = saturate(1.0 - length(In.lightDir) * lightPos.w);
//float diffuse = saturate(dot(normalize(In.lightDir), normalize(In.normal))) * attenuation;
//float4 light = saturate(lightCol * diffuse * shadow + ambient);
//Out.col = float4 (base.rgb * light.rgb, base.a);
float3 normal = 2 * tex2D(normalSample, In.UV) - 1.0;
float3 tempLightDir = normalize(In.Light);
float3 tempViewDir = normalize(In.View);
float diffuse = saturate(dot(normal, tempLightDir));
float3 reflect = 2 * diffuse * normal - tempLightDir;
float specular = diffuse * specLevel * pow(saturate(dot(reflect, tempViewDir)),specExpon);
//Out.col = saturate( base * (ambient + diffuse * lightCol* shadow ) + specular * lightCol);
//Out.col = saturate( base * (ambient + diffuse * lightCol* shadow ) +specular* lightCol );
Out.col = saturate( base * (ambient + diffuse * lightCol* shadow ) +specular );
return Out;
}
technique shadow
{ pass p1
{ vertexShader = compile vs_2_0 VSDepth();
pixelShader = compile ps_2_0 PSDepth();
}
}
technique shadowAlpha
{ pass p1
{ vertexShader = compile vs_2_0 VSDepthAlpha();
pixelShader = compile ps_2_0 PSDepthAlpha();
}
}
technique scene0
// unfiltered shadow map lookup
{ pass p1
{ vertexShader = compile vs_2_0 VSScene();
pixelShader = compile ps_2_0 PSScene0();
}
}
technique scene8
// 4x4 PCF with bi-linear filtered shadow map lookup
{ pass p1
{ vertexShader = compile vs_2_0 VSScene();
pixelShader = compile ps_2_a PSScene8();
}
}
technique scene0Alpha
// unfiltered shadow map lookup
{ pass p1
{ vertexShader = compile vs_2_0 VSScene();
pixelShader = compile ps_2_0 PSScene0Alpha();
}
}
technique scene8Alpha
// 4x4 PCF with bi-linear filtered shadow map lookup
{ pass p1
{ vertexShader = compile vs_2_0 VSScene();
pixelShader = compile ps_2_a PSScene8Alpha();
}
}
Thanks for any help