Dynamic Pixelation Effect for OBS
Introduction
In live streaming and content creation, visual effects enhance the viewer experience. Whether you’re blurring sensitive info, creating a focus effect, or adding a creative touch, the right tools are key. Today, we introduce the dynamic pixelation effect for OBS with the EF-Blur Filter, a custom plugin that pixelates specific areas of your stream based on mouse input. This guide will help you implement the dynamic pixelation effect for OBS, making it follow the mouse cursor. By using the dynamic pixelation effect for OBS, you’ll add an engaging and unique element to your live stream.
What is the EF-Blur Filter?
The EF-Blur Filter is an OBS plugin that applies a pixelation effect to a selected area of your stream. What sets it apart is its ability to dynamically adjust the pixelation based on mouse input. You can click anywhere on your stream, and the filter will pixelate the area around the mouse cursor, creating a blur effect that you can use for various purposes, such as:
- Privacy Protection: Blur sensitive information like passwords, emails, or personal details.
- Focus Effects: Highlight specific areas of your stream while blurring the rest.
- Creative Effects: Add a unique visual style to your stream with dynamic pixelation.
How Does It Work?
The EF-Blur Filter works by capturing the mouse position and applying a pixelation shader to the area around the cursor. Here’s a breakdown of how it functions:
- Mouse Input Detection: The plugin continuously monitors the mouse position and detects when you click the left mouse button.
- Coordinate Mapping: The plugin maps the mouse coordinates to the source space, ensuring the pixelation effect applies accurately, even if the source resizes or repositions.
- Pixelation Shader: A custom shader applies the pixelation effect. It takes into account the pixelation size and block size, letting you customize the intensity and granularity of the blur.
- Dynamic Adjustment: The filter dynamically adjusts the pixelation effect based on the mouse position, ensuring the effect always applies to the correct area.
Key Features
- Dynamic Pixelation: The pixelation effect is applied dynamically based on mouse input, allowing for real-time adjustments.
- Customizable Settings: You can adjust the pixelation radius and block size to achieve the desired effect.
- Source Selection: The filter can be applied to any source in OBS, giving you flexibility in how you use it.
- Cross-Platform Compatibility: The plugin is designed to work on macOS, with support for other platforms planned for future updates.
Prerequisites
Before we begin, ensure you have:
- OBS Studio installed
- Basic knowledge of shaders (HLSL or GLSL)
- Experience with OBS’s filter system
Understanding the Effect
Our goal is to create a pixelation effect that dynamically changes based on the mouse position. The effect will:
- Apply pixelation to a specific area of the screen
- Follow the mouse cursor in real-time
- Adjust pixelation intensity dynamically
Implementing the Shader
OBS allows us to use custom shaders to modify scenes and filters. Below is an example of a GLSL shader for pixelation:
// Modified pixelate.effect shader
#define MOD(x, y) (x - y * floor(x / y))
uniform float4x4 ViewProj;
uniform texture2d image;
uniform float2 uv_size; // Size of the texture (width, height)
uniform float pixel_size; // Size of pixelation blocks
uniform float2 tess_origin; // Center of the pixelation effect
uniform float effect_radius; // Half-size of the square effect
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 coord = v_in.uv * uv_size; // Pixel coordinates
// Calculate absolute differences for square boundary check
float2 dist_vec = abs(coord - tess_origin);
float max_dist = max(dist_vec.x, dist_vec.y);
// Apply pixelation within square bounds
if (max_dist <= effect_radius) {
float2 coord_p = coord - tess_origin;
float2 coord_grid = (coord_p - MOD(coord_p, pixel_size) + sign(coord_p) * pixel_size / 2.0f);
float2 uv_prime = (coord_grid + tess_origin) / uv_size;
return image.Sample(textureSampler, uv_prime);
}
// Return original texture outside square bounds
return image.Sample(textureSampler, v_in.uv);
}
technique Draw
{ pass
{
vertex_shader = mainTransform(v_in);
pixel_shader = mainImage(v_in);
}
}
The Big Picture
The code is written in C and hooks into OBS’s plugin system using the obs-module.h framework. It’s designed as a video filter (OBS_SOURCE_TYPE_FILTER) that you can apply to any video source—like your webcam or game capture. The twist? It pixelates an area around wherever you click, with adjustable radius and block size settings. Think of it as a digital mosaic brush you wield with your mouse.
How It Works
At its core, the plugin uses a struct mouse_pixelate_data to track everything: the target source, pixelation settings, mouse position, and rendering tools like gs_texrender_t for graphics magic. Here’s the flow:
-
- Setup: When you load the filter (mouse_pixelate_create), it allocates memory, sets up a texture renderer, and reads initial settings like pixelation size and block size from OBS’s UI sliders.
- Mouse Tracking: The mouse_pixelate_tick function runs every frame, checking if you’ve clicked the left mouse button (via macOS’s CGEventSourceButtonState). When you do, it grabs your mouse’s screen position (get_mouse_position), adjusts for the OBS window’s location (get_obs_window_position), and maps it to the source’s coordinate space. If your click lands inside the source, it updates the blur_center—the spot where the pixelation will happen.
static void get_mouse_position(float *x, float *y) {
CGPoint mouse = CGEventGetLocation(CGEventCreate(NULL));
*x = (float)mouse.x;
*y = (float)mouse.y;
CFRelease(CGEventCreate(NULL));
blog(LOG_DEBUG, "Raw mouse position: (%.1f, %.1f)", *x, *y);
}
static bool get_obs_window_position(float *window_x, float *window_y) {
CGWindowListOption options = kCGWindowListOptionOnScreenOnly;
CFArrayRef window_list = CGWindowListCopyWindowInfo(options, kCGNullWindowID);
if (!window_list) {
blog(LOG_WARNING, "Failed to get window list");
*window_x = 0.0f;
*window_y = 0.0f;
return false;
}
bool found = false;
for (CFIndex i = 0; i < CFArrayGetCount(window_list); i++) {
CFDictionaryRef window_info = CFArrayGetValueAtIndex(window_list, i);
CFStringRef name = CFDictionaryGetValue(window_info, kCGWindowName);
if (name && CFStringFind(name, CFSTR("OBS"), kCFCompareCaseInsensitive).location != kCFNotFound) {
CFDictionaryRef bounds = CFDictionaryGetValue(window_info, kCGWindowBounds);
if (bounds) {
CGRect rect;
CGRectMakeWithDictionaryRepresentation(bounds, &rect);
*window_x = (float)rect.origin.x;
*window_y = (float)rect.origin.y;
found = true;
blog(LOG_INFO, "Found OBS window at: (%.1f, %.1f)", *window_x, *window_y);
break;
}
}
}
CFRelease(window_list);
if (!found) {
blog(LOG_WARNING, "Could not find OBS window; defaulting to (0, 0)");
*window_x = 0.0f;
*window_y = 0.0f;
}
return found;
}
- Rendering: The mouse_pixelate_render function does the heavy lifting. It renders the source to a texture, applies a custom shader (pixelate.effect), and draws the pixelated result. The shader uses the blur_center, pixel_size (block size), and effect_radius to create that chunky, retro pixel look.
- Settings: You can tweak the target source, radius (10–400 pixels), and block size (2–40 pixels) via the properties panel (mouse_pixelate_properties). These update in real-time thanks to mouse_pixelate_update.
Cool Bits and Challenges
One neat trick is how it handles macOS-specific mouse input using Carbon.h and ApplicationServices.h—sorry, Windows folks, this one’s macOS-only for now! The plugin also logs debug info (e.g., mouse coordinates) using blog(), which is super handy for troubleshooting.
A challenge? Coordinate mapping. Converting screen-space mouse clicks to source-space coordinates took some math—accounting for the OBS window offset, canvas scaling, and source dimensions. Get it wrong, and your pixelation ends up in Narnia.
How to Use the EF-Blur Filter
- Install the Plugin: Download the EF-Blur Filter plugin and place it in the OBS plugins directory.
- Add the Filter: In OBS, select the source you want to apply the filter to, then go to the “Filters” tab and click “Add Filter.” Choose the EF-Blur Filter from the list.
- Configure Settings: Adjust the pixelation radius and block size to achieve the desired effect. You can also select the target source if needed.
- Click to Blur: Once the filter is applied, simply click anywhere on the source to apply the pixelation effect.
Use Cases and Future Tweaks
Imagine streaming a coding session and blurring API keys on the fly, or pixelating your face during a prank stream. It’s versatile! For improvements, I’d port it to Windows (swapping Carbon for WinAPI), add a fade-out effect (tweaking blur_radius over time in video_tick), or make the shader path dynamic. Maybe even support multiple blur centers for multi-click chaos.
Final Thoughts
“EF-Blur” is a neat showcase of OBS’s plugin power—mixing real-time graphics, mouse input, and a custom UI. It’s not perfect (yet), but it’s a blast to build and use.
This version adds more code-specific details (e.g., shader params, coordinate math, error handling) while keeping it readable. Want more on the shader itself, a specific function, or something else? Just say the word! Stay tuned for more updates.
We hope you enjoy using the EF-Blur Filter as much as we enjoyed creating it. Happy streaming! 🎥✨