Skip to content

Commit

Permalink
Merge pull request #6 from ashmanix/develop
Browse files Browse the repository at this point in the history
Multiple Filters
  • Loading branch information
ashmanix committed Sep 24, 2023
2 parents 6be115e + ca3bdb7 commit 2d2fddf
Show file tree
Hide file tree
Showing 19 changed files with 754 additions and 272 deletions.
5 changes: 4 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ if(ENABLE_QT)
AUTORCC ON)
endif()

target_sources(${CMAKE_PROJECT_NAME} PRIVATE src/plugin-main.cpp src/blur-filter-widget.cpp)
target_sources(
${CMAKE_PROJECT_NAME}
PRIVATE src/plugin-main.cpp src/blur-filter-source.cpp src/filters/base-filter.hpp src/filters/simple-gaussian.cpp
src/filters/box-blur-filter.cpp src/filters/fast-gaussian.cpp)

set_target_properties_plugin(${CMAKE_PROJECT_NAME} PROPERTIES OUTPUT_NAME ${_name})
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ To use this plugin:
- Right click on an image or video source and select `Filters`
- On the popup window that appears select the `+` button to add a new filter
- Select the filter called `Ashmanix Blur Filter`
- Use the slider labelled `Blur Size` to set the level of blur.
- Use the dropdown to select between blur filter types.
- Use the dropdown to select between blur filter types
- Each filter will have its own properties you can set

## Build Instructions
To build this code use the included scripts that are taken from the [OBS Plugin Template](https://github.com/obsproject/obs-plugintemplate).
Expand Down
60 changes: 60 additions & 0 deletions data/fast_gaussian_blur.effect
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
uniform float4x4 ViewProj;
// This is a fast guassian blur shader taken from https://www.shadertoy.com/view/Xltfzj
// and modified to work in OBS It was created by existical and is based on a shader published
// here: https://xorshaders.weebly.com/tutorials/blur-shaders-5-part-2

uniform texture2d image;
uniform float targetWidth;
uniform float targetHeight;
uniform float blurSize; // BLUR SIZE (Radius)
uniform float blurQuality; // BLUR QUALITY (Default 4.0 - More is better but slower)
uniform float blurDirections; // BLUR DIRECTIONS (Default 16.0 - More is better but slower)
uniform float sigma = 30.0;

sampler_state clampSampler {
Filter = LINEAR;
AddressU = Clamp;
AddressV = Clamp;
};

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

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

float4 PShader(VertData v_in) : TARGET
{
float pi = 6.28318530718; // Pi*2

float2 resolution = float2(targetWidth, targetHeight);
float2 uv = v_in.uv;
float2 radius = blurSize/resolution;

float4 color = image.Sample(clampSampler, uv);

// Blur calculations
for( float d=0.0; d<pi; d+=pi/blurDirections)
{
for(float i=1.0/blurQuality; i<=1.0; i+=1.0/blurQuality)
{
color += image.Sample(clampSampler, uv+float2(cos(d),sin(d))*radius*i);
}
}

color /= blurQuality * blurDirections - 1;
return color;
}

technique Draw {
pass {
vertex_shader = VSDefault(v_in);
pixel_shader = PShader(v_in);
}
}
9 changes: 7 additions & 2 deletions data/locale/en-US.ini
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
BlurFilter="Ashmanix Blur Filter"
BlurSizeSelectTitle="Blur Size"
BurTypeDropdownSelectTitle="Blur Type"
BlurQualitySelectTitle="Blur Quality"
BlurDirectionsSelectTitle="Blur Directions"
BlurTypeDropdownSelectTitle="Blur Type"
BlurTypeSelectOptionBox="Box Blur"
BlurTypeSelectOptionGaussian="Gaussian Blur"
BlurTypeSelectOptionSimpleGaussian="Simple Gaussian Blur"
FilterOptionsGroupTitle="Options"
FilterOptionsGroupDescription="Filter options"
BlurTypeSelectOptionFastGaussian="Fast Gaussian Blur"
9 changes: 7 additions & 2 deletions data/locale/pt-BR.ini
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
BlurFilter="Filtro de Desfoque Ashmanix"
BlurSizeSelectTitle="Amplitude do Desfoque"
BurTypeDropdownSelectTitle="Tipo de Desfoque"
BlurQualitySelectTitle="Qualidade de desfoque"
BlurDirectionsSelectTitle="Desfocar direções"
BlurTypeDropdownSelectTitle="Tipo de Desfoque"
BlurTypeSelectOptionBox="Desfoque Caixa"
BlurTypeSelectOptionGaussian="Desfoque Gaussiano"
BlurTypeSelectOptionSimpleGaussian="Desfoque gaussiano simples"
FilterOptionsGroupTitle="Opções"
FilterOptionsGroupDescription="Opções de filtro"
BlurTypeSelectOptionFastGaussian="Desfoque Gaussiano Rápido"
File renamed without changes.
203 changes: 203 additions & 0 deletions src/blur-filter-source.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,203 @@
#include "blur-filter-source.hpp"

BlurFilterSource::BlurFilterSource() {}
BlurFilterSource::~BlurFilterSource() {}

void BlurFilterSource::RegisterSource()
{
source_info.id = "ashmanix_plugin_blur_filter";
source_info.type = OBS_SOURCE_TYPE_FILTER;
source_info.output_flags = OBS_SOURCE_VIDEO;
source_info.get_name = GetName;
source_info.create = CreateSource;
source_info.destroy = DestroySource;
source_info.video_render = RenderSource;
source_info.update = UpdateSource;
source_info.get_properties = GetProperties;

obs_register_source(&source_info);
}

const char *BlurFilterSource::GetName(void *unused)
{
UNUSED_PARAMETER(unused);
return obs_module_text("BlurFilter");
}

void BlurFilterSource::ChangeFilterSelection(struct filter_data *filterData,
obs_data_t *settings)
{
UNUSED_PARAMETER(settings);
long long filterIndex = filterData->selectedFilterIndex;

obs_enter_graphics();

if (filterData->effect) {
gs_effect_destroy(filterData->effect);
}
const char *effectPath =
filterData->filterArray[filterIndex]->GetShaderFilePath();
filterData->effect = gs_effect_create_from_file(effectPath, NULL);

obs_leave_graphics();

if (!filterData->effect) {
obs_log(LOG_ERROR, "Could not load effect file '%s'",
effectPath);
}

filterData->filterArray[filterIndex]->SetParameters(filterData->effect);
TogglePropertyGroupVisibility(filterData);
}

void *BlurFilterSource::CreateSource(obs_data_t *settings, obs_source_t *source)
{
struct filter_data *filterData =
(struct filter_data *)bzalloc(sizeof(struct filter_data));

filterData->filterArray.push_back(
std::unique_ptr<BaseFilter>(new SimpleGaussianFilter()));
filterData->filterArray.push_back(
std::unique_ptr<BaseFilter>(new BoxBlurFilter()));
filterData->filterArray.push_back(
std::unique_ptr<BaseFilter>(new FastGaussianFilter()));

filterData->context = source;
filterData->selectedFilterIndex = 0;

filterData->filterArray[filterData->selectedFilterIndex]->UpdateFilter(
settings);

ChangeFilterSelection(filterData, settings);
SetDefaultProperties(filterData, settings);

obs_source_update(source, settings);

return filterData;
}

void BlurFilterSource::DestroySource(void *data)
{
struct filter_data *filterData = (struct filter_data *)data;
if (filterData->effect) {
obs_enter_graphics();
gs_effect_destroy(filterData->effect);
obs_leave_graphics();
}
bfree(data);
}

void BlurFilterSource::UpdateSource(void *data, obs_data_t *settings)
{
// obs_log(LOG_INFO, "Updating Source!");
struct filter_data *filterData = (struct filter_data *)data;
long long blurTypeIndex = obs_data_get_int(settings, SETTING_BLUR_TYPE);
if (filterData && (filterData->selectedFilterIndex != blurTypeIndex)) {
filterData->selectedFilterIndex = blurTypeIndex;
ChangeFilterSelection(filterData, settings);
}
filterData->filterArray[blurTypeIndex]->UpdateFilter(settings);
}

bool BlurFilterSource::FilterSelectionChangeCallback(void *data,
obs_properties_t *props,
obs_property_t *list,
obs_data_t *settings)
{
UNUSED_PARAMETER(props);
long long selectedFilterIndex =
obs_data_get_int(settings, SETTING_BLUR_TYPE);

struct filter_data *filterData = (struct filter_data *)data;

if (selectedFilterIndex != filterData->selectedFilterIndex) {
filterData->selectedFilterIndex = selectedFilterIndex;

ChangeFilterSelection(filterData, settings);

obs_log(LOG_INFO, "Filter Changed To: %s",
obs_property_list_item_name(list, selectedFilterIndex));
}

return true;
}

obs_properties_t *BlurFilterSource::GetProperties(void *data)
{
struct filter_data *filterData = (struct filter_data *)data;

if (filterData) {
filterData->mainProperties = obs_properties_create();

obs_property_t *filterDropdownProperty =
obs_properties_add_list(
filterData->mainProperties, SETTING_BLUR_TYPE,
obs_module_text("BlurTypeDropdownSelectTitle"),
OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT);

for (size_t i = 0; i < filterData->filterArray.size(); i++) {

const char *name =
filterData->filterArray[i]->GetFilterName();
obs_property_list_add_int(filterDropdownProperty, name,
i);
}

obs_property_set_modified_callback2(
filterDropdownProperty, FilterSelectionChangeCallback,
filterData);

std::string filterStringName = "filter-";
for (size_t i = 0; i < filterData->filterArray.size(); i++) {
filterData->filterArray[i]->SetProperties(
filterData->mainProperties,
filterStringName.append(std::to_string(i)));

TogglePropertyGroupVisibility(filterData);
}
return filterData->mainProperties;
}

return nullptr;
}

void BlurFilterSource::SetDefaultProperties(filter_data *filterData,
obs_data_t *settings)
{
for (size_t i = 0; i < filterData->filterArray.size(); i++) {
filterData->filterArray[i]->SetPropertyDefaults(settings);
}
}

void BlurFilterSource::RenderSource(void *data, gs_effect_t *effect)
{
struct filter_data *filterData = (struct filter_data *)data;
long long filterIndex = filterData->selectedFilterIndex;
obs_source_t *context = filterData->context;

if (!obs_source_process_filter_begin(filterData->context, GS_RGBA,
OBS_ALLOW_DIRECT_RENDERING))
return;

filterData->filterArray[filterIndex]->Render(context);

if (!filterData->effect) {
obs_source_process_filter_end(filterData->context, effect, 0,
0);
} else {
obs_source_process_filter_end(filterData->context,
filterData->effect, 0, 0);
}
}

void BlurFilterSource::TogglePropertyGroupVisibility(filter_data *data)
{
for (size_t i = 0; i < data->filterArray.size(); i++) {
if (data->selectedFilterIndex >= 0 &&
i != (size_t)data->selectedFilterIndex) {
data->filterArray[i]->HidePropertiesGroup();
} else {
data->filterArray[i]->ShowPropertiesGroup();
}
}
}
56 changes: 56 additions & 0 deletions src/blur-filter-source.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
#ifndef BLURFILTERSOURCE_H
#define BLURFILTERSOURCE_H

#include <obs-module.h>
#include <plugin-support.h>
#include <string>
#include <vector>
#include <memory>
#include "src/filters/base-filter.hpp"
#include "src/filters/simple-gaussian.hpp"
#include "src/filters/box-blur-filter.hpp"
#include "src/filters/fast-gaussian.hpp"

#define SETTING_BLUR_SIZE "blur_size"
#define SETTING_BLUR_TYPE "blur_type"

class BlurFilterSource {
private:
struct filter_data {
obs_source_t *context;
gs_effect_t *effect;

char *selectedFileName;
long long selectedFilterIndex;
std::vector<std::unique_ptr<BaseFilter>> filterArray;

obs_properties_t *mainProperties;
obs_properties_t *filterProperties;
obs_property_t *filterPropertiesGroup;
};

obs_source_info source_info = {};

static const char *GetName(void *unused);
static void *CreateSource(obs_data_t *settings, obs_source_t *source);
static void DestroySource(void *data);
static void UpdateSource(void *data, obs_data_t *settings);
static obs_properties_t *GetProperties(void *data);
static void SetDefaultProperties(filter_data *filterData,
obs_data_t *settings);
static void RenderSource(void *data, gs_effect_t *effect);
static void ChangeFilterSelection(struct filter_data *filter,
obs_data_t *settings);
static bool FilterSelectionChangeCallback(void *data,
obs_properties_t *props,
obs_property_t *list,
obs_data_t *settings);
static void TogglePropertyGroupVisibility(filter_data *data);

public:
BlurFilterSource();
~BlurFilterSource();
void RegisterSource();
};

#endif // BLURFILTERSOURCE_H
Loading

0 comments on commit 2d2fddf

Please sign in to comment.