mirror of
https://github.com/Xaymar/obs-StreamFX
synced 2024-12-28 18:41:14 +00:00
filter-blur: Allow applying Blur to a sub-region of the source only
The Blur Filter can now be applied to a region inside the source itself, the inverse of that region, and/or a feathered version of that region. This allows for easier scene setups where only some parts need to be blurred, but the rest can be left as is. Fixes #12
This commit is contained in:
parent
1ba9145fbd
commit
af71a7cc1d
6 changed files with 484 additions and 37 deletions
|
@ -9,6 +9,14 @@ uniform int u_radius;
|
|||
uniform int u_diameter;
|
||||
uniform float2 u_texelDelta;
|
||||
|
||||
/// Region
|
||||
uniform float regionLeft;
|
||||
uniform float regionTop;
|
||||
uniform float regionRight;
|
||||
uniform float regionBottom;
|
||||
uniform float regionFeather;
|
||||
uniform float regionFeatherShift;
|
||||
|
||||
// Settings (Private)
|
||||
uniform float bilateralSmoothing;
|
||||
uniform float bilateralSharpness;
|
||||
|
@ -17,6 +25,8 @@ sampler_state textureSampler {
|
|||
Filter = Point;
|
||||
AddressU = Clamp;
|
||||
AddressV = Clamp;
|
||||
MinLOD = 0;
|
||||
MaxLOD = 0;
|
||||
};
|
||||
|
||||
struct VertDataIn {
|
||||
|
@ -38,33 +48,23 @@ VertDataOut VSDefault(VertDataIn v_in)
|
|||
}
|
||||
|
||||
// Bilateral Blur
|
||||
float Bilateral(float x, float sigma)
|
||||
{
|
||||
float Bilateral(float x, float sigma) {
|
||||
return 0.39894 * exp(-0.5 * (x*x) / (sigma*sigma)) / sigma;
|
||||
}
|
||||
|
||||
float Bilateral3(float3 v, float sigma)
|
||||
{
|
||||
// First part is Gaussian function (1.0 / (o * sqrt(2.0 * pivalue))) with o = 1
|
||||
float Bilateral3(float3 v, float sigma) {
|
||||
// First part is Bilateral function (1.0 / (o * sqrt(2.0 * pivalue))) with o = 1
|
||||
return 0.39894 * exp(-0.5 * dot(v,v) / (sigma*sigma)) / sigma;
|
||||
}
|
||||
|
||||
float4 BilateralBlur(float2 p_uv, float2 p_radius,
|
||||
texture2d p_image, float2 p_imageTexel) {
|
||||
float2 l_uvoffset = float2(0, 0);
|
||||
}
|
||||
|
||||
float4 PSBilateral(VertDataOut v_in) : TARGET
|
||||
{
|
||||
float2 l_uv = float2(0, 0);
|
||||
float4 BlurFunc(float2 uv, float4 rgba) {
|
||||
float2 uvOffset = float2(0, 0);
|
||||
|
||||
float Z = 0.0;
|
||||
float bZ = 1.0 / Bilateral(0.0, bilateralSharpness);
|
||||
float4 source = u_image.Sample(textureSampler, v_in.uv);
|
||||
float3 color = float3(0, 0, 0);
|
||||
for (int k = 1; k <= u_radius; k++) {
|
||||
// Advance UV by one texel.
|
||||
l_uv += u_texelDelta;
|
||||
uvOffset += u_texelDelta;
|
||||
|
||||
// Bilateral Kernel
|
||||
float bKernel = Bilateral(abs(k), bilateralSmoothing);
|
||||
|
@ -72,12 +72,12 @@ float4 PSBilateral(VertDataOut v_in) : TARGET
|
|||
float bZKernel = bZ * bKernel;
|
||||
|
||||
// Sample Color
|
||||
float3 l_p = u_image.Sample(textureSampler, v_in.uv + l_uv).rgb;
|
||||
float3 l_n = u_image.Sample(textureSampler, v_in.uv - l_uv).rgb;
|
||||
float3 l_p = u_image.SampleLevel(textureSampler, uv + uvOffset, 0).rgb;
|
||||
float3 l_n = u_image.SampleLevel(textureSampler, uv - uvOffset, 0).rgb;
|
||||
|
||||
// Bilateral Stuff
|
||||
float l_factor_p = Bilateral3(l_p - source.rgb, bilateralSharpness) * bZKernel;
|
||||
float l_factor_n = Bilateral3(l_n - source.rgb, bilateralSharpness) * bZKernel;
|
||||
float l_factor_p = Bilateral3(l_p - rgba.rgb, bilateralSharpness) * bZKernel;
|
||||
float l_factor_n = Bilateral3(l_n - rgba.rgb, bilateralSharpness) * bZKernel;
|
||||
Z = Z + l_factor_p + l_factor_n;
|
||||
|
||||
// Store Color
|
||||
|
@ -85,7 +85,74 @@ float4 PSBilateral(VertDataOut v_in) : TARGET
|
|||
color += l_n * l_factor_n;
|
||||
}
|
||||
|
||||
return float4(color.rgb / Z, source.a);
|
||||
return float4(color.rgb / Z, rgba.a);
|
||||
}
|
||||
|
||||
float4 PSBilateral(VertDataOut v_in) : TARGET {
|
||||
float4 rgba = u_image.SampleLevel(textureSampler, v_in.uv, 0);
|
||||
return BlurFunc(v_in.uv, rgba);
|
||||
}
|
||||
|
||||
float4 PSBilateralRegion(VertDataOut v_in) : TARGET {
|
||||
float4 rgba = u_image.SampleLevel(textureSampler, v_in.uv, 0);
|
||||
if ((v_in.uv.x < regionLeft)
|
||||
|| (v_in.uv.x > regionRight)
|
||||
|| (v_in.uv.y < regionTop)
|
||||
|| (v_in.uv.y > regionBottom)) {
|
||||
return rgba;
|
||||
}
|
||||
|
||||
return BlurFunc(v_in.uv, rgba);
|
||||
}
|
||||
|
||||
float4 PSBilateralRegionInvert(VertDataOut v_in) : TARGET {
|
||||
float4 rgba = u_image.SampleLevel(textureSampler, v_in.uv, 0);
|
||||
if ((v_in.uv.x > regionLeft)
|
||||
&& (v_in.uv.x < regionRight)
|
||||
&& (v_in.uv.y > regionTop)
|
||||
&& (v_in.uv.y < regionBottom)) {
|
||||
return rgba;
|
||||
}
|
||||
|
||||
return BlurFunc(v_in.uv, rgba);
|
||||
}
|
||||
|
||||
float4 PSBilateralRegionFeather(VertDataOut v_in) : TARGET {
|
||||
float halfFeather = (regionFeather / 2.0);
|
||||
float feather = max(regionFeather, 0.00000001);
|
||||
float leftFeather = clamp(((v_in.uv.x - regionLeft + halfFeather) / feather) + regionFeatherShift, 0.0, 1.0);
|
||||
float rightFeather = clamp(((-(v_in.uv.x - regionRight) + halfFeather) / feather) + regionFeatherShift, 0.0, 1.0);
|
||||
float topFeather = clamp(((v_in.uv.y - regionTop + halfFeather) / feather) + regionFeatherShift, 0.0, 1.0);
|
||||
float bottomFeather = clamp(((-(v_in.uv.y - regionBottom) + halfFeather) / feather) + regionFeatherShift, 0.0, 1.0);
|
||||
float finalFeather = min(min(leftFeather, rightFeather), min(topFeather, bottomFeather));
|
||||
|
||||
float4 rgba = u_image.SampleLevel(textureSampler, v_in.uv, 0);
|
||||
if (finalFeather <= 0.00001) {
|
||||
return rgba;
|
||||
} else if (finalFeather >= 0.99999) {
|
||||
return BlurFunc(v_in.uv, rgba);
|
||||
}
|
||||
|
||||
return lerp(rgba, BlurFunc(v_in.uv, rgba), finalFeather);
|
||||
}
|
||||
|
||||
float4 PSBilateralRegionFeatherInvert(VertDataOut v_in) : TARGET {
|
||||
float halfFeather = (regionFeather / 2.0);
|
||||
float feather = max(regionFeather, 0.00000001);
|
||||
float leftFeather = clamp(((v_in.uv.x - regionLeft + halfFeather) / feather) + regionFeatherShift, 0.0, 1.0);
|
||||
float rightFeather = clamp(((-(v_in.uv.x - regionRight) + halfFeather) / feather) + regionFeatherShift, 0.0, 1.0);
|
||||
float topFeather = clamp(((v_in.uv.y - regionTop + halfFeather) / feather) + regionFeatherShift, 0.0, 1.0);
|
||||
float bottomFeather = clamp(((-(v_in.uv.y - regionBottom) + halfFeather) / feather) + regionFeatherShift, 0.0, 1.0);
|
||||
float finalFeather = 1.0 - min(min(leftFeather, rightFeather), min(topFeather, bottomFeather));
|
||||
|
||||
float4 rgba = u_image.SampleLevel(textureSampler, v_in.uv, 0);
|
||||
if (finalFeather <= 0.00001) {
|
||||
return rgba;
|
||||
} else if (finalFeather >= 0.99999) {
|
||||
return BlurFunc(v_in.uv, rgba);
|
||||
}
|
||||
|
||||
return lerp(rgba, BlurFunc(v_in.uv, rgba), finalFeather);
|
||||
}
|
||||
|
||||
technique Draw
|
||||
|
@ -96,3 +163,37 @@ technique Draw
|
|||
pixel_shader = PSBilateral(v_in);
|
||||
}
|
||||
}
|
||||
|
||||
technique DrawRegion
|
||||
{
|
||||
pass
|
||||
{
|
||||
vertex_shader = VSDefault(v_in);
|
||||
pixel_shader = PSBilateralRegion(v_in);
|
||||
}
|
||||
}
|
||||
technique DrawRegionInvert
|
||||
{
|
||||
pass
|
||||
{
|
||||
vertex_shader = VSDefault(v_in);
|
||||
pixel_shader = PSBilateralRegionInvert(v_in);
|
||||
}
|
||||
}
|
||||
|
||||
technique DrawRegionFeather
|
||||
{
|
||||
pass
|
||||
{
|
||||
vertex_shader = VSDefault(v_in);
|
||||
pixel_shader = PSBilateralRegionFeather(v_in);
|
||||
}
|
||||
}
|
||||
technique DrawRegionFeatherInvert
|
||||
{
|
||||
pass
|
||||
{
|
||||
vertex_shader = VSDefault(v_in);
|
||||
pixel_shader = PSBilateralRegionFeatherInvert(v_in);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,10 +9,21 @@ uniform int u_radius;
|
|||
uniform int u_diameter;
|
||||
uniform float2 u_texelDelta;
|
||||
|
||||
/// Region
|
||||
uniform float regionLeft;
|
||||
uniform float regionTop;
|
||||
uniform float regionRight;
|
||||
uniform float regionBottom;
|
||||
uniform float regionFeather;
|
||||
uniform float regionFeatherShift;
|
||||
|
||||
// Data
|
||||
sampler_state textureSampler {
|
||||
Filter = Point;
|
||||
AddressU = Clamp;
|
||||
AddressV = Clamp;
|
||||
MinLOD = 0;
|
||||
MaxLOD = 0;
|
||||
};
|
||||
|
||||
struct VertDataIn {
|
||||
|
@ -34,15 +45,80 @@ VertDataOut VSDefault(VertDataIn v_in)
|
|||
}
|
||||
|
||||
// Box Blur
|
||||
float4 PSBox(VertDataOut v_in) : TARGET
|
||||
{
|
||||
float4 rgba = u_image.Sample(textureSampler, v_in.uv);
|
||||
float4 BlurFunc(float2 uv, float4 rgba) {
|
||||
float4 final = rgba;
|
||||
for (int k = 1; k <= u_radius; k++) {
|
||||
rgba += u_image.Sample(textureSampler, v_in.uv + (u_texelDelta * k));
|
||||
rgba += u_image.Sample(textureSampler, v_in.uv - (u_texelDelta * k));
|
||||
final += u_image.SampleLevel(textureSampler, uv + (u_texelDelta * k), 0);
|
||||
final += u_image.SampleLevel(textureSampler, uv - (u_texelDelta * k), 0);
|
||||
}
|
||||
rgba = rgba / u_diameter;
|
||||
return rgba;
|
||||
return final / u_diameter;
|
||||
}
|
||||
|
||||
float4 PSBox(VertDataOut v_in) : TARGET {
|
||||
float4 rgba = u_image.SampleLevel(textureSampler, v_in.uv, 0);
|
||||
return BlurFunc(v_in.uv, rgba);
|
||||
}
|
||||
|
||||
float4 PSBoxRegion(VertDataOut v_in) : TARGET {
|
||||
float4 rgba = u_image.SampleLevel(textureSampler, v_in.uv, 0);
|
||||
if ((v_in.uv.x < regionLeft)
|
||||
|| (v_in.uv.x > regionRight)
|
||||
|| (v_in.uv.y < regionTop)
|
||||
|| (v_in.uv.y > regionBottom)) {
|
||||
return rgba;
|
||||
}
|
||||
|
||||
return BlurFunc(v_in.uv, rgba);
|
||||
}
|
||||
|
||||
float4 PSBoxRegionInvert(VertDataOut v_in) : TARGET {
|
||||
float4 rgba = u_image.SampleLevel(textureSampler, v_in.uv, 0);
|
||||
if ((v_in.uv.x > regionLeft)
|
||||
&& (v_in.uv.x < regionRight)
|
||||
&& (v_in.uv.y > regionTop)
|
||||
&& (v_in.uv.y < regionBottom)) {
|
||||
return rgba;
|
||||
}
|
||||
|
||||
return BlurFunc(v_in.uv, rgba);
|
||||
}
|
||||
|
||||
float4 PSBoxRegionFeather(VertDataOut v_in) : TARGET {
|
||||
float halfFeather = (regionFeather / 2.0);
|
||||
float feather = max(regionFeather, 0.00000001);
|
||||
float leftFeather = clamp(((v_in.uv.x - regionLeft + halfFeather) / feather) + regionFeatherShift, 0.0, 1.0);
|
||||
float rightFeather = clamp(((-(v_in.uv.x - regionRight) + halfFeather) / feather) + regionFeatherShift, 0.0, 1.0);
|
||||
float topFeather = clamp(((v_in.uv.y - regionTop + halfFeather) / feather) + regionFeatherShift, 0.0, 1.0);
|
||||
float bottomFeather = clamp(((-(v_in.uv.y - regionBottom) + halfFeather) / feather) + regionFeatherShift, 0.0, 1.0);
|
||||
float finalFeather = min(min(leftFeather, rightFeather), min(topFeather, bottomFeather));
|
||||
|
||||
float4 rgba = u_image.SampleLevel(textureSampler, v_in.uv, 0);
|
||||
if (finalFeather <= 0.00001) {
|
||||
return rgba;
|
||||
} else if (finalFeather >= 0.99999) {
|
||||
return BlurFunc(v_in.uv, rgba);
|
||||
}
|
||||
|
||||
return lerp(rgba, BlurFunc(v_in.uv, rgba), finalFeather);
|
||||
}
|
||||
|
||||
float4 PSBoxRegionFeatherInvert(VertDataOut v_in) : TARGET {
|
||||
float halfFeather = (regionFeather / 2.0);
|
||||
float feather = max(regionFeather, 0.00000001);
|
||||
float leftFeather = clamp(((v_in.uv.x - regionLeft + halfFeather) / feather) + regionFeatherShift, 0.0, 1.0);
|
||||
float rightFeather = clamp(((-(v_in.uv.x - regionRight) + halfFeather) / feather) + regionFeatherShift, 0.0, 1.0);
|
||||
float topFeather = clamp(((v_in.uv.y - regionTop + halfFeather) / feather) + regionFeatherShift, 0.0, 1.0);
|
||||
float bottomFeather = clamp(((-(v_in.uv.y - regionBottom) + halfFeather) / feather) + regionFeatherShift, 0.0, 1.0);
|
||||
float finalFeather = 1.0 - min(min(leftFeather, rightFeather), min(topFeather, bottomFeather));
|
||||
|
||||
float4 rgba = u_image.SampleLevel(textureSampler, v_in.uv, 0);
|
||||
if (finalFeather <= 0.00001) {
|
||||
return rgba;
|
||||
} else if (finalFeather >= 0.99999) {
|
||||
return BlurFunc(v_in.uv, rgba);
|
||||
}
|
||||
|
||||
return lerp(rgba, BlurFunc(v_in.uv, rgba), finalFeather);
|
||||
}
|
||||
|
||||
technique Draw
|
||||
|
@ -53,3 +129,39 @@ technique Draw
|
|||
pixel_shader = PSBox(v_in);
|
||||
}
|
||||
}
|
||||
|
||||
technique DrawRegion
|
||||
{
|
||||
pass
|
||||
{
|
||||
vertex_shader = VSDefault(v_in);
|
||||
pixel_shader = PSBoxRegion(v_in);
|
||||
}
|
||||
}
|
||||
|
||||
technique DrawRegionInvert
|
||||
{
|
||||
pass
|
||||
{
|
||||
vertex_shader = VSDefault(v_in);
|
||||
pixel_shader = PSBoxRegionInvert(v_in);
|
||||
}
|
||||
}
|
||||
|
||||
technique DrawRegionFeather
|
||||
{
|
||||
pass
|
||||
{
|
||||
vertex_shader = VSDefault(v_in);
|
||||
pixel_shader = PSBoxRegionFeather(v_in);
|
||||
}
|
||||
}
|
||||
|
||||
technique DrawRegionFeatherInvert
|
||||
{
|
||||
pass
|
||||
{
|
||||
vertex_shader = VSDefault(v_in);
|
||||
pixel_shader = PSBoxRegionFeatherInvert(v_in);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,6 +9,14 @@ uniform int u_radius;
|
|||
uniform int u_diameter;
|
||||
uniform float2 u_texelDelta;
|
||||
|
||||
/// Region
|
||||
uniform float regionLeft;
|
||||
uniform float regionTop;
|
||||
uniform float regionRight;
|
||||
uniform float regionBottom;
|
||||
uniform float regionFeather;
|
||||
uniform float regionFeatherShift;
|
||||
|
||||
// Settings (Private)
|
||||
//uniform float registerkernel[25];
|
||||
uniform texture2d kernel;
|
||||
|
@ -40,18 +48,84 @@ VertDataOut VSDefault(VertDataIn v_in)
|
|||
return vert_out;
|
||||
}
|
||||
|
||||
float4 PSGaussian(VertDataOut v_in) : TARGET {
|
||||
float4 BlurFunc(float2 uv, float4 rgba) {
|
||||
float2 uvOffset = float2(0, 0);
|
||||
float4 rgba = u_image.SampleLevel(textureSampler, v_in.uv, 0)
|
||||
* kernel.SampleLevel(textureSampler, (float2(0, u_radius - 1) * kernelTexel), 0).r;
|
||||
float4 final = rgba * kernel.SampleLevel(textureSampler, (float2(0, u_radius - 1) * kernelTexel), 0).r;
|
||||
for (int k = 1; k <= u_radius; k++) {
|
||||
uvOffset += u_texelDelta;
|
||||
float l_g = kernel.SampleLevel(textureSampler, (float2(k, u_radius - 1) * kernelTexel), 0).r;
|
||||
float4 l_p = u_image.SampleLevel(textureSampler, v_in.uv + uvOffset, 0) * l_g;
|
||||
float4 l_n = u_image.SampleLevel(textureSampler, v_in.uv - uvOffset, 0) * l_g;
|
||||
rgba += l_p + l_n;
|
||||
float4 l_p = u_image.SampleLevel(textureSampler, uv + uvOffset, 0);
|
||||
float4 l_n = u_image.SampleLevel(textureSampler, uv - uvOffset, 0);
|
||||
final += (l_p + l_n) * l_g;
|
||||
}
|
||||
return rgba;
|
||||
return final;
|
||||
}
|
||||
|
||||
float4 PSGaussian(VertDataOut v_in) : TARGET {
|
||||
float4 rgba = u_image.SampleLevel(textureSampler, v_in.uv, 0);
|
||||
return BlurFunc(v_in.uv, rgba);
|
||||
}
|
||||
|
||||
float4 PSGaussianRegion(VertDataOut v_in) : TARGET {
|
||||
float4 rgba = u_image.SampleLevel(textureSampler, v_in.uv, 0);
|
||||
if ((v_in.uv.x < regionLeft)
|
||||
|| (v_in.uv.x > regionRight)
|
||||
|| (v_in.uv.y < regionTop)
|
||||
|| (v_in.uv.y > regionBottom)) {
|
||||
return rgba;
|
||||
}
|
||||
|
||||
return BlurFunc(v_in.uv, rgba);
|
||||
}
|
||||
|
||||
float4 PSGaussianRegionInvert(VertDataOut v_in) : TARGET {
|
||||
float4 rgba = u_image.SampleLevel(textureSampler, v_in.uv, 0);
|
||||
if ((v_in.uv.x > regionLeft)
|
||||
&& (v_in.uv.x < regionRight)
|
||||
&& (v_in.uv.y > regionTop)
|
||||
&& (v_in.uv.y < regionBottom)) {
|
||||
return rgba;
|
||||
}
|
||||
|
||||
return BlurFunc(v_in.uv, rgba);
|
||||
}
|
||||
|
||||
float4 PSGaussianRegionFeather(VertDataOut v_in) : TARGET {
|
||||
float halfFeather = (regionFeather / 2.0);
|
||||
float feather = max(regionFeather, 0.00000001);
|
||||
float leftFeather = clamp(((v_in.uv.x - regionLeft + halfFeather) / feather) + regionFeatherShift, 0.0, 1.0);
|
||||
float rightFeather = clamp(((-(v_in.uv.x - regionRight) + halfFeather) / feather) + regionFeatherShift, 0.0, 1.0);
|
||||
float topFeather = clamp(((v_in.uv.y - regionTop + halfFeather) / feather) + regionFeatherShift, 0.0, 1.0);
|
||||
float bottomFeather = clamp(((-(v_in.uv.y - regionBottom) + halfFeather) / feather) + regionFeatherShift, 0.0, 1.0);
|
||||
float finalFeather = min(min(leftFeather, rightFeather), min(topFeather, bottomFeather));
|
||||
|
||||
float4 rgba = u_image.SampleLevel(textureSampler, v_in.uv, 0);
|
||||
if (finalFeather <= 0.00001) {
|
||||
return rgba;
|
||||
} else if (finalFeather >= 0.99999) {
|
||||
return BlurFunc(v_in.uv, rgba);
|
||||
}
|
||||
|
||||
return lerp(rgba, BlurFunc(v_in.uv, rgba), finalFeather);
|
||||
}
|
||||
|
||||
float4 PSGaussianRegionFeatherInvert(VertDataOut v_in) : TARGET {
|
||||
float halfFeather = (regionFeather / 2.0);
|
||||
float feather = max(regionFeather, 0.00000001);
|
||||
float leftFeather = clamp(((v_in.uv.x - regionLeft + halfFeather) / feather) + regionFeatherShift, 0.0, 1.0);
|
||||
float rightFeather = clamp(((-(v_in.uv.x - regionRight) + halfFeather) / feather) + regionFeatherShift, 0.0, 1.0);
|
||||
float topFeather = clamp(((v_in.uv.y - regionTop + halfFeather) / feather) + regionFeatherShift, 0.0, 1.0);
|
||||
float bottomFeather = clamp(((-(v_in.uv.y - regionBottom) + halfFeather) / feather) + regionFeatherShift, 0.0, 1.0);
|
||||
float finalFeather = 1.0 - min(min(leftFeather, rightFeather), min(topFeather, bottomFeather));
|
||||
|
||||
float4 rgba = u_image.SampleLevel(textureSampler, v_in.uv, 0);
|
||||
if (finalFeather <= 0.00001) {
|
||||
return rgba;
|
||||
} else if (finalFeather >= 0.99999) {
|
||||
return BlurFunc(v_in.uv, rgba);
|
||||
}
|
||||
|
||||
return lerp(rgba, BlurFunc(v_in.uv, rgba), finalFeather);
|
||||
}
|
||||
|
||||
technique Draw
|
||||
|
@ -62,3 +136,37 @@ technique Draw
|
|||
pixel_shader = PSGaussian(v_in);
|
||||
}
|
||||
}
|
||||
|
||||
technique DrawRegion
|
||||
{
|
||||
pass
|
||||
{
|
||||
vertex_shader = VSDefault(v_in);
|
||||
pixel_shader = PSGaussianRegion(v_in);
|
||||
}
|
||||
}
|
||||
technique DrawRegionInvert
|
||||
{
|
||||
pass
|
||||
{
|
||||
vertex_shader = VSDefault(v_in);
|
||||
pixel_shader = PSGaussianRegionInvert(v_in);
|
||||
}
|
||||
}
|
||||
|
||||
technique DrawRegionFeather
|
||||
{
|
||||
pass
|
||||
{
|
||||
vertex_shader = VSDefault(v_in);
|
||||
pixel_shader = PSGaussianRegionFeather(v_in);
|
||||
}
|
||||
}
|
||||
technique DrawRegionFeatherInvert
|
||||
{
|
||||
pass
|
||||
{
|
||||
vertex_shader = VSDefault(v_in);
|
||||
pixel_shader = PSGaussianRegionFeatherInvert(v_in);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,6 +12,22 @@ Filter.Blur.Size="Size (Pixel)"
|
|||
Filter.Blur.Size.Description="Area size of the blur, large sizes may cause:\n- Skipped frames\n- Frame loss or drops\n- Input lag\n- GPU overheating\n- or other issues."
|
||||
Filter.Blur.Bilateral.Smoothing="Smoothing"
|
||||
Filter.Blur.Bilateral.Sharpness="Sharpness"
|
||||
Filter.Blur.Region="Apply to Region only"
|
||||
Filter.Blur.Region.Description="Only apply the blur to a region inside the source."
|
||||
Filter.Blur.Region.Left="Left Edge"
|
||||
Filter.Blur.Region.Left.Description="Distance to left edge of the source in percent."
|
||||
Filter.Blur.Region.Top="Top Edge"
|
||||
Filter.Blur.Region.Top.Description="Distance to top edge of the source in percent."
|
||||
Filter.Blur.Region.Right="Right Edge"
|
||||
Filter.Blur.Region.Right.Description="Distance to right edge of the source in percent."
|
||||
Filter.Blur.Region.Bottom="Bottom Edge"
|
||||
Filter.Blur.Region.Bottom.Description="Distance to bottom edge of the source in percent."
|
||||
Filter.Blur.Region.Feather="Feather Area"
|
||||
Filter.Blur.Region.Feather.Description="Size of the smoothing area in percent, or 0 to turn off feather."
|
||||
Filter.Blur.Region.Feather.Shift="Feather Shift"
|
||||
Filter.Blur.Region.Feather.Shift.Description="Shift of the Feather area, positive is inwards, negative is outwards."
|
||||
Filter.Blur.Region.Invert="Invert Region"
|
||||
Filter.Blur.Region.Invert.Description="Invert the region so that everything but this area is blurred."
|
||||
Filter.Blur.ColorFormat="Color Format"
|
||||
|
||||
# Filter - Custom Shader
|
||||
|
|
|
@ -44,6 +44,16 @@ extern "C" {
|
|||
#define S_BILATERAL_SMOOTHING "Filter.Blur.Bilateral.Smoothing"
|
||||
#define S_BILATERAL_SHARPNESS "Filter.Blur.Bilateral.Sharpness"
|
||||
|
||||
// Region
|
||||
#define S_REGION "Filter.Blur.Region"
|
||||
#define S_REGION_LEFT "Filter.Blur.Region.Left"
|
||||
#define S_REGION_TOP "Filter.Blur.Region.Top"
|
||||
#define S_REGION_RIGHT "Filter.Blur.Region.Right"
|
||||
#define S_REGION_BOTTOM "Filter.Blur.Region.Bottom"
|
||||
#define S_REGION_FEATHER "Filter.Blur.Region.Feather"
|
||||
#define S_REGION_FEATHER_SHIFT "Filter.Blur.Region.Feather.Shift"
|
||||
#define S_REGION_INVERT "Filter.Blur.Region.Invert"
|
||||
|
||||
// Advanced
|
||||
#define S_FILTER_BLUR_COLORFORMAT "Filter.Blur.ColorFormat"
|
||||
|
||||
|
@ -96,6 +106,7 @@ Filter::Blur::Blur() {
|
|||
} catch (std::runtime_error ex) {
|
||||
P_LOG_ERROR("<filter-blur> Loading effect '%s' (path: '%s') failed with error(s): %s",
|
||||
kv.first.c_str(), kv.second.c_str(), ex.what());
|
||||
obs_leave_graphics();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -160,6 +171,16 @@ void Filter::Blur::get_defaults(obs_data_t *data) {
|
|||
obs_data_set_default_double(data, S_BILATERAL_SMOOTHING, 50.0);
|
||||
obs_data_set_default_double(data, S_BILATERAL_SHARPNESS, 90.0);
|
||||
|
||||
// Region
|
||||
obs_data_set_default_bool(data, S_REGION, false);
|
||||
obs_data_set_default_double(data, S_REGION_LEFT, 0.0f);
|
||||
obs_data_set_default_double(data, S_REGION_TOP, 0.0f);
|
||||
obs_data_set_default_double(data, S_REGION_RIGHT, 0.0f);
|
||||
obs_data_set_default_double(data, S_REGION_BOTTOM, 0.0f);
|
||||
obs_data_set_default_double(data, S_REGION_FEATHER, 0.0f);
|
||||
obs_data_set_default_double(data, S_REGION_FEATHER_SHIFT, 0.0f);
|
||||
obs_data_set_default_bool(data, S_REGION_INVERT, false);
|
||||
|
||||
// Advanced
|
||||
obs_data_set_default_bool(data, S_ADVANCED, false);
|
||||
obs_data_set_default_int(data, S_FILTER_BLUR_COLORFORMAT, ColorFormat::RGB);
|
||||
|
@ -186,6 +207,25 @@ obs_properties_t * Filter::Blur::get_properties(void *) {
|
|||
p = obs_properties_add_float_slider(pr, S_BILATERAL_SHARPNESS, P_TRANSLATE(S_BILATERAL_SHARPNESS), 0, 99.99, 0.01);
|
||||
obs_property_set_long_description(p, P_TRANSLATE(P_DESC(S_BILATERAL_SHARPNESS)));
|
||||
|
||||
// Region
|
||||
p = obs_properties_add_bool(pr, S_REGION, P_TRANSLATE(S_REGION));
|
||||
obs_property_set_long_description(p, P_TRANSLATE(P_DESC(S_REGION)));
|
||||
obs_property_set_modified_callback(p, modified_properties);
|
||||
p = obs_properties_add_float_slider(pr, S_REGION_LEFT, P_TRANSLATE(S_REGION_LEFT), 0.0, 100.0, 0.01);
|
||||
obs_property_set_long_description(p, P_TRANSLATE(P_DESC(S_REGION_LEFT)));
|
||||
p = obs_properties_add_float_slider(pr, S_REGION_TOP, P_TRANSLATE(S_REGION_TOP), 0.0, 100.0, 0.01);
|
||||
obs_property_set_long_description(p, P_TRANSLATE(P_DESC(S_REGION_TOP)));
|
||||
p = obs_properties_add_float_slider(pr, S_REGION_RIGHT, P_TRANSLATE(S_REGION_RIGHT), 0.0, 100.0, 0.01);
|
||||
obs_property_set_long_description(p, P_TRANSLATE(P_DESC(S_REGION_RIGHT)));
|
||||
p = obs_properties_add_float_slider(pr, S_REGION_BOTTOM, P_TRANSLATE(S_REGION_BOTTOM), 0.0, 100.0, 0.01);
|
||||
obs_property_set_long_description(p, P_TRANSLATE(P_DESC(S_REGION_BOTTOM)));
|
||||
p = obs_properties_add_float_slider(pr, S_REGION_FEATHER, P_TRANSLATE(S_REGION_FEATHER), 0.0, 50.0, 0.01);
|
||||
obs_property_set_long_description(p, P_TRANSLATE(P_DESC(S_REGION_FEATHER)));
|
||||
p = obs_properties_add_float_slider(pr, S_REGION_FEATHER_SHIFT, P_TRANSLATE(S_REGION_FEATHER_SHIFT), -100.0, 100.0, 0.01);
|
||||
obs_property_set_long_description(p, P_TRANSLATE(P_DESC(S_REGION_FEATHER_SHIFT)));
|
||||
p = obs_properties_add_bool(pr, S_REGION_INVERT, P_TRANSLATE(S_REGION_INVERT));
|
||||
obs_property_set_long_description(p, P_TRANSLATE(P_DESC(S_REGION_INVERT)));
|
||||
|
||||
// Advanced
|
||||
p = obs_properties_add_bool(pr, S_ADVANCED, P_TRANSLATE(S_ADVANCED));
|
||||
obs_property_set_long_description(p, P_TRANSLATE(P_DESC(S_ADVANCED)));
|
||||
|
@ -216,6 +256,16 @@ bool Filter::Blur::modified_properties(obs_properties_t *pr, obs_property_t *, o
|
|||
obs_property_set_visible(obs_properties_get(pr, S_BILATERAL_SMOOTHING), showBilateral);
|
||||
obs_property_set_visible(obs_properties_get(pr, S_BILATERAL_SHARPNESS), showBilateral);
|
||||
|
||||
// Region
|
||||
bool showRegion = obs_data_get_bool(d, S_REGION);
|
||||
obs_property_set_visible(obs_properties_get(pr, S_REGION_LEFT), showRegion);
|
||||
obs_property_set_visible(obs_properties_get(pr, S_REGION_TOP), showRegion);
|
||||
obs_property_set_visible(obs_properties_get(pr, S_REGION_RIGHT), showRegion);
|
||||
obs_property_set_visible(obs_properties_get(pr, S_REGION_BOTTOM), showRegion);
|
||||
obs_property_set_visible(obs_properties_get(pr, S_REGION_FEATHER), showRegion);
|
||||
obs_property_set_visible(obs_properties_get(pr, S_REGION_FEATHER_SHIFT), showRegion);
|
||||
obs_property_set_visible(obs_properties_get(pr, S_REGION_INVERT), showRegion);
|
||||
|
||||
// Advanced
|
||||
bool showAdvanced = false;
|
||||
if (obs_data_get_bool(d, S_ADVANCED))
|
||||
|
@ -312,8 +362,24 @@ void Filter::Blur::Instance::update(obs_data_t *data) {
|
|||
m_bilateralSmoothing = obs_data_get_double(data, S_BILATERAL_SMOOTHING) / 100.0;
|
||||
m_bilateralSharpness = obs_data_get_double(data, S_BILATERAL_SHARPNESS) / 100.0;
|
||||
|
||||
// Region
|
||||
m_region.enabled = obs_data_get_bool(data, S_REGION);
|
||||
if (m_region.enabled) {
|
||||
m_region.left = float_t(obs_data_get_double(data, S_REGION_LEFT) / 100.0);
|
||||
m_region.top = float_t(obs_data_get_double(data, S_REGION_TOP) / 100.0);
|
||||
m_region.right = 1.0 - float_t(obs_data_get_double(data, S_REGION_RIGHT) / 100.0);
|
||||
m_region.bottom = 1.0 - float_t(obs_data_get_double(data, S_REGION_BOTTOM) / 100.0);
|
||||
m_region.feather = float_t(obs_data_get_double(data, S_REGION_FEATHER) / 100.0);
|
||||
m_region.feather_shift = float_t(obs_data_get_double(data, S_REGION_FEATHER_SHIFT) / 100.0);
|
||||
m_region.invert = obs_data_get_bool(data, S_REGION_INVERT);
|
||||
}
|
||||
|
||||
// Advanced
|
||||
m_colorFormat = obs_data_get_int(data, S_FILTER_BLUR_COLORFORMAT);
|
||||
if (obs_data_get_bool(data, S_ADVANCED)) {
|
||||
m_colorFormat = obs_data_get_int(data, S_FILTER_BLUR_COLORFORMAT);
|
||||
} else {
|
||||
m_colorFormat = obs_data_get_default_int(data, S_FILTER_BLUR_COLORFORMAT);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t Filter::Blur::Instance::get_width() {
|
||||
|
@ -469,6 +535,17 @@ void Filter::Blur::Instance::video_render(gs_effect_t *effect) {
|
|||
std::make_tuple("Horizontal", m_rtHorizontal, 1.0f / baseW, 0.0f),
|
||||
std::make_tuple("Vertical", m_rtVertical, 0.0f, 1.0f / baseH),
|
||||
};
|
||||
std::string pass = "Draw";
|
||||
if (m_region.enabled) {
|
||||
if (m_region.feather > 0) {
|
||||
pass = "DrawRegionFeather";
|
||||
} else {
|
||||
pass = "DrawRegion";
|
||||
}
|
||||
if (m_region.invert) {
|
||||
pass += "Invert";
|
||||
}
|
||||
}
|
||||
for (auto v : kvs) {
|
||||
const char* name = std::get<0>(v);
|
||||
gs_texrender_t* rt = std::get<1>(v);
|
||||
|
@ -497,7 +574,7 @@ void Filter::Blur::Instance::video_render(gs_effect_t *effect) {
|
|||
gs_clear(GS_CLEAR_COLOR | GS_CLEAR_DEPTH, &black, 0, 0);
|
||||
|
||||
// Render
|
||||
while (gs_effect_loop(m_effect->get_object(), "Draw")) {
|
||||
while (gs_effect_loop(m_effect->get_object(), pass.c_str())) {
|
||||
gs_draw_sprite(intermediate, 0, baseW, baseH);
|
||||
}
|
||||
|
||||
|
@ -578,6 +655,27 @@ bool Filter::Blur::Instance::apply_shared_param(gs_texture_t* input, float texel
|
|||
result = result && gs_set_param_int(m_effect->get_object(), "u_radius", (int)m_size);
|
||||
result = result && gs_set_param_int(m_effect->get_object(), "u_diameter", (int)(1 + (m_size * 2)));
|
||||
|
||||
if (m_region.enabled) {
|
||||
if (m_effect->has_parameter("regionLeft")) {
|
||||
m_effect->get_parameter("regionLeft").set_float(m_region.left);
|
||||
}
|
||||
if (m_effect->has_parameter("regionTop")) {
|
||||
m_effect->get_parameter("regionTop").set_float(m_region.top);
|
||||
}
|
||||
if (m_effect->has_parameter("regionRight")) {
|
||||
m_effect->get_parameter("regionRight").set_float(m_region.right);
|
||||
}
|
||||
if (m_effect->has_parameter("regionBottom")) {
|
||||
m_effect->get_parameter("regionBottom").set_float(m_region.bottom);
|
||||
}
|
||||
if (m_effect->has_parameter("regionFeather")) {
|
||||
m_effect->get_parameter("regionFeather").set_float(m_region.feather);
|
||||
}
|
||||
if (m_effect->has_parameter("regionFeatherShift")) {
|
||||
m_effect->get_parameter("regionFeatherShift").set_float(m_region.feather_shift);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
@ -98,6 +98,18 @@ namespace Filter {
|
|||
double_t m_bilateralSmoothing;
|
||||
double_t m_bilateralSharpness;
|
||||
|
||||
// Regional
|
||||
struct Region {
|
||||
bool enabled;
|
||||
float_t left;
|
||||
float_t top;
|
||||
float_t right;
|
||||
float_t bottom;
|
||||
float_t feather;
|
||||
float_t feather_shift;
|
||||
bool invert;
|
||||
} m_region;
|
||||
|
||||
// Advanced
|
||||
bool m_errorLogged = false;
|
||||
uint64_t m_colorFormat;
|
||||
|
|
Loading…
Reference in a new issue