struct pixelShaderInput { float4 Diffuse : COLOR0; float2 ShadowMapProjection : TEXCOORD0; float LightSpaceDepth : TEXCOORD1; }; sampler2D ShadowMapSampler; #define SM_SIZE 2048 float4 ps_LightPassBilin4x4PCF( pixelShaderInput Input ) : COLOR0 { float4 shadowMapVals[4]; float4 shadowMapWeights[4]; float2 shadowFractMap[4]={ { -(1/SM_SIZE), -(1/SM_SIZE) }, { (1/SM_SIZE), -(1/SM_SIZE) }, { -(1/SM_SIZE), (1/SM_SIZE) }, { (1/SM_SIZE), (1/SM_SIZE) } }; //fetch 4 2x2 quads shadowMapVals[0] = tex2D(ShadowMapSampler, Input.ShadowMapProjection + shadowFractMap[0] ); shadowMapVals[1] = tex2D(ShadowMapSampler, Input.ShadowMapProjection + shadowFractMap[1] ); shadowMapVals[2] = tex2D(ShadowMapSampler, Input.ShadowMapProjection + shadowFractMap[2] ); shadowMapVals[3] = tex2D(ShadowMapSampler, Input.ShadowMapProjection + shadowFractMap[3] ); //fraction component of projected coordinates; here 1024 represents the shadowmap size // float4 pFrac = frac( Input.ShadowMapProjection * float4( SM_SIZE, SM_SIZE, 0, 0 ) ); float2 pFrac = frac( Input.ShadowMapProjection.xy * float2( SM_SIZE, SM_SIZE ) ); // shaves 2 instructions // /* shadowMapWeights[0] = float4( 1, 1-pFrac.x, 1, 1-pFrac.x ); shadowMapWeights[0] *= float4( 1-pFrac.y, 1, 1, 1-pFrac.y ); shadowMapWeights[1] = float4( pFrac.x, 1, pFrac.x, 1 ); shadowMapWeights[1] *= float4( 1-pFrac.y, 1, 1, 1-pFrac.y ); shadowMapWeights[2] = float4( 1, 1-pFrac.x, 1, 1-pFrac.x ); shadowMapWeights[2] *= float4( 1, pFrac.y, pFrac.y, 1 ); shadowMapWeights[3] = float4( pFrac.x, 1, pFrac.x, 1 ); shadowMapWeights[3] *= float4( 1, pFrac.y, pFrac.y, 1 ); // */ /* compiler already opts to shadowMapWeights[0] = float4( 1-pFrac.y, 1-pFrac.x, 1, (1-pFrac.x) * (1-pFrac.y) ); shadowMapWeights[1] = float4( pFrac.x * (1-pFrac.y), 1, pFrac.x, 1-pFrac.y ); shadowMapWeights[2] = float4( 1, (1-pFrac.x) * pFrac.y, pFrac.y, 1-pFrac.x ); shadowMapWeights[3] = float4( pFrac.x, pFrac.y, pFrac.x * pFrac.y, 1 ); */ // projective distance from z plane in view coords //float dist = Input.LightSpaceDepth - 0.005; float fDepth = Input.LightSpaceDepth - 0.005; float4 inLight; float percentInLight; inLight = ( fDepth < shadowMapVals[0] ); percentInLight = dot(inLight, shadowMapWeights[0]); inLight = ( fDepth < shadowMapVals[1] ); percentInLight += dot(inLight, shadowMapWeights[1]); inLight = ( fDepth < shadowMapVals[2] ); percentInLight += dot(inLight, shadowMapWeights[2]); inLight = ( fDepth < shadowMapVals[3] ); percentInLight += dot(inLight, shadowMapWeights[3]); // (goboTexCoord, lightDist, lightVector, surfaceNormal) //sum of weights is 9 since border taps are bilinearly filtered //return ( (1.0f/9.0f) * percentInLight) * Input.Diffuse + float4( 0.25, 0.25, 0.25, 1.0 ); return ( (1.0f/9.0f) * percentInLight) * Input.Diffuse + float4( 0.25, 0.25, 0.25, 1.0 ); }