#define MAX_RADIUS 128u uniform float4x4 ViewProj; uniform texture2d image; uniform float2 uv_size; uniform float2 radial_center; uniform float radius; sampler_state textureSampler{ Filter = Linear; AddressU = Clamp; AddressV = Clamp; MinLOD = 0; MaxLOD = 0; }; struct VertData { float4 pos : POSITION; float2 uv : TEXCOORD0; }; VertData mainTransform(VertData v_in) { v_in.pos = mul(float4(v_in.pos.xyz, 1.0), ViewProj); return v_in; } float4 mainImage(VertData v_in) : TARGET { // convert radial center pixel coordinate to uv space float2 radial_center_uv = radial_center/uv_size; // calculate distance (in uv space) between coordinate and radial center. float dist = distance(v_in.uv, radial_center_uv); // calculate unit vector in direction of radial center to coordinate // scale by uv size to get unit vector in pixels. float2 texel_step = normalize(v_in.uv - radial_center_uv)/uv_size; float blur_radius = 2.0f * dist * radius; // 1. Sample incoming pixel, multiply by weight[0] float4 col = image.Sample(textureSampler, v_in.uv); // 2. March out from incoming pixel, multiply by corresponding weight. One step in // negative relative direction (step towards center point) for(uint i=1u; i<=MAX_RADIUS; i+=2u) { if(i+1u > blur_radius) { break; } float offset = float(i)+0.5f; col += 2.0*image.Sample(textureSampler, v_in.uv - (offset * texel_step)); } float fradius = floor(blur_radius); float residual = blur_radius-(fradius-float(int(fradius)%2)); float offset = (blur_radius - residual/2.0f); col += image.Sample(textureSampler, v_in.uv - (offset * texel_step)) * residual; col /= blur_radius + 1.0f; return col; } technique Draw { pass { vertex_shader = mainTransform(v_in); pixel_shader = mainImage(v_in); } }