float2 res : register(c0); sampler2D colorSampler : register(s0); sampler2D depthSampler : register(s1); sampler2D blurSampler : register(s4); // Tweakables static float g_fRadius = 0.005f; static float g_fLowRadiusScaling = 0.4f; static float g_fNearPlane = 1.0f; static float g_fFocalPlane = 8.0f; static float g_fFarPlane = 128.0f; static float g_fMaxDistBlur = 0.45f; static const float2 vPoissonDisc[] = { float2(-0.326212f, -0.40581f), float2(-0.840144f, -0.07358f), float2(-0.695914f, 0.457137f), float2(-0.203345f, 0.620716f), float2(0.96234f, -0.194983f), float2(0.473434f, -0.480026f), float2(0.519456f, 0.767022f), float2(0.185461f, -0.893124f), float2(0.507431f, 0.064425f), float2(0.89642f, 0.412458f), float2(-0.32194f, -0.932615f), float2(-0.791559f, -0.59771f) }; float4 ps_blur_intensity(float2 TexCoord : TEXCOORD0) : COLOR0 { // Sample pixel depth float fDepth = tex2D(depthSampler, TexCoord).x; // Fix canvas depth fDepth += (fDepth < 0.001f) * g_fFarPlane; float fIntensity; // Close-up blur if(fDepth < g_fFocalPlane) fIntensity = (fDepth - g_fFocalPlane) / (g_fFocalPlane - g_fNearPlane); // Distance blur else fIntensity = min((fDepth - g_fFocalPlane) / (g_fFarPlane - g_fFocalPlane), g_fMaxDistBlur); // Bias to valid range return float4( tex2D(colorSampler, TexCoord).xyz, 0.5f + 0.5f * fIntensity); } float4 ps_main(float2 TexCoord : TEXCOORD0) : COLOR0 { // Center pixel depth float fDepth = tex2D(colorSampler, TexCoord).w; // Scale sampling radius float fRadius = abs(2.0f * g_fRadius * fDepth - g_fRadius); float fLowRadius = fRadius * g_fLowRadiusScaling; float4 fColor = 0.0f; float fAmount = 0.0f; // Loop over samples for(int i = 0; i < 12; i++) { // Sample on poisson disc float2 fHighSampleTexCoord = TexCoord + fRadius * vPoissonDisc[i]; float2 fLowSampleTexCoord = TexCoord + fLowRadius * vPoissonDisc[i]; // Sample blurred and unblurred texture float4 fHighSample = tex2D(colorSampler, fHighSampleTexCoord); float4 fLowSample = tex2D(blurSampler, fLowSampleTexCoord); // Blend between blurred and unblurred texture float fSampleBlurIntensity = abs(2.0f * fHighSample.w - 1.0f); float4 fSample = lerp(fHighSample, fLowSample, fSampleBlurIntensity); // Compute smart weight to avoid cross-edge leaking float fWeight = fSample.w < fDepth ? abs(2.0f * fSample.w - 1.0f) : 1.0f; // Sum up fColor += fSample * fWeight; fAmount += fWeight; } return fColor / fAmount; }