mirror of
https://github.com/Xaymar/obs-StreamFX
synced 2024-11-28 14:23:01 +00:00
8c5dc3c630
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
137 lines
3.1 KiB
Text
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);
|
|
}
|
|
}
|