   Big FPS hit using shadow maps
  Hi,I have finally got shadow mapping up and running, after weeks of experimentation! I followed the approach used in 'gradient shadow mapping' from shaderX4.Here's the result:I've now got the unblurred shadow map (shown top left), plus per pixel and specular lighting. Unfortunately, my FPS has been hammered. I had about 50-60 fps before this, but the shadow map shader brings it right down to about 7fps. I then wrote a new technique which just does the shadows with diffuse pervertex lighting only, but this only took me up to 10fps.It seems the bottleneck is in the use of 6 texture lookups in the pixel shader( 5 for the gradient shadow map and 1 for the diffuse texture). Is this because my FX5200 is bad for PS_2_0?Heres the effect file anyway.....  #define SHADOW_SIZE 1024#define SHADOW_FILTERING LINEAR#define SHADOW_FOV 1#define INVPIXEL ( 1. / SHADOW_SIZE )#define RANGE_SCALE 12#define RANGE_OFFSET 0#define SHADOW_FMT "r32f"// --------------------------------------------------------------// Variables// --------------------------------------------------------------float4x4 ObjectToWorld: World < string UIWidget="None"; >;float4x4 ObjectToView: WorldView < string UIWidget="None"; >;float4x4 ObjectToClip: WorldViewProjection < string UIWidget="None"; >;float4x4 WorldToViewInverse : ViewInverse < string UIWidget="None"; >;float4x4 WorldToClip: ViewProjection < string UIWidget="None"; >;float4x4 WorldToLightClip: ViewProjection < string frustum = "light0"; >;float3 LightPos : Position  = {-1.0f, 1.0f, 0.0f};float3 LightDir = {0.5, 0.0, -0.5};float3 SkyColor : Ambient = {0.5f, 0.5f, 0.5f};float3 GroundColor : Ambient = {0.1f, 0.1f, 0.1f};half ShadowBias = 0.001; // 0.0float ShadowGradientScaleBias  = 0.001;  //0float ShadowFuzzyWidth  = 0.1; // 0.000float GradientClamp = 0.01;  // 0.01float SpecularExponent : SpecularPower = 12.0;// --------------------------------------------------------------// Render targets// --------------------------------------------------------------texture ShadowMap : RenderColorTarget//texture ShadowDepthTarget : RenderDepthStencilTargettexture Skin;sampler ShadowSampler = sampler_state {    texture = <ShadowMap>;    AddressU  = CLAMP;    AddressV = CLAMP;    MipFilter = NONE;    MinFilter = SHADOW_FILTERING;    MagFilter = SHADOW_FILTERING;};sampler SkinSampler = sampler_state {    texture = (Skin);    MIPFILTER = LINEAR;    MINFILTER = LINEAR;    MAGFILTER = LINEAR;};// -----------------------------------------------------------------------------// Structs// -----------------------------------------------------------------------------struct VertexIn{float4 Position: POSITION;float3 Normal: NORMAL;    float2 Tex: TEXCOORD0;};struct VSOUTPUT_SHADOW{float4 Position: POSITION;float ShadowmapDepth: TEXCOORD0;};struct VSOUTPUT_SCENE_HI{float4 Position: POSITION;float2 Tex: TEXCOORD0;half3 N: TEXCOORD1;half3 L: TEXCOORD2;half3 V: TEXCOORD3;float4 ShadowmapCoord: TEXCOORD4;};struct VSOUTPUT_SCENE_LO{float4 Position: POSITION;float2 Tex: TEXCOORD0;float4 Diffuse: TEXCOORD1;float4 ShadowmapCoord: TEXCOORD2;};// -----------------------------------------------------------------------------// Render to shadow map// -----------------------------------------------------------------------------VSOUTPUT_SHADOW VS_SHADOW( VertexIn In ){VSOUTPUT_SHADOW Out;float4 P = mul( In.Position, ObjectToWorld );Out.Position = mul( P, WorldToLightClip );Out.Position.xy *= SHADOW_FOV;// fix for DirectX rasterisation rules (OpenGL doesn't need this)Out.Position.xy += float2( - INVPIXEL, + INVPIXEL ) * Out.Position.w;Out.ShadowmapDepth = ( Out.Position.z - RANGE_OFFSET ) / RANGE_SCALE;    return Out;}float4 PS_SHADOW( VSOUTPUT_SHADOW In ) : COLOR{    return In.ShadowmapDepth;}// -----------------------------------------------------------------------------// Render shaded - High Quality: Specular and Per Pixel Lighting// -----------------------------------------------------------------------------VSOUTPUT_SCENE_HI VS_SCENE_HI( VertexIn In ){float4 P = mul( In.Position, ObjectToWorld );float3 N = mul( In.Normal, ObjectToWorld );VSOUTPUT_SCENE_HI Out;Out.Position = mul( P, WorldToClip );Out.N = N;Out.L = LightPos - P;Out.V = WorldToViewInverse[3] - P;Out.ShadowmapCoord = mul( P, WorldToLightClip );Out.ShadowmapCoord.xy = Out.ShadowmapCoord.xy * float2( .5, -.5 ) + .5 * Out.ShadowmapCoord.w;Out.ShadowmapCoord.z = ( Out.ShadowmapCoord.z - ShadowBias - RANGE_OFFSET ) / RANGE_SCALE; Out.Tex = In.Tex;    return Out;}half4 PS_SCENE_HI( VSOUTPUT_SCENE_HI In ) : COLOR{// point on shadowmapfloat2 shadowP = In.ShadowmapCoord.xy / In.ShadowmapCoord.w;  float centerdepth = tex2D( ShadowSampler, shadowP ).x;   // gradient calculation  float pixeloffset = INVPIXEL / 2;   float4 depths = float4(    tex2D( ShadowSampler, shadowP + float2( -pixeloffset, 0 ) ).x,    tex2D( ShadowSampler, shadowP + float2( +pixeloffset, 0 ) ).x,    tex2D( ShadowSampler, shadowP + float2( 0, -pixeloffset ) ).x,    tex2D( ShadowSampler, shadowP + float2( 0, +pixeloffset ) ).x );float2 differences = abs( depths.yw - depths.xz );float gradient = min( GradientClamp, max( differences.x, differences.y ) );// visibility functionfloat delta_z = centerdepth + gradient * ShadowGradientScaleBias - In.ShadowmapCoord.z;    float visibility = saturate( 1 + delta_z / ( gradient * ShadowFuzzyWidth ) );  // lighting modelhalf3 N = normalize( In.N );half3 V = normalize( In.V );half3 L = normalize( In.L );    half3 H = normalize( L + V );half3 dotNL = dot( N, L );half3 dotNH = dot( N, H );half3 lighting = lit( dotNL, dotNH, SpecularExponent );//half3 lightColor = visibility;// * LightColor;half SpecIntens = dotNL * sqrt( ( SpecularExponent + 1 ) / 2 );   half3 result = half3(0.3f, 0.3f, 0.3f);  // result += lerp( GroundColor, SkyColor, ( 1 + N.y ) / 2 );    result += visibility * lighting.y;    result += visibility * SpecIntens * lighting.z;    return (tex2D( SkinSampler, In.Tex ) * half4( result, 1 ) );  }    // -----------------------------------------------------------------------------// Render shaded - Low Quality: Per-Vertex Diffuse Lighting Only// -----------------------------------------------------------------------------VSOUTPUT_SCENE_LO VS_SCENE_LO( VertexIn In ){float3 L = -LightDir;VSOUTPUT_SCENE_LO Out;Out.Position = mul( In.Position, ObjectToClip );float3 N = mul( In.Normal, ObjectToView );Out.Diffuse = max(0, dot(N, L));// + g_ambient; Out.ShadowmapCoord = mul( P, WorldToLightClip );Out.ShadowmapCoord.xy = Out.ShadowmapCoord.xy * float2( .5, -.5 ) + .5 * Out.ShadowmapCoord.w;Out.ShadowmapCoord.z = ( Out.ShadowmapCoord.z - ShadowBias - RANGE_OFFSET ) / RANGE_SCALE; Out.Tex = In.Tex;    return Out;}half4 PS_SCENE_LO( VSOUTPUT_SCENE_LO In ) : COLOR{// point on shadowmapfloat2 shadowP = In.ShadowmapCoord.xy / In.ShadowmapCoord.w;  float centerdepth = tex2D( ShadowSampler, shadowP ).x;   // gradient calculation  float pixeloffset = INVPIXEL / 2;   float4 depths = float4(    tex2D( ShadowSampler, shadowP + float2( -pixeloffset, 0 ) ).x,    tex2D( ShadowSampler, shadowP + float2( +pixeloffset, 0 ) ).x,    tex2D( ShadowSampler, shadowP + float2( 0, -pixeloffset ) ).x,    tex2D( ShadowSampler, shadowP + float2( 0, +pixeloffset ) ).x );float2 differences = abs( depths.yw - depths.xz );float gradient = min( GradientClamp, max( differences.x, differences.y ) );// visibility functionfloat delta_z = centerdepth + gradient * ShadowGradientScaleBias - In.ShadowmapCoord.z;    float visibility = saturate( 1 + delta_z / ( gradient * ShadowFuzzyWidth ) );    half3 result = half3(0.3f, 0.3f, 0.3f);   result += visibility * In.Diffuse;  return (tex2D( SkinSampler, In.Tex ) * half4( result, 1 ) );  }// -----------------------------------------------------------------------------// Techniques// -----------------------------------------------------------------------------technique techShadow{pass p0 {VertexShader = compile vs_2_0 VS_SHADOW();ZEnable = true;ZWriteEnable = true;ZFunc = LessEqual;CullMode = none;PixelShader = compile ps_2_0 PS_SHADOW();}}technique techSceneHi{pass p0{VertexShader = compile vs_2_0 VS_SCENE_HI();ZEnable = true;ZWriteEnable = true;ZFunc = LessEqual;CullMode = none;PixelShader = compile ps_2_0 PS_SCENE_HI();}}technique techSceneLo{pass p0{VertexShader = compile vs_2_0 VS_SCENE_LO();ZEnable = true;ZWriteEnable = true;ZFunc = LessEqual;CullMode = none;PixelShader = compile ps_2_0 PS_SCENE_LO();}}Any speed enhancing recommendations welcome :)Simon   
  I'm not completely sure, but I think the main reason it is slow, is because the FX 5200 has poor pixel shader performance. Try and see your performance without the gradient calculation, taking only 1 sample.   ;  I've never used HLSL before. But the size of your texturemap looks insane :) Try a smaller resolution.   ;  The best way, IMO, to find out what's holding you back is to comment out sections of code and see how it affects performance. A good start would be commenting out all you pixel shaders, putting in return float4(1.0, 1.0, 1.0, 1.0) and seeing what happens. If you get a huge boost, it was the pixel shader output. Next you try the texture bandwidth. I normally reduce my textures by a factor of 16 (4 each way). If this boost performance, your texture bandwidth was holding you back.After that I move to vertex shader use. I either comment out sections of the VS doing stuff that isn't related to position (you want the same number of pixels drawn). If that doesn't help you either, you're probably CPU bound.Hope this helps :).   ;  Yes, it is the PS tex2D lookups which make the FX5200 have a nervous breakdown.I'm off shopping!One other problem.My Pixel Shader is taking the wrong approach. It tests against the shadowMap texture, but if the pixel is not within the frustrum of the light, it is shadowed.Really I want it lit when too far away!Simon   