mirror of
https://github.com/Xaymar/obs-StreamFX
synced 2024-11-10 22:05:06 +00:00
filter-blur: Add proper mask options
* Removes the old 'Region' fields and places them under a 'Mask' option that can do much more. * Supported Mask types: Region, Image, Source. * Image and Source mask types allow for a color filter and multiplier.
This commit is contained in:
parent
a2a30b5fe1
commit
d56f4f9eac
6 changed files with 359 additions and 427 deletions
|
@ -9,14 +9,6 @@ uniform int u_radius;
|
||||||
uniform int u_diameter;
|
uniform int u_diameter;
|
||||||
uniform float2 u_texelDelta;
|
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)
|
// Settings (Private)
|
||||||
uniform float bilateralSmoothing;
|
uniform float bilateralSmoothing;
|
||||||
uniform float bilateralSharpness;
|
uniform float bilateralSharpness;
|
||||||
|
@ -93,68 +85,6 @@ float4 PSBilateral(VertDataOut v_in) : TARGET {
|
||||||
return BlurFunc(v_in.uv, rgba);
|
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
|
technique Draw
|
||||||
{
|
{
|
||||||
pass
|
pass
|
||||||
|
@ -163,37 +93,3 @@ technique Draw
|
||||||
pixel_shader = PSBilateral(v_in);
|
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
// OBS Default
|
// Parameters
|
||||||
|
/// OBS
|
||||||
uniform float4x4 ViewProj;
|
uniform float4x4 ViewProj;
|
||||||
|
/// Blur
|
||||||
// Settings (Shared)
|
|
||||||
uniform texture2d u_image;
|
uniform texture2d u_image;
|
||||||
uniform float2 u_imageSize;
|
uniform float2 u_imageSize;
|
||||||
uniform float2 u_imageTexel;
|
uniform float2 u_imageTexel;
|
||||||
|
@ -9,16 +9,8 @@ uniform int u_radius;
|
||||||
uniform int u_diameter;
|
uniform int u_diameter;
|
||||||
uniform float2 u_texelDelta;
|
uniform float2 u_texelDelta;
|
||||||
|
|
||||||
/// Region
|
|
||||||
uniform float regionLeft;
|
|
||||||
uniform float regionTop;
|
|
||||||
uniform float regionRight;
|
|
||||||
uniform float regionBottom;
|
|
||||||
uniform float regionFeather;
|
|
||||||
uniform float regionFeatherShift;
|
|
||||||
|
|
||||||
// Data
|
// Data
|
||||||
sampler_state textureSampler {
|
sampler_state pointSampler {
|
||||||
Filter = Point;
|
Filter = Point;
|
||||||
AddressU = Clamp;
|
AddressU = Clamp;
|
||||||
AddressV = Clamp;
|
AddressV = Clamp;
|
||||||
|
@ -48,79 +40,17 @@ VertDataOut VSDefault(VertDataIn v_in)
|
||||||
float4 BlurFunc(float2 uv, float4 rgba) {
|
float4 BlurFunc(float2 uv, float4 rgba) {
|
||||||
float4 final = rgba;
|
float4 final = rgba;
|
||||||
for (int k = 1; k <= u_radius; k++) {
|
for (int k = 1; k <= u_radius; k++) {
|
||||||
final += u_image.SampleLevel(textureSampler, uv + (u_texelDelta * k), 0);
|
final += u_image.SampleLevel(pointSampler, uv + (u_texelDelta * k), 0);
|
||||||
final += u_image.SampleLevel(textureSampler, uv - (u_texelDelta * k), 0);
|
final += u_image.SampleLevel(pointSampler, uv - (u_texelDelta * k), 0);
|
||||||
}
|
}
|
||||||
return final / u_diameter;
|
return final / u_diameter;
|
||||||
}
|
}
|
||||||
|
|
||||||
float4 PSBox(VertDataOut v_in) : TARGET {
|
float4 PSBox(VertDataOut v_in) : TARGET {
|
||||||
float4 rgba = u_image.SampleLevel(textureSampler, v_in.uv, 0);
|
float4 rgba = u_image.SampleLevel(pointSampler, v_in.uv, 0);
|
||||||
return BlurFunc(v_in.uv, rgba);
|
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
|
technique Draw
|
||||||
{
|
{
|
||||||
pass
|
pass
|
||||||
|
@ -129,39 +59,3 @@ technique Draw
|
||||||
pixel_shader = PSBox(v_in);
|
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,14 +9,6 @@ uniform int u_radius;
|
||||||
uniform int u_diameter;
|
uniform int u_diameter;
|
||||||
uniform float2 u_texelDelta;
|
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)
|
// Settings (Private)
|
||||||
//uniform float registerkernel[25];
|
//uniform float registerkernel[25];
|
||||||
uniform texture2d kernel;
|
uniform texture2d kernel;
|
||||||
|
@ -66,68 +58,6 @@ float4 PSGaussian(VertDataOut v_in) : TARGET {
|
||||||
return BlurFunc(v_in.uv, rgba);
|
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
|
technique Draw
|
||||||
{
|
{
|
||||||
pass
|
pass
|
||||||
|
@ -136,37 +66,3 @@ technique Draw
|
||||||
pixel_shader = PSGaussian(v_in);
|
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -53,6 +53,36 @@ Filter.Blur.Region.Feather.Shift.Description="Shift of the Feather area, positiv
|
||||||
Filter.Blur.Region.Invert="Invert Region"
|
Filter.Blur.Region.Invert="Invert Region"
|
||||||
Filter.Blur.Region.Invert.Description="Invert the region so that everything but this area is blurred."
|
Filter.Blur.Region.Invert.Description="Invert the region so that everything but this area is blurred."
|
||||||
Filter.Blur.ColorFormat="Color Format"
|
Filter.Blur.ColorFormat="Color Format"
|
||||||
|
Filter.Blur.Mask="Apply a Mask"
|
||||||
|
Filter.Blur.Mask.Description="Apply a mask to the area that needs to be blurred, which allows for more control over the blurred area."
|
||||||
|
Filter.Blur.Mask.Type="Mask Type"
|
||||||
|
Filter.Blur.Mask.Type.Description="What kind of mask to you want to apply?"
|
||||||
|
Filter.Blur.Mask.Type.Region="Region"
|
||||||
|
Filter.Blur.Mask.Type.Image="Image"
|
||||||
|
Filter.Blur.Mask.Type.Source="Source"
|
||||||
|
Filter.Blur.Mask.Region.Left="Left Edge"
|
||||||
|
Filter.Blur.Mask.Region.Left.Description="Distance to left edge of the source in percent."
|
||||||
|
Filter.Blur.Mask.Region.Top="Top Edge"
|
||||||
|
Filter.Blur.Mask.Region.Top.Description="Distance to top edge of the source in percent."
|
||||||
|
Filter.Blur.Mask.Region.Right="Right Edge"
|
||||||
|
Filter.Blur.Mask.Region.Right.Description="Distance to right edge of the source in percent."
|
||||||
|
Filter.Blur.Mask.Region.Bottom="Bottom Edge"
|
||||||
|
Filter.Blur.Mask.Region.Bottom.Description="Distance to bottom edge of the source in percent."
|
||||||
|
Filter.Blur.Mask.Region.Feather="Feather Area"
|
||||||
|
Filter.Blur.Mask.Region.Feather.Description="Size of the smoothing area in percent, or 0 to turn off feather."
|
||||||
|
Filter.Blur.Mask.Region.Feather.Shift="Feather Shift"
|
||||||
|
Filter.Blur.Mask.Region.Feather.Shift.Description="Shift of the Feather area, positive is inwards, negative is outwards."
|
||||||
|
Filter.Blur.Mask.Region.Invert="Invert Region"
|
||||||
|
Filter.Blur.Mask.Region.Invert.Description="Invert the region so that everything but this area is blurred."
|
||||||
|
Filter.Blur.Mask.Image="Image Mask"
|
||||||
|
Filter.Blur.Mask.Image.Description="Image to use for the mask."
|
||||||
|
Filter.Blur.Mask.Source="Source Mask"
|
||||||
|
Filter.Blur.Mask.Source.Description="Source to use for the mask."
|
||||||
|
Filter.Blur.Mask.Color="Mask Color Filter"
|
||||||
|
Filter.Blur.Mask.Color.Description="Filter the mask by this color before applying it."
|
||||||
|
Filter.Blur.Mask.Multiplier="Mask Multiplier"
|
||||||
|
Filter.Blur.Mask.Multiplier.Description="Multiply the final mask value by this value."
|
||||||
|
|
||||||
|
|
||||||
# Filter - Custom Shader
|
# Filter - Custom Shader
|
||||||
Filter.CustomShader="Custom Shader"
|
Filter.CustomShader="Custom Shader"
|
||||||
|
|
|
@ -43,15 +43,23 @@ extern "C" {
|
||||||
#define P_SIZE "Filter.Blur.Size"
|
#define P_SIZE "Filter.Blur.Size"
|
||||||
#define P_BILATERAL_SMOOTHING "Filter.Blur.Bilateral.Smoothing"
|
#define P_BILATERAL_SMOOTHING "Filter.Blur.Bilateral.Smoothing"
|
||||||
#define P_BILATERAL_SHARPNESS "Filter.Blur.Bilateral.Sharpness"
|
#define P_BILATERAL_SHARPNESS "Filter.Blur.Bilateral.Sharpness"
|
||||||
#define P_REGION "Filter.Blur.Region"
|
|
||||||
#define P_REGION_LEFT "Filter.Blur.Region.Left"
|
|
||||||
#define P_REGION_RIGHT "Filter.Blur.Region.Right"
|
|
||||||
#define P_REGION_TOP "Filter.Blur.Region.Top"
|
|
||||||
#define P_REGION_BOTTOM "Filter.Blur.Region.Bottom"
|
|
||||||
#define P_REGION_FEATHER "Filter.Blur.Region.Feather"
|
|
||||||
#define P_REGION_FEATHER_SHIFT "Filter.Blur.Region.Feather.Shift"
|
|
||||||
#define P_REGION_INVERT "Filter.Blur.Region.Invert"
|
|
||||||
#define P_COLORFORMAT "Filter.Blur.ColorFormat"
|
#define P_COLORFORMAT "Filter.Blur.ColorFormat"
|
||||||
|
#define P_MASK "Filter.Blur.Mask"
|
||||||
|
#define P_MASK_TYPE "Filter.Blur.Mask.Type"
|
||||||
|
#define P_MASK_TYPE_REGION "Filter.Blur.Mask.Type.Region"
|
||||||
|
#define P_MASK_TYPE_IMAGE "Filter.Blur.Mask.Type.Image"
|
||||||
|
#define P_MASK_TYPE_SOURCE "Filter.Blur.Mask.Type.Source"
|
||||||
|
#define P_MASK_REGION_LEFT "Filter.Blur.Mask.Region.Left"
|
||||||
|
#define P_MASK_REGION_RIGHT "Filter.Blur.Mask.Region.Right"
|
||||||
|
#define P_MASK_REGION_TOP "Filter.Blur.Mask.Region.Top"
|
||||||
|
#define P_MASK_REGION_BOTTOM "Filter.Blur.Mask.Region.Bottom"
|
||||||
|
#define P_MASK_REGION_FEATHER "Filter.Blur.Mask.Region.Feather"
|
||||||
|
#define P_MASK_REGION_FEATHER_SHIFT "Filter.Blur.Mask.Region.Feather.Shift"
|
||||||
|
#define P_MASK_REGION_INVERT "Filter.Blur.Mask.Region.Invert"
|
||||||
|
#define P_MASK_IMAGE "Filter.Blur.Mask.Image"
|
||||||
|
#define P_MASK_SOURCE "Filter.Blur.Mask.Source"
|
||||||
|
#define P_MASK_COLOR "Filter.Blur.Mask.Color"
|
||||||
|
#define P_MASK_MULTIPLIER "Filter.Blur.Mask.Multiplier"
|
||||||
|
|
||||||
// Initializer & Finalizer
|
// Initializer & Finalizer
|
||||||
INITIALIZER(filterBlurFactoryInitializer)
|
INITIALIZER(filterBlurFactoryInitializer)
|
||||||
|
@ -89,34 +97,12 @@ bool filter::blur::instance::apply_shared_param(gs_texture_t* input, float texel
|
||||||
result = result && gs_set_param_int(blur_effect->get_object(), "u_radius", (int)size);
|
result = result && gs_set_param_int(blur_effect->get_object(), "u_radius", (int)size);
|
||||||
result = result && gs_set_param_int(blur_effect->get_object(), "u_diameter", (int)(1 + (size * 2)));
|
result = result && gs_set_param_int(blur_effect->get_object(), "u_diameter", (int)(1 + (size * 2)));
|
||||||
|
|
||||||
if (region.enabled) {
|
|
||||||
if (blur_effect->has_parameter("regionLeft")) {
|
|
||||||
blur_effect->get_parameter("regionLeft").set_float(region.left);
|
|
||||||
}
|
|
||||||
if (blur_effect->has_parameter("regionTop")) {
|
|
||||||
blur_effect->get_parameter("regionTop").set_float(region.top);
|
|
||||||
}
|
|
||||||
if (blur_effect->has_parameter("regionRight")) {
|
|
||||||
blur_effect->get_parameter("regionRight").set_float(region.right);
|
|
||||||
}
|
|
||||||
if (blur_effect->has_parameter("regionBottom")) {
|
|
||||||
blur_effect->get_parameter("regionBottom").set_float(region.bottom);
|
|
||||||
}
|
|
||||||
if (blur_effect->has_parameter("regionFeather")) {
|
|
||||||
blur_effect->get_parameter("regionFeather").set_float(region.feather);
|
|
||||||
}
|
|
||||||
if (blur_effect->has_parameter("regionFeatherShift")) {
|
|
||||||
blur_effect->get_parameter("regionFeatherShift").set_float(region.feather_shift);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool filter::blur::instance::apply_bilateral_param()
|
bool filter::blur::instance::apply_bilateral_param()
|
||||||
{
|
{
|
||||||
gs_eparam_t* param;
|
|
||||||
|
|
||||||
if (type != type::Bilateral)
|
if (type != type::Bilateral)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -150,24 +136,103 @@ bool filter::blur::instance::apply_gaussian_param()
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool filter::blur::instance::apply_mask_parameters(std::shared_ptr<gs::effect> effect, gs_texture_t * original_texture, gs_texture_t* blurred_texture)
|
||||||
|
{
|
||||||
|
if (effect->has_parameter("image_orig")) {
|
||||||
|
effect->get_parameter("image_orig").set_texture(original_texture);
|
||||||
|
}
|
||||||
|
if (effect->has_parameter("image_blur")) {
|
||||||
|
effect->get_parameter("image_blur").set_texture(blurred_texture);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Region
|
||||||
|
if (mask.type == mask_type::Region) {
|
||||||
|
if (effect->has_parameter("mask_region_left")) {
|
||||||
|
effect->get_parameter("mask_region_left").set_float(mask.region.left);
|
||||||
|
}
|
||||||
|
if (effect->has_parameter("mask_region_right")) {
|
||||||
|
effect->get_parameter("mask_region_right").set_float(mask.region.right);
|
||||||
|
}
|
||||||
|
if (effect->has_parameter("mask_region_top")) {
|
||||||
|
effect->get_parameter("mask_region_top").set_float(mask.region.top);
|
||||||
|
}
|
||||||
|
if (effect->has_parameter("mask_region_bottom")) {
|
||||||
|
effect->get_parameter("mask_region_bottom").set_float(mask.region.bottom);
|
||||||
|
}
|
||||||
|
if (effect->has_parameter("mask_region_feather")) {
|
||||||
|
effect->get_parameter("mask_region_feather").set_float(mask.region.feather);
|
||||||
|
}
|
||||||
|
if (effect->has_parameter("mask_region_feather_shift")) {
|
||||||
|
effect->get_parameter("mask_region_feather_shift").set_float(mask.region.feather_shift);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Image
|
||||||
|
if (mask.type == mask_type::Image) {
|
||||||
|
if (effect->has_parameter("mask_image")) {
|
||||||
|
if (mask.image.texture) {
|
||||||
|
effect->get_parameter("mask_image").set_texture(mask.image.texture);
|
||||||
|
} else {
|
||||||
|
effect->get_parameter("mask_image").set_texture(nullptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Source
|
||||||
|
if (mask.type == mask_type::Source) {
|
||||||
|
if (effect->has_parameter("mask_image")) {
|
||||||
|
if (mask.source.texture) {
|
||||||
|
effect->get_parameter("mask_image").set_texture(mask.source.texture);
|
||||||
|
} else {
|
||||||
|
effect->get_parameter("mask_image").set_texture(nullptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Shared
|
||||||
|
if (effect->has_parameter("mask_color")) {
|
||||||
|
effect->get_parameter("mask_color")
|
||||||
|
.set_float4((mask.color & 0xFF) / 255.0f, ((mask.color >> 8) & 0xFF) / 255.0f,
|
||||||
|
((mask.color >> 16) & 0xFF) / 255.0f, ((mask.color >> 24) & 0xFF) / 255.0f);
|
||||||
|
}
|
||||||
|
if (effect->has_parameter("mask_multiplier")) {
|
||||||
|
effect->get_parameter("mask_multiplier").set_float(mask.multiplier);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool filter::blur::instance::modified_properties(void* ptr, obs_properties_t* props, obs_property* prop,
|
bool filter::blur::instance::modified_properties(void* ptr, obs_properties_t* props, obs_property* prop,
|
||||||
obs_data_t* settings)
|
obs_data_t* settings)
|
||||||
{
|
{
|
||||||
bool showBilateral = (obs_data_get_int(settings, P_TYPE) == type::Bilateral);
|
bool showBilateral = (obs_data_get_int(settings, P_TYPE) == type::Bilateral);
|
||||||
|
|
||||||
|
prop;
|
||||||
|
ptr;
|
||||||
|
|
||||||
// bilateral blur
|
// bilateral blur
|
||||||
obs_property_set_visible(obs_properties_get(props, P_BILATERAL_SMOOTHING), showBilateral);
|
obs_property_set_visible(obs_properties_get(props, P_BILATERAL_SMOOTHING), showBilateral);
|
||||||
obs_property_set_visible(obs_properties_get(props, P_BILATERAL_SHARPNESS), showBilateral);
|
obs_property_set_visible(obs_properties_get(props, P_BILATERAL_SHARPNESS), showBilateral);
|
||||||
|
|
||||||
// region
|
// region
|
||||||
bool showRegion = obs_data_get_bool(settings, P_REGION);
|
bool show_mask = obs_data_get_bool(settings, P_MASK);
|
||||||
obs_property_set_visible(obs_properties_get(props, P_REGION_LEFT), showRegion);
|
mask_type mtype = static_cast<mask_type>(obs_data_get_int(settings, P_MASK_TYPE));
|
||||||
obs_property_set_visible(obs_properties_get(props, P_REGION_TOP), showRegion);
|
bool show_region = (mtype == mask_type::Region) && show_mask;
|
||||||
obs_property_set_visible(obs_properties_get(props, P_REGION_RIGHT), showRegion);
|
bool show_image = (mtype == mask_type::Image) && show_mask;
|
||||||
obs_property_set_visible(obs_properties_get(props, P_REGION_BOTTOM), showRegion);
|
bool show_source = (mtype == mask_type::Source) && show_mask;
|
||||||
obs_property_set_visible(obs_properties_get(props, P_REGION_FEATHER), showRegion);
|
|
||||||
obs_property_set_visible(obs_properties_get(props, P_REGION_FEATHER_SHIFT), showRegion);
|
obs_property_set_visible(obs_properties_get(props, P_MASK_REGION_LEFT), show_region);
|
||||||
obs_property_set_visible(obs_properties_get(props, P_REGION_INVERT), showRegion);
|
obs_property_set_visible(obs_properties_get(props, P_MASK_REGION_TOP), show_region);
|
||||||
|
obs_property_set_visible(obs_properties_get(props, P_MASK_REGION_RIGHT), show_region);
|
||||||
|
obs_property_set_visible(obs_properties_get(props, P_MASK_REGION_BOTTOM), show_region);
|
||||||
|
obs_property_set_visible(obs_properties_get(props, P_MASK_REGION_FEATHER), show_region);
|
||||||
|
obs_property_set_visible(obs_properties_get(props, P_MASK_REGION_FEATHER_SHIFT), show_region);
|
||||||
|
obs_property_set_visible(obs_properties_get(props, P_MASK_REGION_INVERT), show_region);
|
||||||
|
|
||||||
|
obs_property_set_visible(obs_properties_get(props, P_MASK_IMAGE), show_image);
|
||||||
|
obs_property_set_visible(obs_properties_get(props, P_MASK_SOURCE), show_source);
|
||||||
|
obs_property_set_visible(obs_properties_get(props, P_MASK_COLOR), show_image || show_source);
|
||||||
|
obs_property_set_visible(obs_properties_get(props, P_MASK_MULTIPLIER), show_image || show_source);
|
||||||
|
|
||||||
// advanced
|
// advanced
|
||||||
bool showAdvanced = obs_data_get_bool(settings, S_ADVANCED);
|
bool showAdvanced = obs_data_get_bool(settings, S_ADVANCED);
|
||||||
|
@ -245,25 +310,52 @@ obs_properties_t* filter::blur::instance::get_properties()
|
||||||
0.01);
|
0.01);
|
||||||
obs_property_set_long_description(p, P_TRANSLATE(P_DESC(P_BILATERAL_SHARPNESS)));
|
obs_property_set_long_description(p, P_TRANSLATE(P_DESC(P_BILATERAL_SHARPNESS)));
|
||||||
|
|
||||||
// region
|
// Mask
|
||||||
p = obs_properties_add_bool(pr, P_REGION, P_TRANSLATE(P_REGION));
|
p = obs_properties_add_bool(pr, P_MASK, P_TRANSLATE(P_MASK));
|
||||||
obs_property_set_long_description(p, P_TRANSLATE(P_DESC(P_REGION)));
|
obs_property_set_long_description(p, P_TRANSLATE(P_DESC(P_MASK)));
|
||||||
obs_property_set_modified_callback2(p, modified_properties, this);
|
obs_property_set_modified_callback2(p, modified_properties, this);
|
||||||
p = obs_properties_add_float_slider(pr, P_REGION_LEFT, P_TRANSLATE(P_REGION_LEFT), 0.0, 100.0, 0.01);
|
p = obs_properties_add_list(pr, P_MASK_TYPE, P_TRANSLATE(P_MASK_TYPE), OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT);
|
||||||
obs_property_set_long_description(p, P_TRANSLATE(P_DESC(P_REGION_LEFT)));
|
obs_property_set_long_description(p, P_TRANSLATE(P_DESC(P_MASK_TYPE)));
|
||||||
p = obs_properties_add_float_slider(pr, P_REGION_TOP, P_TRANSLATE(P_REGION_TOP), 0.0, 100.0, 0.01);
|
obs_property_set_modified_callback2(p, modified_properties, this);
|
||||||
obs_property_set_long_description(p, P_TRANSLATE(P_DESC(P_REGION_TOP)));
|
obs_property_list_add_int(p, P_TRANSLATE(P_MASK_TYPE_REGION), mask_type::Region);
|
||||||
p = obs_properties_add_float_slider(pr, P_REGION_RIGHT, P_TRANSLATE(P_REGION_RIGHT), 0.0, 100.0, 0.01);
|
obs_property_list_add_int(p, P_TRANSLATE(P_MASK_TYPE_IMAGE), mask_type::Image);
|
||||||
obs_property_set_long_description(p, P_TRANSLATE(P_DESC(P_REGION_RIGHT)));
|
obs_property_list_add_int(p, P_TRANSLATE(P_MASK_TYPE_SOURCE), mask_type::Source);
|
||||||
p = obs_properties_add_float_slider(pr, P_REGION_BOTTOM, P_TRANSLATE(P_REGION_BOTTOM), 0.0, 100.0, 0.01);
|
/// Region
|
||||||
obs_property_set_long_description(p, P_TRANSLATE(P_DESC(P_REGION_BOTTOM)));
|
p = obs_properties_add_float_slider(pr, P_MASK_REGION_LEFT, P_TRANSLATE(P_MASK_REGION_LEFT), 0.0, 100.0, 0.01);
|
||||||
p = obs_properties_add_float_slider(pr, P_REGION_FEATHER, P_TRANSLATE(P_REGION_FEATHER), 0.0, 50.0, 0.01);
|
obs_property_set_long_description(p, P_TRANSLATE(P_DESC(P_MASK_REGION_LEFT)));
|
||||||
obs_property_set_long_description(p, P_TRANSLATE(P_DESC(P_REGION_FEATHER)));
|
p = obs_properties_add_float_slider(pr, P_MASK_REGION_TOP, P_TRANSLATE(P_MASK_REGION_TOP), 0.0, 100.0, 0.01);
|
||||||
p = obs_properties_add_float_slider(pr, P_REGION_FEATHER_SHIFT, P_TRANSLATE(P_REGION_FEATHER_SHIFT), -100.0, 100.0,
|
obs_property_set_long_description(p, P_TRANSLATE(P_DESC(P_MASK_REGION_TOP)));
|
||||||
0.01);
|
p = obs_properties_add_float_slider(pr, P_MASK_REGION_RIGHT, P_TRANSLATE(P_MASK_REGION_RIGHT), 0.0, 100.0, 0.01);
|
||||||
obs_property_set_long_description(p, P_TRANSLATE(P_DESC(P_REGION_FEATHER_SHIFT)));
|
obs_property_set_long_description(p, P_TRANSLATE(P_DESC(P_MASK_REGION_RIGHT)));
|
||||||
p = obs_properties_add_bool(pr, P_REGION_INVERT, P_TRANSLATE(P_REGION_INVERT));
|
p = obs_properties_add_float_slider(pr, P_MASK_REGION_BOTTOM, P_TRANSLATE(P_MASK_REGION_BOTTOM), 0.0, 100.0, 0.01);
|
||||||
obs_property_set_long_description(p, P_TRANSLATE(P_DESC(P_REGION_INVERT)));
|
obs_property_set_long_description(p, P_TRANSLATE(P_DESC(P_MASK_REGION_BOTTOM)));
|
||||||
|
p = obs_properties_add_float_slider(pr, P_MASK_REGION_FEATHER, P_TRANSLATE(P_MASK_REGION_FEATHER), 0.0, 50.0, 0.01);
|
||||||
|
obs_property_set_long_description(p, P_TRANSLATE(P_DESC(P_MASK_REGION_FEATHER)));
|
||||||
|
p = obs_properties_add_float_slider(pr, P_MASK_REGION_FEATHER_SHIFT, P_TRANSLATE(P_MASK_REGION_FEATHER_SHIFT),
|
||||||
|
-100.0, 100.0, 0.01);
|
||||||
|
obs_property_set_long_description(p, P_TRANSLATE(P_DESC(P_MASK_REGION_FEATHER_SHIFT)));
|
||||||
|
p = obs_properties_add_bool(pr, P_MASK_REGION_INVERT, P_TRANSLATE(P_MASK_REGION_INVERT));
|
||||||
|
obs_property_set_long_description(p, P_TRANSLATE(P_DESC(P_MASK_REGION_INVERT)));
|
||||||
|
/// Image
|
||||||
|
p = obs_properties_add_path(pr, P_MASK_IMAGE, P_TRANSLATE(P_MASK_IMAGE), OBS_PATH_FILE,
|
||||||
|
P_TRANSLATE(S_FILEFILTERS_IMAGES), nullptr);
|
||||||
|
obs_property_set_long_description(p, P_TRANSLATE(P_DESC(P_MASK_IMAGE)));
|
||||||
|
/// Source
|
||||||
|
p = obs_properties_add_list(pr, P_MASK_SOURCE, P_TRANSLATE(P_MASK_SOURCE), OBS_COMBO_TYPE_LIST,
|
||||||
|
OBS_COMBO_FORMAT_STRING);
|
||||||
|
obs_property_set_long_description(p, P_TRANSLATE(P_DESC(P_MASK_SOURCE)));
|
||||||
|
obs_enum_sources(
|
||||||
|
[](void* ptr, obs_source_t* source) {
|
||||||
|
obs_property_t* p = reinterpret_cast<obs_property_t*>(ptr);
|
||||||
|
obs_property_list_add_string(p, obs_source_get_name(source), obs_source_get_name(source));
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
p);
|
||||||
|
/// Shared
|
||||||
|
p = obs_properties_add_color(pr, P_MASK_COLOR, P_TRANSLATE(P_MASK_COLOR));
|
||||||
|
obs_property_set_long_description(p, P_TRANSLATE(P_DESC(P_MASK_COLOR)));
|
||||||
|
p = obs_properties_add_float_slider(pr, P_MASK_MULTIPLIER, P_TRANSLATE(P_MASK_MULTIPLIER), 0.0, 10.0, 0.01);
|
||||||
|
obs_property_set_long_description(p, P_TRANSLATE(P_DESC(P_MASK_MULTIPLIER)));
|
||||||
|
|
||||||
// advanced
|
// advanced
|
||||||
p = obs_properties_add_bool(pr, S_ADVANCED, P_TRANSLATE(S_ADVANCED));
|
p = obs_properties_add_bool(pr, S_ADVANCED, P_TRANSLATE(S_ADVANCED));
|
||||||
|
@ -290,15 +382,30 @@ void filter::blur::instance::update(obs_data_t* settings)
|
||||||
bilateral_sharpness = obs_data_get_double(settings, P_BILATERAL_SHARPNESS) / 100.0;
|
bilateral_sharpness = obs_data_get_double(settings, P_BILATERAL_SHARPNESS) / 100.0;
|
||||||
|
|
||||||
// region
|
// region
|
||||||
region.enabled = obs_data_get_bool(settings, P_REGION);
|
mask.enabled = obs_data_get_bool(settings, P_MASK);
|
||||||
if (region.enabled) {
|
if (mask.enabled) {
|
||||||
region.left = float_t(obs_data_get_double(settings, P_REGION_LEFT) / 100.0);
|
mask.type = static_cast<mask_type>(obs_data_get_int(settings, P_MASK_TYPE));
|
||||||
region.top = float_t(obs_data_get_double(settings, P_REGION_TOP) / 100.0);
|
switch (mask.type) {
|
||||||
region.right = 1.0 - float_t(obs_data_get_double(settings, P_REGION_RIGHT) / 100.0);
|
case mask_type::Region:
|
||||||
region.bottom = 1.0 - float_t(obs_data_get_double(settings, P_REGION_BOTTOM) / 100.0);
|
mask.region.left = float_t(obs_data_get_double(settings, P_MASK_REGION_LEFT) / 100.0);
|
||||||
region.feather = float_t(obs_data_get_double(settings, P_REGION_FEATHER) / 100.0);
|
mask.region.top = float_t(obs_data_get_double(settings, P_MASK_REGION_TOP) / 100.0);
|
||||||
region.feather_shift = float_t(obs_data_get_double(settings, P_REGION_FEATHER_SHIFT) / 100.0);
|
mask.region.right = 1.0f - float_t(obs_data_get_double(settings, P_MASK_REGION_RIGHT) / 100.0);
|
||||||
region.invert = obs_data_get_bool(settings, P_REGION_INVERT);
|
mask.region.bottom = 1.0f - float_t(obs_data_get_double(settings, P_MASK_REGION_BOTTOM) / 100.0);
|
||||||
|
mask.region.feather = float_t(obs_data_get_double(settings, P_MASK_REGION_FEATHER) / 100.0);
|
||||||
|
mask.region.feather_shift = float_t(obs_data_get_double(settings, P_MASK_REGION_FEATHER_SHIFT) / 100.0);
|
||||||
|
mask.region.invert = obs_data_get_bool(settings, P_MASK_REGION_INVERT);
|
||||||
|
break;
|
||||||
|
case mask_type::Image:
|
||||||
|
mask.image.path = obs_data_get_string(settings, P_MASK_IMAGE);
|
||||||
|
break;
|
||||||
|
case mask_type::Source:
|
||||||
|
mask.source.name = obs_data_get_string(settings, P_MASK_SOURCE);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if ((mask.type == mask_type::Image) || (mask.type == mask_type::Source)) {
|
||||||
|
mask.color = static_cast<uint32_t>(obs_data_get_int(settings, P_MASK_COLOR));
|
||||||
|
mask.multiplier = float_t(obs_data_get_double(settings, P_MASK_MULTIPLIER));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// advanced
|
// advanced
|
||||||
|
@ -465,16 +572,7 @@ void filter::blur::instance::video_render(gs_effect_t* effect)
|
||||||
};
|
};
|
||||||
|
|
||||||
std::string pass = "Draw";
|
std::string pass = "Draw";
|
||||||
if (region.enabled) {
|
|
||||||
if (region.feather > 0) {
|
|
||||||
pass = "DrawRegionFeather";
|
|
||||||
} else {
|
|
||||||
pass = "DrawRegion";
|
|
||||||
}
|
|
||||||
if (region.invert) {
|
|
||||||
pass += "Invert";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (auto v : kvs) {
|
for (auto v : kvs) {
|
||||||
const char* name = std::get<0>(v);
|
const char* name = std::get<0>(v);
|
||||||
gs_texrender_t* rt = std::get<1>(v);
|
gs_texrender_t* rt = std::get<1>(v);
|
||||||
|
@ -520,6 +618,53 @@ void filter::blur::instance::video_render(gs_effect_t* effect)
|
||||||
}
|
}
|
||||||
#pragma endregion blur
|
#pragma endregion blur
|
||||||
|
|
||||||
|
#pragma region Mask
|
||||||
|
if (mask.enabled) {
|
||||||
|
std::string technique = "";
|
||||||
|
switch (mask.type) {
|
||||||
|
case Region:
|
||||||
|
if (mask.region.feather > 0.001) {
|
||||||
|
if (mask.region.invert) {
|
||||||
|
technique = "RegionFeatherInverted";
|
||||||
|
} else {
|
||||||
|
technique = "RegionFeather";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (mask.region.invert) {
|
||||||
|
technique = "RegionInverted";
|
||||||
|
} else {
|
||||||
|
technique = "Region";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case Image:
|
||||||
|
case Source:
|
||||||
|
technique = "Image";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
gs_texrender_reset(horizontal_rendertarget);
|
||||||
|
if (gs_texrender_begin(horizontal_rendertarget, baseW, baseH)) {
|
||||||
|
std::shared_ptr<gs::effect> mask_effect = factory::get()->get_mask_effect();
|
||||||
|
apply_mask_parameters(mask_effect, sourceTexture, blurred);
|
||||||
|
|
||||||
|
// Camera
|
||||||
|
gs_ortho(0, (float)baseW, 0, (float)baseH, -1, 1);
|
||||||
|
gs_clear(GS_CLEAR_COLOR | GS_CLEAR_DEPTH, &black, 0, 0);
|
||||||
|
|
||||||
|
// Render
|
||||||
|
while (gs_effect_loop(mask_effect->get_object(), technique.c_str())) {
|
||||||
|
gs_draw_sprite(blurred, 0, baseW, baseH);
|
||||||
|
}
|
||||||
|
|
||||||
|
gs_texrender_end(horizontal_rendertarget);
|
||||||
|
|
||||||
|
blurred = gs_texrender_get_texture(horizontal_rendertarget);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma endregion
|
||||||
|
|
||||||
#pragma region YUV->RGB or straight draw
|
#pragma region YUV->RGB or straight draw
|
||||||
// Draw final effect
|
// Draw final effect
|
||||||
{
|
{
|
||||||
|
@ -586,22 +731,52 @@ filter::blur::factory::~factory() {}
|
||||||
void filter::blur::factory::on_list_fill()
|
void filter::blur::factory::on_list_fill()
|
||||||
{
|
{
|
||||||
obs_enter_graphics();
|
obs_enter_graphics();
|
||||||
std::pair<blur::type, std::string> shader_list[] = {
|
|
||||||
{type::Box, obs_module_file("effects/box-blur.effect")},
|
{
|
||||||
{type::Gaussian, obs_module_file("effects/gaussian-blur.effect")},
|
char* file = obs_module_file("effects/box-blur.effect");
|
||||||
{type::Bilateral, obs_module_file("effects/bilateral-blur.effect")},
|
|
||||||
};
|
|
||||||
for (auto& kv : shader_list) {
|
|
||||||
try {
|
try {
|
||||||
std::shared_ptr<gs::effect> effect = std::make_shared<gs::effect>(kv.second);
|
effects.insert_or_assign(type::Box, std::make_shared<gs::effect>(file));
|
||||||
effects.insert(std::make_pair(kv.first, effect));
|
|
||||||
} catch (std::runtime_error ex) {
|
} catch (std::runtime_error ex) {
|
||||||
P_LOG_ERROR("<filter-blur> Loading effect '%s' failed with error(s): %s", kv.second.c_str(), ex.what());
|
P_LOG_ERROR("<filter-blur> Loading effect '%s' failed with error(s): %s", file, ex.what());
|
||||||
obs_leave_graphics();
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
bfree(file);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
char* file = obs_module_file("effects/gaussian-blur.effect");
|
||||||
|
try {
|
||||||
|
effects.insert_or_assign(type::Gaussian, std::make_shared<gs::effect>(file));
|
||||||
|
} catch (std::runtime_error ex) {
|
||||||
|
P_LOG_ERROR("<filter-blur> Loading effect '%s' failed with error(s): %s", file, ex.what());
|
||||||
|
}
|
||||||
|
bfree(file);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
char* file = obs_module_file("effects/bilateral-blur.effect");
|
||||||
|
try {
|
||||||
|
effects.insert_or_assign(type::Bilateral, std::make_shared<gs::effect>(file));
|
||||||
|
} catch (std::runtime_error ex) {
|
||||||
|
P_LOG_ERROR("<filter-blur> Loading effect '%s' failed with error(s): %s", file, ex.what());
|
||||||
|
}
|
||||||
|
bfree(file);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
char* file = obs_module_file("effects/color-conversion.effect");
|
||||||
|
try {
|
||||||
|
color_converter_effect = std::make_shared<gs::effect>(file);
|
||||||
|
} catch (std::runtime_error ex) {
|
||||||
|
P_LOG_ERROR("<filter-blur> Loading effect '%s' failed with error(s): %s", file, ex.what());
|
||||||
|
}
|
||||||
|
bfree(file);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
char* file = obs_module_file("effects/mask.effect");
|
||||||
|
try {
|
||||||
|
mask_effect = std::make_shared<gs::effect>(file);
|
||||||
|
} catch (std::runtime_error ex) {
|
||||||
|
P_LOG_ERROR("<filter-blur> Loading effect '%s' failed with error(s): %s", file, ex.what());
|
||||||
|
}
|
||||||
|
bfree(file);
|
||||||
}
|
}
|
||||||
color_converter_effect = std::make_shared<gs::effect>(obs_module_file("effects/color-conversion.effect")),
|
|
||||||
|
|
||||||
generate_kernel_textures();
|
generate_kernel_textures();
|
||||||
obs_leave_graphics();
|
obs_leave_graphics();
|
||||||
|
@ -612,13 +787,15 @@ void filter::blur::factory::on_list_empty()
|
||||||
obs_enter_graphics();
|
obs_enter_graphics();
|
||||||
effects.clear();
|
effects.clear();
|
||||||
kernels.clear();
|
kernels.clear();
|
||||||
|
color_converter_effect.reset();
|
||||||
|
mask_effect.reset();
|
||||||
obs_leave_graphics();
|
obs_leave_graphics();
|
||||||
}
|
}
|
||||||
|
|
||||||
void filter::blur::factory::generate_gaussian_kernels()
|
void filter::blur::factory::generate_gaussian_kernels()
|
||||||
{
|
{
|
||||||
// 2D texture, horizontal is value, vertical is kernel size.
|
// 2D texture, horizontal is value, vertical is kernel size.
|
||||||
size_t size_power_of_two = pow(2, util::math::get_power_of_two_exponent_ceil(max_kernel_size));
|
size_t size_power_of_two = size_t(pow(2, util::math::get_power_of_two_exponent_ceil(max_kernel_size)));
|
||||||
|
|
||||||
std::vector<float_t> texture_Data(size_power_of_two * size_power_of_two);
|
std::vector<float_t> texture_Data(size_power_of_two * size_power_of_two);
|
||||||
std::vector<float_t> math_data(size_power_of_two);
|
std::vector<float_t> math_data(size_power_of_two);
|
||||||
|
@ -687,14 +864,21 @@ void filter::blur::factory::get_defaults(obs_data_t* data)
|
||||||
obs_data_set_default_double(data, P_BILATERAL_SHARPNESS, 90.0);
|
obs_data_set_default_double(data, P_BILATERAL_SHARPNESS, 90.0);
|
||||||
|
|
||||||
// region
|
// region
|
||||||
obs_data_set_default_bool(data, P_REGION, false);
|
obs_data_set_default_bool(data, P_MASK, false);
|
||||||
obs_data_set_default_double(data, P_REGION_LEFT, 0.0f);
|
obs_data_set_default_int(data, P_MASK_TYPE, mask_type::Region);
|
||||||
obs_data_set_default_double(data, P_REGION_TOP, 0.0f);
|
obs_data_set_default_double(data, P_MASK_REGION_LEFT, 0.0f);
|
||||||
obs_data_set_default_double(data, P_REGION_RIGHT, 0.0f);
|
obs_data_set_default_double(data, P_MASK_REGION_RIGHT, 0.0f);
|
||||||
obs_data_set_default_double(data, P_REGION_BOTTOM, 0.0f);
|
obs_data_set_default_double(data, P_MASK_REGION_TOP, 0.0f);
|
||||||
obs_data_set_default_double(data, P_REGION_FEATHER, 0.0f);
|
obs_data_set_default_double(data, P_MASK_REGION_BOTTOM, 0.0f);
|
||||||
obs_data_set_default_double(data, P_REGION_FEATHER_SHIFT, 0.0f);
|
obs_data_set_default_double(data, P_MASK_REGION_FEATHER, 0.0f);
|
||||||
obs_data_set_default_bool(data, P_REGION_INVERT, false);
|
obs_data_set_default_double(data, P_MASK_REGION_FEATHER_SHIFT, 0.0f);
|
||||||
|
obs_data_set_default_bool(data, P_MASK_REGION_INVERT, false);
|
||||||
|
char* default_file = obs_module_file("white.png");
|
||||||
|
obs_data_set_default_string(data, P_MASK_IMAGE, default_file);
|
||||||
|
bfree(default_file);
|
||||||
|
obs_data_set_default_string(data, P_MASK_SOURCE, "");
|
||||||
|
obs_data_set_default_int(data, P_MASK_COLOR, 0xFFFFFFFF);
|
||||||
|
obs_data_set_default_double(data, P_MASK_MULTIPLIER, 1.0);
|
||||||
|
|
||||||
// advanced
|
// advanced
|
||||||
obs_data_set_default_bool(data, S_ADVANCED, false);
|
obs_data_set_default_bool(data, S_ADVANCED, false);
|
||||||
|
@ -713,6 +897,7 @@ void filter::blur::factory::update(void* inptr, obs_data_t* settings)
|
||||||
|
|
||||||
const char* filter::blur::factory::get_name(void* inptr)
|
const char* filter::blur::factory::get_name(void* inptr)
|
||||||
{
|
{
|
||||||
|
inptr;
|
||||||
return P_TRANSLATE(SOURCE_NAME);
|
return P_TRANSLATE(SOURCE_NAME);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -756,6 +941,11 @@ std::shared_ptr<gs::effect> filter::blur::factory::get_color_converter_effect()
|
||||||
return color_converter_effect;
|
return color_converter_effect;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<gs::effect> filter::blur::factory::get_mask_effect()
|
||||||
|
{
|
||||||
|
return mask_effect;
|
||||||
|
}
|
||||||
|
|
||||||
std::shared_ptr<gs::texture> filter::blur::factory::get_kernel(filter::blur::type type)
|
std::shared_ptr<gs::texture> filter::blur::factory::get_kernel(filter::blur::type type)
|
||||||
{
|
{
|
||||||
return kernels.at(type);
|
return kernels.at(type);
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include "gfx-source-texture.h"
|
||||||
#include "gs-effect.h"
|
#include "gs-effect.h"
|
||||||
#include "gs-helper.h"
|
#include "gs-helper.h"
|
||||||
#include "gs-texture.h"
|
#include "gs-texture.h"
|
||||||
|
@ -34,6 +35,12 @@ namespace filter {
|
||||||
Bilateral,
|
Bilateral,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum mask_type : int64_t {
|
||||||
|
Region,
|
||||||
|
Image,
|
||||||
|
Source,
|
||||||
|
};
|
||||||
|
|
||||||
class instance {
|
class instance {
|
||||||
obs_source_t* m_source;
|
obs_source_t* m_source;
|
||||||
gs_texrender_t* primary_rendertarget;
|
gs_texrender_t* primary_rendertarget;
|
||||||
|
@ -51,16 +58,31 @@ namespace filter {
|
||||||
double_t bilateral_sharpness;
|
double_t bilateral_sharpness;
|
||||||
|
|
||||||
// Regional
|
// Regional
|
||||||
struct Region {
|
struct {
|
||||||
bool enabled;
|
bool enabled;
|
||||||
float_t left;
|
mask_type type;
|
||||||
float_t top;
|
struct {
|
||||||
float_t right;
|
float_t left;
|
||||||
float_t bottom;
|
float_t top;
|
||||||
float_t feather;
|
float_t right;
|
||||||
float_t feather_shift;
|
float_t bottom;
|
||||||
bool invert;
|
float_t feather;
|
||||||
} region;
|
float_t feather_shift;
|
||||||
|
bool invert;
|
||||||
|
} region;
|
||||||
|
struct {
|
||||||
|
std::string path;
|
||||||
|
std::shared_ptr<gs::texture> texture;
|
||||||
|
} image;
|
||||||
|
struct {
|
||||||
|
std::string name;
|
||||||
|
obs_source_t* object;
|
||||||
|
std::shared_ptr<gfx::source_texture> source_texture;
|
||||||
|
std::shared_ptr<gs::texture> texture;
|
||||||
|
} source;
|
||||||
|
uint32_t color;
|
||||||
|
float_t multiplier;
|
||||||
|
} mask;
|
||||||
|
|
||||||
// advanced
|
// advanced
|
||||||
bool have_logged_error = false;
|
bool have_logged_error = false;
|
||||||
|
@ -69,6 +91,7 @@ namespace filter {
|
||||||
bool apply_shared_param(gs_texture_t* input, float texelX, float texelY);
|
bool apply_shared_param(gs_texture_t* input, float texelX, float texelY);
|
||||||
bool apply_bilateral_param();
|
bool apply_bilateral_param();
|
||||||
bool apply_gaussian_param();
|
bool apply_gaussian_param();
|
||||||
|
bool apply_mask_parameters(std::shared_ptr<gs::effect> effect, gs_texture_t * original_texture, gs_texture_t* blurred_texture);
|
||||||
|
|
||||||
static bool modified_properties(void* ptr, obs_properties_t* props, obs_property* prop,
|
static bool modified_properties(void* ptr, obs_properties_t* props, obs_property* prop,
|
||||||
obs_data_t* settings);
|
obs_data_t* settings);
|
||||||
|
@ -94,6 +117,7 @@ namespace filter {
|
||||||
obs_source_info source_info;
|
obs_source_info source_info;
|
||||||
std::list<instance*> sources;
|
std::list<instance*> sources;
|
||||||
std::shared_ptr<gs::effect> color_converter_effect;
|
std::shared_ptr<gs::effect> color_converter_effect;
|
||||||
|
std::shared_ptr<gs::effect> mask_effect;
|
||||||
|
|
||||||
std::map<filter::blur::type, std::shared_ptr<gs::effect>> effects;
|
std::map<filter::blur::type, std::shared_ptr<gs::effect>> effects;
|
||||||
std::map<filter::blur::type, std::shared_ptr<gs::texture>> kernels;
|
std::map<filter::blur::type, std::shared_ptr<gs::texture>> kernels;
|
||||||
|
@ -131,6 +155,8 @@ namespace filter {
|
||||||
|
|
||||||
std::shared_ptr<gs::effect> get_color_converter_effect();
|
std::shared_ptr<gs::effect> get_color_converter_effect();
|
||||||
|
|
||||||
|
std::shared_ptr<gs::effect> get_mask_effect();
|
||||||
|
|
||||||
std::shared_ptr<gs::texture> get_kernel(filter::blur::type type);
|
std::shared_ptr<gs::texture> get_kernel(filter::blur::type type);
|
||||||
|
|
||||||
public: // Singleton
|
public: // Singleton
|
||||||
|
|
Loading…
Reference in a new issue