obs-StreamFX/data/effects/blur/box.effect
Michael Fabian 'Xaymar' Dirks 8c5dc3c630 gfx/blur/box: Refactor Box Blur
Box Blur is the first to be on the new system and has received all the new features and optimizations available. The maximum Blur size has been increased to 128, Rotational and Zoom Blur are supported and a small optimization has been done to the shader.

Related: #45, #6
2019-04-02 03:50:01 +02:00

137 lines
3.1 KiB
Text

// 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);
}
}