mirror of
https://github.com/Xaymar/obs-StreamFX
synced 2024-11-11 14:25:05 +00:00
fedc8e075c
Gaussian Blur is another Blur that now supports the new system, increasing the maxium Blur size to 128 and adding support for Rotational and Zoom blur. Various optimizations were done to the actual shader code which further reduced the GPU usage. Currently the Gaussian curve is recalculated when the blur is first created, which can lead to a short hitch due to it having to search for the correct kernels. This is currently unavoidable and expected behavior until a better solution is found. Related: #45, #6
146 lines
3.3 KiB
Text
146 lines
3.3 KiB
Text
// Parameters:
|
|
/// OBS Default
|
|
uniform float4x4 ViewProj;
|
|
/// Texture
|
|
uniform texture2d pImage;
|
|
uniform float2 pImageTexel;
|
|
/// Blur
|
|
uniform float pSize;
|
|
uniform float pAngle;
|
|
uniform float2 pCenter;
|
|
uniform float2 pStepScale;
|
|
/// Gaussian
|
|
uniform float4 pKernel[32];
|
|
|
|
#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;
|
|
}
|
|
|
|
// Functions
|
|
float GetKernelAt(int i) {
|
|
return ((float[4])(pKernel[floor(i/4)]))[i%4];
|
|
}
|
|
|
|
// Blur 1 Dimensional
|
|
float4 PSBlur1D(VertDataOut vtx) : TARGET {
|
|
float4 final = pImage.Sample(linearSampler, vtx.uv)
|
|
* GetKernelAt(0);
|
|
|
|
// 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;
|
|
float kernel = GetKernelAt(n);
|
|
final += pImage.Sample(linearSampler, vtx.uv + nstep) * kernel;
|
|
final += pImage.Sample(linearSampler, vtx.uv - nstep) * kernel;
|
|
|
|
if (n >= pSize) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
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)
|
|
* GetKernelAt(0);
|
|
|
|
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++) {
|
|
float kernel = GetKernelAt(n);
|
|
final += pImage.Sample(linearSampler, rotateAround(vtx.uv, pCenter, angstep * n)) * kernel;
|
|
final += pImage.Sample(linearSampler, rotateAround(vtx.uv, pCenter, angstep * -n)) * kernel;
|
|
|
|
if (n >= pSize) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
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)
|
|
* GetKernelAt(0);
|
|
|
|
// 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++) {
|
|
float kernel = GetKernelAt(n);
|
|
final += pImage.Sample(linearSampler, vtx.uv + (dir * n) * dist) * kernel;
|
|
final += pImage.Sample(linearSampler, vtx.uv - (dir * n) * dist) * kernel;
|
|
|
|
if (n >= pSize) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
return final;
|
|
}
|
|
|
|
technique Zoom {
|
|
pass {
|
|
vertex_shader = VSDefault(vtx);
|
|
pixel_shader = PSZoom(vtx);
|
|
}
|
|
}
|