transition: Add initial version of Shader filter
These allow you to apply any kind of filtering to a any source, using just standard HLSL. Just like transitions, one extra parameter is set called 'InputA'. Fixes #95
This commit is contained in:
parent
ead355beea
commit
43b5d309eb
|
@ -575,8 +575,8 @@ if(${PropertyPrefix}ENABLE_FILTER_SHADER)
|
|||
"data/examples/shaders/filter/example_displace_by_texture.effect"
|
||||
)
|
||||
list(APPEND PROJECT_PRIVATE_SOURCE
|
||||
# "source/filters/filter-shader.hpp"
|
||||
# "source/filters/filter-shader.cpp"
|
||||
"source/filters/filter-shader.hpp"
|
||||
"source/filters/filter-shader.cpp"
|
||||
)
|
||||
list(APPEND PROJECT_DEFINITIONS
|
||||
ENABLE_FILTER_SHADER
|
||||
|
|
|
@ -19,225 +19,34 @@
|
|||
|
||||
#include "filter-shader.hpp"
|
||||
#include <stdexcept>
|
||||
#include "obs/gs/gs-helper.hpp"
|
||||
#include "strings.hpp"
|
||||
#include "utility.hpp"
|
||||
|
||||
#define ST "Filter.Shader"
|
||||
#define ST_SCALE_LOCKED "Filter.Shader.Scale.Locked"
|
||||
#define ST_SCALE_SCALE "Filter.Shader.Scale.Scale"
|
||||
#define ST_SCALE_WIDTH "Filter.Shader.Scale.Width"
|
||||
#define ST_SCALE_HEIGHT "Filter.Shader.Scale.Height"
|
||||
|
||||
static std::shared_ptr<filter::shader::shader_factory> factory_instance = nullptr;
|
||||
|
||||
void filter::shader::shader_factory::initialize()
|
||||
{
|
||||
factory_instance = std::make_shared<filter::shader::shader_factory>();
|
||||
}
|
||||
|
||||
void filter::shader::shader_factory::finalize()
|
||||
{
|
||||
factory_instance.reset();
|
||||
}
|
||||
|
||||
std::shared_ptr<filter::shader::shader_factory> filter::shader::shader_factory::get()
|
||||
{
|
||||
return factory_instance;
|
||||
}
|
||||
|
||||
static void get_defaults(obs_data_t* data)
|
||||
{
|
||||
obs_data_set_default_string(data, S_SHADER_FILE, obs_module_file("shaders/filter/example.effect"));
|
||||
obs_data_set_default_string(data, S_SHADER_TECHNIQUE, "Draw");
|
||||
obs_data_set_default_bool(data, ST_SCALE_LOCKED, true);
|
||||
obs_data_set_default_double(data, ST_SCALE_SCALE, 1.0);
|
||||
obs_data_set_default_double(data, ST_SCALE_WIDTH, 1.0);
|
||||
obs_data_set_default_double(data, ST_SCALE_HEIGHT, 1.0);
|
||||
}
|
||||
|
||||
filter::shader::shader_factory::shader_factory()
|
||||
{
|
||||
memset(&_source_info, 0, sizeof(obs_source_info));
|
||||
_source_info.id = "obs-stream-effects-filter-shader";
|
||||
_source_info.type = OBS_SOURCE_TYPE_FILTER;
|
||||
_source_info.output_flags = OBS_SOURCE_VIDEO;
|
||||
_source_info.get_name = [](void*) { return D_TRANSLATE(ST); };
|
||||
_source_info.get_defaults = get_defaults;
|
||||
|
||||
_source_info.create = [](obs_data_t* data, obs_source_t* self) {
|
||||
try {
|
||||
return static_cast<void*>(new filter::shader::shader_instance(data, self));
|
||||
} catch (const std::exception& ex) {
|
||||
P_LOG_ERROR("<filter-shader> Failed to create source, error: %s", ex.what());
|
||||
} catch (...) {
|
||||
P_LOG_ERROR("<filter-shader> Failed to create source.");
|
||||
}
|
||||
return static_cast<void*>(nullptr);
|
||||
};
|
||||
_source_info.destroy = [](void* ptr) {
|
||||
try {
|
||||
delete reinterpret_cast<filter::shader::shader_instance*>(ptr);
|
||||
} catch (const std::exception& ex) {
|
||||
P_LOG_ERROR("<filter-shader> Failed to delete source, error: %s", ex.what());
|
||||
} catch (...) {
|
||||
P_LOG_ERROR("<filter-shader> Failed to delete source.");
|
||||
}
|
||||
};
|
||||
_source_info.get_properties = [](void* ptr) {
|
||||
obs_properties_t* pr = obs_properties_create();
|
||||
try {
|
||||
if (ptr)
|
||||
reinterpret_cast<filter::shader::shader_instance*>(ptr)->properties(pr);
|
||||
} catch (const std::exception& ex) {
|
||||
P_LOG_ERROR("<filter-shader> Failed to retrieve options, error: %s", ex.what());
|
||||
} catch (...) {
|
||||
P_LOG_ERROR("<filter-shader> Failed to retrieve options.");
|
||||
}
|
||||
return pr;
|
||||
};
|
||||
_source_info.get_width = [](void* ptr) {
|
||||
try {
|
||||
if (ptr)
|
||||
return reinterpret_cast<filter::shader::shader_instance*>(ptr)->width();
|
||||
} catch (const std::exception& ex) {
|
||||
P_LOG_ERROR("<filter-shader> Failed to retrieve width, error: %s", ex.what());
|
||||
} catch (...) {
|
||||
P_LOG_ERROR("<filter-shader> Failed to retrieve width.");
|
||||
}
|
||||
return uint32_t(0);
|
||||
};
|
||||
_source_info.get_height = [](void* ptr) {
|
||||
try {
|
||||
if (ptr)
|
||||
return reinterpret_cast<filter::shader::shader_instance*>(ptr)->height();
|
||||
} catch (const std::exception& ex) {
|
||||
P_LOG_ERROR("<filter-shader> Failed to retrieve height, error: %s", ex.what());
|
||||
} catch (...) {
|
||||
P_LOG_ERROR("<filter-shader> Failed to retrieve height.");
|
||||
}
|
||||
return uint32_t(0);
|
||||
};
|
||||
_source_info.load = [](void* ptr, obs_data_t* data) {
|
||||
try {
|
||||
if (ptr)
|
||||
reinterpret_cast<filter::shader::shader_instance*>(ptr)->load(data);
|
||||
} catch (const std::exception& ex) {
|
||||
P_LOG_ERROR("<filter-shader> Failed to load, error: %s", ex.what());
|
||||
} catch (...) {
|
||||
P_LOG_ERROR("<filter-shader> Failed to load.");
|
||||
}
|
||||
};
|
||||
_source_info.update = [](void* ptr, obs_data_t* data) {
|
||||
try {
|
||||
if (ptr)
|
||||
reinterpret_cast<filter::shader::shader_instance*>(ptr)->update(data);
|
||||
} catch (const std::exception& ex) {
|
||||
P_LOG_ERROR("<filter-shader> Failed to update, error: %s", ex.what());
|
||||
} catch (...) {
|
||||
P_LOG_ERROR("<filter-shader> Failed to update.");
|
||||
}
|
||||
};
|
||||
_source_info.activate = [](void* ptr) {
|
||||
try {
|
||||
if (ptr)
|
||||
reinterpret_cast<filter::shader::shader_instance*>(ptr)->activate();
|
||||
} catch (const std::exception& ex) {
|
||||
P_LOG_ERROR("<filter-shader> Failed to activate, error: %s", ex.what());
|
||||
} catch (...) {
|
||||
P_LOG_ERROR("<filter-shader> Failed to activate.");
|
||||
}
|
||||
};
|
||||
_source_info.deactivate = [](void* ptr) {
|
||||
try {
|
||||
if (ptr)
|
||||
reinterpret_cast<filter::shader::shader_instance*>(ptr)->deactivate();
|
||||
} catch (const std::exception& ex) {
|
||||
P_LOG_ERROR("<filter-shader> Failed to deactivate, error: %s", ex.what());
|
||||
} catch (...) {
|
||||
P_LOG_ERROR("<filter-shader> Failed to deactivate.");
|
||||
}
|
||||
};
|
||||
_source_info.video_tick = [](void* ptr, float_t time) {
|
||||
try {
|
||||
if (ptr)
|
||||
reinterpret_cast<filter::shader::shader_instance*>(ptr)->video_tick(time);
|
||||
} catch (const std::exception& ex) {
|
||||
P_LOG_ERROR("<filter-shader> Failed to tick, error: %s", ex.what());
|
||||
} catch (...) {
|
||||
P_LOG_ERROR("<filter-shader> Failed to tick.");
|
||||
}
|
||||
};
|
||||
_source_info.video_render = [](void* ptr, gs_effect_t* effect) {
|
||||
try {
|
||||
if (ptr)
|
||||
reinterpret_cast<filter::shader::shader_instance*>(ptr)->video_render(effect);
|
||||
} catch (const std::exception& ex) {
|
||||
P_LOG_ERROR("<filter-shader> Failed to render, error: %s", ex.what());
|
||||
} catch (...) {
|
||||
P_LOG_ERROR("<filter-shader> Failed to render.");
|
||||
}
|
||||
};
|
||||
_source_info.enum_active_sources = [](void* ptr, obs_source_enum_proc_t enum_callback, void* param) {
|
||||
try {
|
||||
if (ptr)
|
||||
reinterpret_cast<filter::shader::shader_instance*>(ptr)->enum_active_sources(enum_callback, param);
|
||||
} catch (const std::exception& ex) {
|
||||
P_LOG_ERROR("<filter-shader> Failed to enumerate sources, error: %s", ex.what());
|
||||
} catch (...) {
|
||||
P_LOG_ERROR("<filter-shader> Failed to enumerate sources.");
|
||||
}
|
||||
};
|
||||
|
||||
obs_register_source(&_source_info);
|
||||
}
|
||||
|
||||
filter::shader::shader_factory::~shader_factory() {}
|
||||
|
||||
filter::shader::shader_instance::shader_instance(obs_data_t* data, obs_source_t* self)
|
||||
: _self(self), _active(true), _width(0), _height(0)
|
||||
: obs::source_instance(data, self)
|
||||
{
|
||||
_fx = std::make_shared<gfx::effect_source::effect_source>(self);
|
||||
_fx->set_valid_property_cb(std::bind(&filter::shader::shader_instance::valid_param, this, std::placeholders::_1));
|
||||
_fx->set_override_cb(std::bind(&filter::shader::shader_instance::override_param, this, std::placeholders::_1));
|
||||
|
||||
_rt = std::make_shared<gs::rendertarget>(GS_RGBA, GS_ZS_NONE);
|
||||
_rt2 = std::make_shared<gs::rendertarget>(GS_RGBA, GS_ZS_NONE);
|
||||
|
||||
_fx = std::make_shared<gfx::shader::shader>(self, gfx::shader::shader_mode::Transition);
|
||||
_rt = std::make_shared<gs::rendertarget>(GS_RGBA, GS_ZS_NONE);
|
||||
update(data);
|
||||
}
|
||||
|
||||
filter::shader::shader_instance::~shader_instance() {}
|
||||
|
||||
uint32_t filter::shader::shader_instance::width()
|
||||
uint32_t filter::shader::shader_instance::get_width()
|
||||
{
|
||||
return _swidth;
|
||||
return _fx->width();
|
||||
}
|
||||
|
||||
uint32_t filter::shader::shader_instance::height()
|
||||
uint32_t filter::shader::shader_instance::get_height()
|
||||
{
|
||||
return _sheight;
|
||||
}
|
||||
|
||||
bool modifiedcb3(obs_properties_t* props, obs_property_t* property, obs_data_t* settings) noexcept try {
|
||||
obs_property_set_visible(obs_properties_get(props, ST_SCALE_SCALE), obs_data_get_bool(settings, ST_SCALE_LOCKED));
|
||||
obs_property_set_visible(obs_properties_get(props, ST_SCALE_WIDTH), !obs_data_get_bool(settings, ST_SCALE_LOCKED));
|
||||
obs_property_set_visible(obs_properties_get(props, ST_SCALE_HEIGHT), !obs_data_get_bool(settings, ST_SCALE_LOCKED));
|
||||
return true;
|
||||
} catch (const std::exception& ex) {
|
||||
P_LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
||||
} catch (...) {
|
||||
P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
||||
return false;
|
||||
return _fx->height();
|
||||
}
|
||||
|
||||
void filter::shader::shader_instance::properties(obs_properties_t* props)
|
||||
{
|
||||
auto p = obs_properties_add_bool(props, ST_SCALE_LOCKED, D_TRANSLATE(ST_SCALE_LOCKED));
|
||||
obs_property_set_modified_callback(p, modifiedcb3);
|
||||
obs_properties_add_float(props, ST_SCALE_SCALE, D_TRANSLATE(ST_SCALE_SCALE), 0.01, 5.0, 0.01);
|
||||
obs_properties_add_float(props, ST_SCALE_WIDTH, D_TRANSLATE(ST_SCALE_WIDTH), 0.01, 5.0, 0.01);
|
||||
obs_properties_add_float(props, ST_SCALE_HEIGHT, D_TRANSLATE(ST_SCALE_HEIGHT), 0.01, 5.0, 0.01);
|
||||
|
||||
_fx->properties(props);
|
||||
}
|
||||
|
||||
|
@ -248,143 +57,95 @@ void filter::shader::shader_instance::load(obs_data_t* data)
|
|||
|
||||
void filter::shader::shader_instance::update(obs_data_t* data)
|
||||
{
|
||||
_scale_locked = obs_data_get_bool(data, ST_SCALE_LOCKED);
|
||||
if (_scale_locked) {
|
||||
_hscale = _wscale = obs_data_get_double(data, ST_SCALE_SCALE);
|
||||
} else {
|
||||
_wscale = obs_data_get_double(data, ST_SCALE_WIDTH);
|
||||
_hscale = obs_data_get_double(data, ST_SCALE_HEIGHT);
|
||||
}
|
||||
_fx->update(data);
|
||||
}
|
||||
|
||||
void filter::shader::shader_instance::activate()
|
||||
{
|
||||
_active = true;
|
||||
}
|
||||
|
||||
void filter::shader::shader_instance::deactivate()
|
||||
{
|
||||
_active = false;
|
||||
}
|
||||
|
||||
bool filter::shader::shader_instance::valid_param(std::shared_ptr<gs::effect_parameter> param)
|
||||
{
|
||||
if (strcmp(param->get_name().c_str(), "ImageSource") == 0)
|
||||
return false;
|
||||
if (strcmp(param->get_name().c_str(), "ImageSource_Size") == 0)
|
||||
return false;
|
||||
if (strcmp(param->get_name().c_str(), "ImageSource_Texel") == 0)
|
||||
return false;
|
||||
if (strcmp(param->get_name().c_str(), "ImageTarget_Size") == 0)
|
||||
return false;
|
||||
if (strcmp(param->get_name().c_str(), "ImageTarget_Texel") == 0)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void filter::shader::shader_instance::override_param(std::shared_ptr<gs::effect> effect)
|
||||
{
|
||||
auto p_source = effect->get_parameter("ImageSource");
|
||||
auto p_source_size = effect->get_parameter("ImageSource_Size");
|
||||
auto p_source_texel = effect->get_parameter("ImageSource_Texel");
|
||||
if (p_source && (p_source->get_type() == gs::effect_parameter::type::Texture)) {
|
||||
p_source->set_texture(_rt_tex);
|
||||
}
|
||||
if (p_source_size && (p_source_size->get_type() == gs::effect_parameter::type::Float2)) {
|
||||
p_source_size->set_float2(_width, _height);
|
||||
}
|
||||
if (p_source_texel && (p_source_size->get_type() == gs::effect_parameter::type::Float2)) {
|
||||
p_source_texel->set_float2(1.0f / _width, 1.0f / _height);
|
||||
}
|
||||
|
||||
auto p_target_size = effect->get_parameter("ImageTarget_Size");
|
||||
auto p_target_texel = effect->get_parameter("ImageTarget_Texel");
|
||||
if (p_target_size && (p_target_size->get_type() == gs::effect_parameter::type::Float2)) {
|
||||
p_target_size->set_float2(_swidth, _sheight);
|
||||
}
|
||||
if (p_target_texel && (p_target_texel->get_type() == gs::effect_parameter::type::Float2)) {
|
||||
p_target_texel->set_float2(1.0f / _swidth, 1.0f / _sheight);
|
||||
}
|
||||
}
|
||||
|
||||
void filter::shader::shader_instance::enum_active_sources(obs_source_enum_proc_t r, void* p)
|
||||
{
|
||||
_fx->enum_active_sources(r, p);
|
||||
}
|
||||
|
||||
void filter::shader::shader_instance::video_tick(float_t sec_since_last)
|
||||
{
|
||||
obs_source_t* target = obs_filter_get_target(_self);
|
||||
|
||||
{ // Update width and height.
|
||||
_width = obs_source_get_base_width(target);
|
||||
_height = obs_source_get_base_height(target);
|
||||
_swidth = _width * _wscale;
|
||||
_sheight = _height * _hscale;
|
||||
}
|
||||
|
||||
if (_fx->tick(sec_since_last)) {
|
||||
obs_data_t* data = obs_source_get_settings(_self);
|
||||
update(data);
|
||||
_fx->update(data);
|
||||
obs_data_release(data);
|
||||
}
|
||||
|
||||
_rt_updated = false;
|
||||
_rt2_updated = false;
|
||||
obs_source_t* tgt = obs_filter_get_target(_self);
|
||||
_fx->set_size(obs_source_get_width(tgt), obs_source_get_height(tgt));
|
||||
}
|
||||
|
||||
void filter::shader::shader_instance::video_render(gs_effect_t* effect)
|
||||
{
|
||||
// Grab initial values.
|
||||
obs_source_t* parent = obs_filter_get_parent(_self);
|
||||
obs_source_t* target = obs_filter_get_target(_self);
|
||||
gs_effect_t* effect_default = obs_get_base_effect(obs_base_effect::OBS_EFFECT_DEFAULT);
|
||||
|
||||
// Skip filter if anything is wrong.
|
||||
if (!_active || !parent || !target || !_width || !_height || !effect_default) {
|
||||
if (!_fx || !_fx->width() || !_fx->height()) {
|
||||
obs_source_skip_video_filter(_self);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_rt_updated) {
|
||||
if (obs_source_process_filter_begin(_self, GS_RGBA, OBS_ALLOW_DIRECT_RENDERING)) {
|
||||
auto op = _rt->render(_width, _height);
|
||||
{
|
||||
gs::debug_marker _marker_cache{gs::debug_color_cache, "%s Cache"};
|
||||
auto op = _rt->render(_fx->width(), _fx->height());
|
||||
|
||||
gs_ortho(0, static_cast<float_t>(_fx->width()), 0, static_cast<float_t>(_fx->height()), -1, 1);
|
||||
|
||||
vec4 clear_color = {0};
|
||||
gs_clear(GS_CLEAR_COLOR | GS_CLEAR_DEPTH, &clear_color, 0, 0);
|
||||
|
||||
/// Render original source
|
||||
if (obs_source_process_filter_begin(_self, GS_RGBA, OBS_NO_DIRECT_RENDERING)) {
|
||||
gs_blend_state_push();
|
||||
gs_reset_blend_state();
|
||||
gs_set_cull_mode(GS_NEITHER);
|
||||
gs_enable_color(true, true, true, true);
|
||||
gs_enable_blending(false);
|
||||
gs_blend_function_separate(GS_BLEND_ONE, GS_BLEND_ZERO, GS_BLEND_SRCALPHA, GS_BLEND_ZERO);
|
||||
gs_enable_depth_test(false);
|
||||
gs_enable_stencil_test(false);
|
||||
gs_enable_stencil_write(false);
|
||||
gs_ortho(0, static_cast<float_t>(_width), 0, static_cast<float_t>(_height), -1., 1.);
|
||||
obs_source_process_filter_end(_self, effect_default, _width, _height);
|
||||
gs_enable_color(true, true, true, true);
|
||||
gs_set_cull_mode(GS_NEITHER);
|
||||
|
||||
obs_source_process_filter_end(_self, obs_get_base_effect(OBS_EFFECT_DEFAULT), _fx->width(), _fx->height());
|
||||
|
||||
gs_blend_state_pop();
|
||||
}
|
||||
_rt_tex = _rt->get_texture();
|
||||
_rt_updated = true;
|
||||
}
|
||||
|
||||
if (!_rt2_updated) {
|
||||
try {
|
||||
auto op = _rt2->render(_swidth, _sheight);
|
||||
_fx->render();
|
||||
} catch (...) {
|
||||
} else {
|
||||
obs_source_skip_video_filter(_self);
|
||||
return;
|
||||
}
|
||||
_rt2_tex = _rt2->get_texture();
|
||||
_rt2_updated = true;
|
||||
}
|
||||
|
||||
if (!_rt2_tex)
|
||||
return;
|
||||
|
||||
gs_effect_t* ef = effect ? effect : effect_default;
|
||||
if (gs_eparam_t* prm = gs_effect_get_param_by_name(ef, "image"))
|
||||
gs_effect_set_texture(prm, _rt2_tex->get_object());
|
||||
|
||||
while (gs_effect_loop(ef, "Draw")) {
|
||||
gs_draw_sprite(nullptr, 0, _swidth, _sheight);
|
||||
}
|
||||
_fx->prepare_render();
|
||||
_fx->set_input_a(_rt->get_texture());
|
||||
_fx->render();
|
||||
}
|
||||
|
||||
void filter::shader::shader_instance::transition_start() {}
|
||||
|
||||
void filter::shader::shader_instance::transition_stop() {}
|
||||
|
||||
std::shared_ptr<filter::shader::shader_factory> filter::shader::shader_factory::factory_instance = nullptr;
|
||||
|
||||
filter::shader::shader_factory::shader_factory()
|
||||
{
|
||||
_info.id = "obs-stream-effects-filter-shader";
|
||||
_info.type = OBS_SOURCE_TYPE_FILTER;
|
||||
_info.output_flags = OBS_SOURCE_VIDEO | OBS_SOURCE_CUSTOM_DRAW;
|
||||
|
||||
finish_setup();
|
||||
}
|
||||
|
||||
filter::shader::shader_factory::~shader_factory() {}
|
||||
|
||||
const char* filter::shader::shader_factory::get_name()
|
||||
{
|
||||
return D_TRANSLATE(ST);
|
||||
}
|
||||
|
||||
void filter::shader::shader_factory::get_defaults2(obs_data_t* data) {}
|
||||
|
||||
obs_properties_t* filter::shader::shader_factory::get_properties2(shader::shader_instance* data)
|
||||
{
|
||||
auto pr = obs_properties_create();
|
||||
obs_properties_set_param(pr, data, nullptr);
|
||||
|
||||
if (data) {
|
||||
reinterpret_cast<shader_instance*>(data)->properties(pr);
|
||||
}
|
||||
|
||||
return pr;
|
||||
}
|
||||
|
|
|
@ -21,69 +21,64 @@
|
|||
|
||||
#include "gfx/shader/gfx-shader.hpp"
|
||||
#include "obs/gs/gs-rendertarget.hpp"
|
||||
#include "obs/obs-source-factory.hpp"
|
||||
#include "plugin.hpp"
|
||||
|
||||
extern "C" {
|
||||
#include <obs.h>
|
||||
}
|
||||
|
||||
namespace filter {
|
||||
namespace shader {
|
||||
class shader_factory {
|
||||
obs_source_info _source_info;
|
||||
namespace filter::shader {
|
||||
class shader_instance : public obs::source_instance {
|
||||
std::shared_ptr<gfx::shader::shader> _fx;
|
||||
std::shared_ptr<gs::rendertarget> _rt;
|
||||
|
||||
public: // Singleton
|
||||
static void initialize();
|
||||
static void finalize();
|
||||
static std::shared_ptr<shader_factory> get();
|
||||
public:
|
||||
shader_instance(obs_data_t* data, obs_source_t* self);
|
||||
virtual ~shader_instance();
|
||||
|
||||
public:
|
||||
shader_factory();
|
||||
~shader_factory();
|
||||
};
|
||||
virtual uint32_t get_width() override;
|
||||
virtual uint32_t get_height() override;
|
||||
|
||||
class shader_instance {
|
||||
obs_source_t* _self;
|
||||
bool _active;
|
||||
void properties(obs_properties_t* props);
|
||||
|
||||
uint32_t _width, _height;
|
||||
virtual void load(obs_data_t* data) override;
|
||||
virtual void update(obs_data_t* data) override;
|
||||
|
||||
bool _scale_locked;
|
||||
float_t _wscale, _hscale;
|
||||
uint32_t _swidth, _sheight;
|
||||
virtual void video_tick(float_t sec_since_last) override;
|
||||
virtual void video_render(gs_effect_t* effect) override;
|
||||
|
||||
std::shared_ptr<gs::rendertarget> _rt;
|
||||
bool _rt_updated;
|
||||
std::shared_ptr<gs::texture> _rt_tex;
|
||||
virtual void transition_start() override;
|
||||
virtual void transition_stop() override;
|
||||
};
|
||||
|
||||
std::shared_ptr<gs::rendertarget> _rt2;
|
||||
bool _rt2_updated;
|
||||
std::shared_ptr<gs::texture> _rt2_tex;
|
||||
class shader_factory : public obs::source_factory<filter::shader::shader_factory, filter::shader::shader_instance> {
|
||||
static std::shared_ptr<filter::shader::shader_factory> factory_instance;
|
||||
|
||||
std::shared_ptr<gfx::effect_source::effect_source> _fx;
|
||||
public: // Singleton
|
||||
static void initialize()
|
||||
{
|
||||
factory_instance = std::make_shared<filter::shader::shader_factory>();
|
||||
}
|
||||
|
||||
public:
|
||||
shader_instance(obs_data_t* data, obs_source_t* self);
|
||||
~shader_instance();
|
||||
static void finalize()
|
||||
{
|
||||
factory_instance.reset();
|
||||
}
|
||||
|
||||
uint32_t width();
|
||||
uint32_t height();
|
||||
static std::shared_ptr<shader_factory> get()
|
||||
{
|
||||
return factory_instance;
|
||||
}
|
||||
|
||||
void properties(obs_properties_t* props);
|
||||
public:
|
||||
shader_factory();
|
||||
virtual ~shader_factory();
|
||||
|
||||
void load(obs_data_t* data);
|
||||
void update(obs_data_t* data);
|
||||
virtual const char* get_name() override;
|
||||
|
||||
void activate();
|
||||
void deactivate();
|
||||
virtual void get_defaults2(obs_data_t* data) override;
|
||||
|
||||
bool valid_param(std::shared_ptr<gs::effect_parameter> param);
|
||||
void override_param(std::shared_ptr<gs::effect> effect);
|
||||
|
||||
void enum_active_sources(obs_source_enum_proc_t, void*);
|
||||
|
||||
void video_tick(float_t sec_since_last);
|
||||
void video_render(gs_effect_t* effect);
|
||||
};
|
||||
} // namespace shader
|
||||
} // namespace filter
|
||||
virtual obs_properties_t* get_properties2(filter::shader::shader_instance* data) override;
|
||||
};
|
||||
} // namespace filter::shader
|
||||
|
|
|
@ -41,7 +41,7 @@
|
|||
#include "filters/filter-sdf-effects.hpp"
|
||||
#endif
|
||||
#ifdef ENABLE_FILTER_SHADER
|
||||
//#include "filters/filter-shader.hpp"
|
||||
#include "filters/filter-shader.hpp"
|
||||
#endif
|
||||
#ifdef ENABLE_FILTER_TRANSFORM
|
||||
#include "filters/filter-transform.hpp"
|
||||
|
@ -91,7 +91,7 @@ try {
|
|||
filter::sdf_effects::sdf_effects_factory::initialize();
|
||||
#endif
|
||||
#ifdef ENABLE_FILTER_SHADER
|
||||
//filter::shader::shader_factory::initialize();
|
||||
filter::shader::shader_factory::initialize();
|
||||
#endif
|
||||
#ifdef ENABLE_FILTER_TRANSFORM
|
||||
filter::transform::transform_factory::initialize();
|
||||
|
@ -107,7 +107,7 @@ try {
|
|||
|
||||
// Transitions
|
||||
#ifdef ENABLE_TRANSITION_SHADER
|
||||
transition::shader::shader_factory::initialize();
|
||||
transition::shader::shader_factory::initialize();
|
||||
#endif
|
||||
|
||||
return true;
|
||||
|
@ -122,7 +122,7 @@ try {
|
|||
|
||||
// Transitions
|
||||
#ifdef ENABLE_TRANSITION_SHADER
|
||||
transition::shader::shader_factory::finalize();
|
||||
transition::shader::shader_factory::finalize();
|
||||
#endif
|
||||
|
||||
// Sources
|
||||
|
@ -150,7 +150,7 @@ transition::shader::shader_factory::finalize();
|
|||
filter::sdf_effects::sdf_effects_factory::finalize();
|
||||
#endif
|
||||
#ifdef ENABLE_FILTER_SHADER
|
||||
//filter::shader::shader_factory::finalize();
|
||||
filter::shader::shader_factory::finalize();
|
||||
#endif
|
||||
#ifdef ENABLE_FILTER_TRANSFORM
|
||||
filter::transform::transform_factory::finalize();
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
#include "strings.hpp"
|
||||
#include "utility.hpp"
|
||||
|
||||
#define ST "Source.Shader"
|
||||
#define ST "Transition.Shader"
|
||||
|
||||
transition::shader::shader_instance::shader_instance(obs_data_t* data, obs_source_t* self)
|
||||
: obs::source_instance(data, self), _is_main(false)
|
||||
|
|
Loading…
Reference in New Issue