Skip to content

Commit

Permalink
Feature/effect masking (#18)
Browse files Browse the repository at this point in the history
* Adds crop mask, with optional rounded corners.
* Adds source masking, with options to mask by alpha, grayscale, luminosity, or manual
* Refactor param data into data struct.  Change mask functions to use new struct.
* Adds defaults callback for filter settings, and sets up some sane defaults.
* Switches box blur to using data param pointers.
* Switches gaussian blur to using data param pointers.
* Switches pixelate blur to using data param pointers.
* Adds plugin version info to filter parameters panel.
* Adds circle masking.
* Adds Image masking.
* Updated readme file with masking information
  • Loading branch information
FiniteSingularity committed Aug 31, 2023
1 parent 98a256d commit 757e83d
Show file tree
Hide file tree
Showing 20 changed files with 1,792 additions and 358 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ else()
cmake_minimum_required(VERSION 3.18)
endif()

project(obs-composite-blur VERSION 0.0.3)
project(obs-composite-blur VERSION 0.0.7)
set(PROJECT_FULL_NAME "OBS Composite Blur")

# Set new UUIDs when you start to create a new plugin.
Expand Down
18 changes: 18 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,21 @@ Zoom blur is applied away from a center zoom point, and increases the further fr

### Tilt-Shift
Tilt-Shift blur defines an in-focus plane, specified by a location in the frame, and a thickness. All pixels outside of the in-focus plane have their blur value increased the further away from the plane they are. The resulting image gives a distorted sense of scale, making large objects look like mineature models. When applied to video scenes like a city street, the effect can be significant. Inputs are blur radius, focus plane angle, focus plane location, and focus plane thickness.

## Effect Masking
OBS Composite Blur offers a variety of ways to mask where and how blur is applied to your source. For all mask options, the mask can also be inverted by checking the "Invert Mask" box. The following options are available.

### Crop
Specify the percentage distance in from the top, bottom, left, and right edges of your source that you want masked. Additionally, the crop mask allows you to specify a corner radius for nice, smooth rounded corners.

### Source
Use another OBS source or scene as a mask for your blur. Simply select the source or scene you want to use, and then specify if you want to use the source's alpha channel, grayscale value, luminosity, or a custom combination of the red, green, blue, and alpha channels to mask the blur effect. You can also multiply the resulting mask by a value. The multiply value comes in handy if you have a translucent source, but want everything behind the translucent source to be fully blurred.

### Image
All of the same options as [Source](#source), but allows you to select an image file rather than a source.

### Rectangle
Is the same as the [Crop](#crop) option, but instead of specifying the edges, you specify the center of the rectangle, the rectangle width, and rectangle height. This is easier to use with plugins like Move Transition if you want to animate the movement or size of the rectangular masked blur.

### Circle
Similar to the [Rectangle](#rectangle) option, but lets you specify the center of a circle and its radius. Some nice sweep effects can be made by using a very large circle, and moving it from off the source (less than 0 or greater than 100 for the center coordinates) over the source.
160 changes: 80 additions & 80 deletions buildspec.json
Original file line number Diff line number Diff line change
@@ -1,83 +1,83 @@
{
"dependencies": {
"obs-studio": {
"version": "28.0.0-beta1",
"repository": "https://github.com/obsproject/obs-studio.git",
"branch": "master",
"hash": "43a49dca47344a5170159ef99b86b97f90d4e4ad"
},
"prebuilt": {
"version": "2022-08-02",
"baseUrl": "https://github.com/obsproject/obs-deps/releases/download",
"label": "Pre-built obs-deps",
"hashes": {
"macos-x86_64": "7637e52305e6fc53014b5aabd583f1a4490b1d97450420e977cae9a336a29525",
"macos-arm64": "755e0fa69b17a3ae444e1befa9d91d77e3cafe628fbd1c6333686091826595cd",
"macos-universal": "de057e73e6fe0825664c258ca2dd6798c41ae580bf4d896e1647676a4941934a",
"windows-x64": "2192d8ce780c4281b807cd457994963669e5202659ecd92f19b54c3e7d0c1915",
"windows-x86": "9f8582ab5891b000869d6484ea591add9fbac9f1c91b56c7b85fdfd56a261c1b"
}
},
"qt5": {
"version": "2022-08-02",
"baseUrl": "https://github.com/obsproject/obs-deps/releases/download",
"label": "Pre-built Qt5",
"hashes": {
"macos-x86_64": "3d0381a52b0e4d49967936c4357f79ac711f43564329304a6db5c90edadd2697",
"macos-arm64": "f4b32548c0530f121956bf0a9a70c36ecbbfca81073d39c396a1759baf2a05c3",
"macos-universal": "9a6cf3b9a6c9efee6ba10df649202e8075e99f3c54ae88dc9a36dbc9d7471c1e",
"windows-x64": "6488a33a474f750d5a4a268a5e20c78bb40799d99136a1b7ce3365a843cb2fd7",
"windows-x86": "a916e09b0a874036801deab2c8a7ec14fdf5d268aa5511eac5bf40727e0c4e33"
},
"pdb-hashes": {
"windows-x64": "e0e5070143fcad9311a68ce5685d8ba8f34f581ed6942b7a92d360f94ca1ba11",
"windows-x86": "36642d1052aa461964f46c17610477b0d9b9defbe2d745ccaacb85f805c1bec2"
}
},
"qt6": {
"version": "2022-08-02",
"baseUrl": "https://github.com/obsproject/obs-deps/releases/download",
"label": "Pre-built Qt6",
"hashes": {
"macos-x86_64": "a83f72a11023b03b6cb2dc365f0a66ad9df31163bbb4fe2df32d601856a9fad3",
"macos-arm64": "2f30af90c049670a5660656adbb440668aa1b0567f75a5f29e1def9108928403",
"macos-universal": "252e6684f43ab9c6f262c73af739e2296ce391b998da2c4ee04c254aaa07db18",
"windows-x64": "e5509b54196a3f935250cc4b9c54160c8e588fd0f92bc078a2a64f9d9e2e4e93",
"windows-x86": "24fc03bef153a0e027c1479e42eb08097a4ea1d70a4710825be0783d0626cb0d"
},
"pdb-hashes": {
"windows-x64": "60e5b1d2bc4d7c431bc05f14e3b1e85e088788c372fa85f58717cd6c49555a46",
"windows-x86": "f34d1a89fc85d92913bd6c7f75ec5c28471d74db708c98161100bc8b75f8fc63"
}
}
"dependencies": {
"obs-studio": {
"version": "28.0.0-beta1",
"repository": "https://github.com/obsproject/obs-studio.git",
"branch": "master",
"hash": "43a49dca47344a5170159ef99b86b97f90d4e4ad"
},
"platformConfig": {
"macos-x86_64": {
"qtVersion": 6,
"deploymentTarget": "10.15"
},
"macos-arm64": {
"qtVersion": 6,
"deploymentTarget": "11.0"
},
"macos-universal": {
"qtVersion": 6,
"deploymentTarget": "10.15"
},
"windows-x64": {
"qtVersion": 6,
"visualStudio": "Visual Studio 17 2022",
"platformSDK": "10.0.20348.0"
},
"windows-x86": {
"qtVersion": 6,
"visualStudio": "Visual Studio 17 2022",
"platformSDK": "10.0.20348.0"
},
"linux-x86_64": {
"qtVersion": 6
}
"prebuilt": {
"version": "2022-08-02",
"baseUrl": "https://github.com/obsproject/obs-deps/releases/download",
"label": "Pre-built obs-deps",
"hashes": {
"macos-x86_64": "7637e52305e6fc53014b5aabd583f1a4490b1d97450420e977cae9a336a29525",
"macos-arm64": "755e0fa69b17a3ae444e1befa9d91d77e3cafe628fbd1c6333686091826595cd",
"macos-universal": "de057e73e6fe0825664c258ca2dd6798c41ae580bf4d896e1647676a4941934a",
"windows-x64": "2192d8ce780c4281b807cd457994963669e5202659ecd92f19b54c3e7d0c1915",
"windows-x86": "9f8582ab5891b000869d6484ea591add9fbac9f1c91b56c7b85fdfd56a261c1b"
}
},
"name": "obs-composite-blur",
"version": "0.0.3"
}
"qt5": {
"version": "2022-08-02",
"baseUrl": "https://github.com/obsproject/obs-deps/releases/download",
"label": "Pre-built Qt5",
"hashes": {
"macos-x86_64": "3d0381a52b0e4d49967936c4357f79ac711f43564329304a6db5c90edadd2697",
"macos-arm64": "f4b32548c0530f121956bf0a9a70c36ecbbfca81073d39c396a1759baf2a05c3",
"macos-universal": "9a6cf3b9a6c9efee6ba10df649202e8075e99f3c54ae88dc9a36dbc9d7471c1e",
"windows-x64": "6488a33a474f750d5a4a268a5e20c78bb40799d99136a1b7ce3365a843cb2fd7",
"windows-x86": "a916e09b0a874036801deab2c8a7ec14fdf5d268aa5511eac5bf40727e0c4e33"
},
"pdb-hashes": {
"windows-x64": "e0e5070143fcad9311a68ce5685d8ba8f34f581ed6942b7a92d360f94ca1ba11",
"windows-x86": "36642d1052aa461964f46c17610477b0d9b9defbe2d745ccaacb85f805c1bec2"
}
},
"qt6": {
"version": "2022-08-02",
"baseUrl": "https://github.com/obsproject/obs-deps/releases/download",
"label": "Pre-built Qt6",
"hashes": {
"macos-x86_64": "a83f72a11023b03b6cb2dc365f0a66ad9df31163bbb4fe2df32d601856a9fad3",
"macos-arm64": "2f30af90c049670a5660656adbb440668aa1b0567f75a5f29e1def9108928403",
"macos-universal": "252e6684f43ab9c6f262c73af739e2296ce391b998da2c4ee04c254aaa07db18",
"windows-x64": "e5509b54196a3f935250cc4b9c54160c8e588fd0f92bc078a2a64f9d9e2e4e93",
"windows-x86": "24fc03bef153a0e027c1479e42eb08097a4ea1d70a4710825be0783d0626cb0d"
},
"pdb-hashes": {
"windows-x64": "60e5b1d2bc4d7c431bc05f14e3b1e85e088788c372fa85f58717cd6c49555a46",
"windows-x86": "f34d1a89fc85d92913bd6c7f75ec5c28471d74db708c98161100bc8b75f8fc63"
}
}
},
"platformConfig": {
"macos-x86_64": {
"qtVersion": 6,
"deploymentTarget": "10.15"
},
"macos-arm64": {
"qtVersion": 6,
"deploymentTarget": "11.0"
},
"macos-universal": {
"qtVersion": 6,
"deploymentTarget": "10.15"
},
"windows-x64": {
"qtVersion": 6,
"visualStudio": "Visual Studio 17 2022",
"platformSDK": "10.0.20348.0"
},
"windows-x86": {
"qtVersion": 6,
"visualStudio": "Visual Studio 17 2022",
"platformSDK": "10.0.20348.0"
},
"linux-x86_64": {
"qtVersion": 6
}
},
"name": "obs-composite-blur",
"version": "0.0.7"
}
40 changes: 39 additions & 1 deletion data/locale/en-US.ini
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
CompositeBlurFilter="Composite Blur"
CompositeBlurFilter.Channel.Alpha="Alpha"
CompositeBlurFilter.Channel.Red="Red"
CompositeBlurFilter.Channel.Green="Green"
CompositeBlurFilter.Channel.Blue="Blue"
CompositeBlurFilter.BlurAlgorithm="Blur Algorithm"
CompositeBlurFilter.BlurType="Blur Type"
CompositeBlurFilter.Radius="Blur radius"
Expand Down Expand Up @@ -28,4 +32,38 @@ CompositeBlurFilter.Pixelate.Hexagonal="Hexagonal"
CompositeBlurFilter.Pixelate.Triakis="Triakis"
CompositeBlurFilter.Pixelate.Circle="Circle"
CompositeBlurFilter.Pixelate.Triangle="Triangle"
CompositeBlurFilter.DualKawase.Passes="Blur Radius"
CompositeBlurFilter.DualKawase.Passes="Blur Radius"
CompositeBlurFilter.EffectMask="Effect Mask"
CompositeBlurFilter.EffectMask.CropParameters="Crop Mask Parameters"
CompositeBlurFilter.EffectMask.None="None"
CompositeBlurFilter.EffectMask.Crop="Crop"
CompositeBlurFilter.EffectMask.Rectangle="Rectangle"
CompositeBlurFilter.EffectMask.Circle="Circle"
CompositeBlurFilter.EffectMask.Source="Source"
CompositeBlurFilter.EffectMask.Image="Image"
CompositeBlurFilter.EffectMask.Crop.Top="Top (%)"
CompositeBlurFilter.EffectMask.Crop.Bottom="Bottom (%)"
CompositeBlurFilter.EffectMask.Crop.Left="Left (%)"
CompositeBlurFilter.EffectMask.Crop.Right="Right (%)"
CompositeBlurFilter.EffectMask.CornerRadius="Corner Radius (%)"
CompositeBlurFilter.EffectMask.Invert="Invert Mask?"
CompositeBlurFilter.EffectMask.SourceParameters="Source Mask Parameters"
CompositeBlurFilter.EffectMask.ImageParameters="Image Mask Parameters"
CompositeBlurFilter.EffectMask.Source.Source="Source"
CompositeBlurFilter.EffectMask.Source.File="Image File"
CompositeBlurFilter.EffectMask.Source.Filter="Mask Using"
CompositeBlurFilter.EffectMask.Source.Alpha="Alpha Channel"
CompositeBlurFilter.EffectMask.Source.Grayscale="Grayscale Value"
CompositeBlurFilter.EffectMask.Source.Luminosity="Luminosity"
CompositeBlurFilter.EffectMask.Source.Sliders="Manual RGBA Sliders"
CompositeBlurFilter.EffectMask.Source.Multiplier="Multiplier"
CompositeBlurFilter.EffectMask.Circle.CenterX="Center X (%)"
CompositeBlurFilter.EffectMask.Circle.CenterY="Center Y (%)"
CompositeBlurFilter.EffectMask.Circle.Radius="Radius (%)"
CompositeBlurFilter.EffectMask.CircleParameters="Circle Mask Parameters"
CompositeBlurFilter.EffectMask.Rect.CenterX="Center X (%)"
CompositeBlurFilter.EffectMask.Rect.CenterY="Center Y (%)"
CompositeBlurFilter.EffectMask.Rect.Width="Width (%)"
CompositeBlurFilter.EffectMask.Rect.Height="Height (%)"
CompositeBlurFilter.EffectMask.Rect.CornerRadius="Corner Radius (%)"
CompositeBlurFilter.EffectMask.RectParameters="Rectangle Mask Parameters"
47 changes: 47 additions & 0 deletions data/shaders/effect_mask_circle.effect
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
uniform float4x4 ViewProj;
uniform texture2d image;
uniform texture2d filtered_image;

uniform float circle_radius;
uniform float2 center;
uniform float2 uv_scale;
uniform bool inv = false;

sampler_state textureSampler{
Filter = Linear;
AddressU = Clamp;
AddressV = Clamp;
MinLOD = 0;
MaxLOD = 0;
};

struct VertData {
float4 pos : POSITION;
float2 uv : TEXCOORD0;
};

VertData mainTransform(VertData v_in)
{
v_in.pos = mul(float4(v_in.pos.xyz, 1.0), ViewProj);
return v_in;
}

float4 mainImage(VertData v_in) : TARGET
{
float2 uv_prime = v_in.uv * uv_scale;
float2 center_prime = center * uv_scale;
float dist = distance(uv_prime, center_prime);
if (dist > circle_radius) {
return !inv ? image.Sample(textureSampler, v_in.uv) : filtered_image.Sample(textureSampler, v_in.uv);
}
return inv ? image.Sample(textureSampler, v_in.uv) : filtered_image.Sample(textureSampler, v_in.uv);
}

technique Draw
{
pass
{
vertex_shader = mainTransform(v_in);
pixel_shader = mainImage(v_in);
}
}
87 changes: 87 additions & 0 deletions data/shaders/effect_mask_crop.effect
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
uniform float4x4 ViewProj;
uniform texture2d image;
uniform texture2d filtered_image;

uniform float2 scale;
uniform float2 offset;
uniform float2 box_aspect_ratio;
uniform float corner_radius;
uniform bool inv = false;

sampler_state textureSampler{
Filter = Linear;
AddressU = Clamp;
AddressV = Clamp;
MinLOD = 0;
MaxLOD = 0;
};

struct VertData {
float4 pos : POSITION;
float2 uv : TEXCOORD0;
};

VertData mainTransform(VertData v_in)
{
v_in.pos = mul(float4(v_in.pos.xyz, 1.0), ViewProj);
return v_in;
}

float4 mainImage(VertData v_in) : TARGET
{
float2 transform_coord = (v_in.uv - offset) * scale;
if(transform_coord.x < 0.0f || transform_coord.y < 0.0f || transform_coord.x > 1.0f || transform_coord.y > 1.0f) {
// Outside
return inv ? filtered_image.Sample(textureSampler, v_in.uv) : image.Sample(textureSampler, v_in.uv);
}
// Inside
// 1. Scale to 1:1 ratio, shorten long side
float2 inner_coord = transform_coord * box_aspect_ratio;
if(
inner_coord.x > corner_radius && inner_coord.y > corner_radius &&
inner_coord.x < (box_aspect_ratio.x - corner_radius) && inner_coord.y < (box_aspect_ratio.y - corner_radius)
) {
return inv ? image.Sample(textureSampler, v_in.uv) : filtered_image.Sample(textureSampler, v_in.uv);
}
if(inner_coord.x < corner_radius && inner_coord.y < corner_radius) {
// top left
if (distance(inner_coord, float2(corner_radius, corner_radius)) > corner_radius) {
return inv ? filtered_image.Sample(textureSampler, v_in.uv) : image.Sample(textureSampler, v_in.uv);
}
} else if(inner_coord.x < corner_radius && inner_coord.y > (box_aspect_ratio.y - corner_radius)) {
// bot left
if (distance(inner_coord, float2(corner_radius, box_aspect_ratio.y - corner_radius)) > corner_radius) {
return inv ? filtered_image.Sample(textureSampler, v_in.uv) : image.Sample(textureSampler, v_in.uv);
}
} else if(inner_coord.x > (box_aspect_ratio.x - corner_radius) && inner_coord.y < corner_radius) {
// top right
if (distance(inner_coord, float2(box_aspect_ratio.x - corner_radius, corner_radius)) > corner_radius) {
return inv ? filtered_image.Sample(textureSampler, v_in.uv) : image.Sample(textureSampler, v_in.uv);
}
} else if(inner_coord.x > (box_aspect_ratio.x - corner_radius) && inner_coord.y > (box_aspect_ratio.y - corner_radius)) {
// bot right
if (distance(inner_coord, float2(box_aspect_ratio.x - corner_radius, box_aspect_ratio.y - corner_radius)) > corner_radius) {
return inv ? filtered_image.Sample(textureSampler, v_in.uv) : image.Sample(textureSampler, v_in.uv);
}
}

return inv ? image.Sample(textureSampler, v_in.uv) : filtered_image.Sample(textureSampler, v_in.uv);

// else if(
// transform_coord.x > corner_radius && transform_coord.x < 1.0f-corner_radius &&
// transform_coord.y > corner_radius && transform_coord.y < 1.0f-corner_radius
// ) {
// return inv ? image.Sample(textureSampler, v_in.uv) : filtered_image.Sample(textureSampler, v_in.uv);
// }
// return float4(1.0, 0.0, 1.0, 1.0);

}

technique Draw
{
pass
{
vertex_shader = mainTransform(v_in);
pixel_shader = mainImage(v_in);
}
}
Loading

0 comments on commit 757e83d

Please sign in to comment.