// Parameters: /// OBS Default uniform float4x4 ViewProj; /// Texture uniform texture2d pImage; uniform float2 pImageTexel; /// Blur uniform float pSize; uniform float pSizeInverseMul; uniform float pAngle; uniform float2 pCenter; uniform float2 pStepScale; #define MAX_BLUR_SIZE 128 // Sampler sampler_state linearSampler { Filter = Linear; AddressU = Clamp; AddressV = Clamp; MinLOD = 0; MaxLOD = 0; }; // Default Vertex Shader and Data struct VertDataIn { float4 pos : POSITION; float2 uv : TEXCOORD0; }; struct VertDataOut { float4 pos : POSITION; float2 uv : TEXCOORD0; }; VertDataOut VSDefault(VertDataIn vtx) { VertDataOut vert_out; vert_out.pos = mul(float4(vtx.pos.xyz, 1.0), ViewProj); vert_out.uv = vtx.uv; return vert_out; } // Blur 1 Dimensional float4 PSBlur1D(VertDataOut vtx) : TARGET { float4 final = pImage.Sample(linearSampler, vtx.uv); // Loop unrolling is only possible with a fixed known maximum. // Some compilers may unroll up to x iterations, but most will not. for (int n = 1; n <= MAX_BLUR_SIZE; n++) { float2 nstep = (pImageTexel * pStepScale) * n; final += pImage.Sample(linearSampler, vtx.uv + nstep); final += pImage.Sample(linearSampler, vtx.uv - nstep); if (n >= pSize) { break; } } final *= pSizeInverseMul; return final; } technique Draw { pass { vertex_shader = VSDefault(vtx); pixel_shader = PSBlur1D(vtx); } } // Blur Rotation float2 rotate(float2 pt, float angle) { float cp = cos(angle); float sp = sin(angle); float sn = -sp; return float2((pt.x * cp) + (pt.y * sn), (pt.x * sp) + (pt.y * cp)); } float2 rotateAround(float2 pt, float2 cpt, float angle) { return rotate(pt - cpt, angle) + cpt; } float4 PSRotate(VertDataOut vtx) : TARGET { float4 final = pImage.Sample(linearSampler, vtx.uv); float angstep = pAngle * pStepScale.x; // Loop unrolling is only possible with a fixed known maximum. // Some compilers may unroll up to x iterations, but most will not. for (int n = 1; n <= MAX_BLUR_SIZE; n++) { final += pImage.Sample(linearSampler, rotateAround(vtx.uv, pCenter, angstep * n)); final += pImage.Sample(linearSampler, rotateAround(vtx.uv, pCenter, angstep * -n)); if (n >= pSize) { break; } } final *= pSizeInverseMul; return final; } technique Rotate { pass { vertex_shader = VSDefault(vtx); pixel_shader = PSRotate(vtx); } } // Blur Zoom float4 PSZoom(VertDataOut vtx) : TARGET { float4 final = pImage.Sample(linearSampler, vtx.uv); // step is calculated from the direction relative to the center float2 dir = normalize(vtx.uv - pCenter) * pStepScale * pImageTexel; float dist = distance(vtx.uv, pCenter); // Loop unrolling is only possible with a fixed known maximum. // Some compilers may unroll up to x iterations, but most will not. for (int n = 1; n <= MAX_BLUR_SIZE; n++) { final += pImage.Sample(linearSampler, vtx.uv + (dir * n) * dist); final += pImage.Sample(linearSampler, vtx.uv + (dir * -n) * dist); if (n >= pSize) { break; } } final *= pSizeInverseMul; return final; } technique Zoom { pass { vertex_shader = VSDefault(vtx); pixel_shader = PSZoom(vtx); } }