mirror of
https://github.com/Xaymar/obs-StreamFX
synced 2024-11-10 22:05:06 +00:00
gfx-effect-source: Implement basic functionality
Rendering is now possible, although some parameter types are not yet supported. So far, booleans and floats will work fine, integers will cause an error in OBS Studios rendering code for an unknown reason.
This commit is contained in:
parent
b4de874ec9
commit
0957ce0bb9
3 changed files with 195 additions and 86 deletions
|
@ -1,6 +1,16 @@
|
||||||
# Generic
|
# Generic
|
||||||
Advanced="Advanced"
|
Advanced="Advanced"
|
||||||
|
|
||||||
|
# Custom Shader
|
||||||
|
CustomShader.Type="Type"
|
||||||
|
CustomShader.Type.Description="What type of shader do you want to use?"
|
||||||
|
CustomShader.Type.Text="Text"
|
||||||
|
CustomShader.Type.File="File"
|
||||||
|
CustomShader.Input.Text="Shader Content"
|
||||||
|
CustomShader.Input.Text.Description="Text to load as a shader."
|
||||||
|
CustomShader.Input.File="Shader File"
|
||||||
|
CustomShader.Input.File.Description="File to load as a shader."
|
||||||
|
|
||||||
# Filter - Blur
|
# Filter - Blur
|
||||||
Filter.Blur="Blur"
|
Filter.Blur="Blur"
|
||||||
Filter.Blur.Type="Type"
|
Filter.Blur.Type="Type"
|
||||||
|
|
|
@ -52,27 +52,31 @@ bool gfx::effect_source::property_input_modified(void* obj, obs_properties_t*, o
|
||||||
return reinterpret_cast<gfx::effect_source*>(obj)->test_for_updates(text, file);
|
return reinterpret_cast<gfx::effect_source*>(obj)->test_for_updates(text, file);
|
||||||
}
|
}
|
||||||
|
|
||||||
void gfx::effect_source::video_tick_impl(float time) {
|
|
||||||
// Shader Timers
|
|
||||||
time_existing += time;
|
|
||||||
time_active += time;
|
|
||||||
|
|
||||||
// File Timer
|
|
||||||
shader.file_info.time_updated -= time;
|
|
||||||
}
|
|
||||||
|
|
||||||
void gfx::effect_source::video_render_impl(gs_effect_t* parent_effect) {
|
|
||||||
parent_effect;
|
|
||||||
}
|
|
||||||
|
|
||||||
gfx::effect_source::effect_source(obs_data_t* data, obs_source_t* owner) {
|
gfx::effect_source::effect_source(obs_data_t* data, obs_source_t* owner) {
|
||||||
m_source = owner;
|
m_source = owner;
|
||||||
time_existing = 0;
|
m_timeExisting = 0;
|
||||||
time_active = 0;
|
m_timeActive = 0;
|
||||||
update(data);
|
|
||||||
|
m_quadBuffer = std::make_shared<gs::vertex_buffer>(4);
|
||||||
|
m_quadBuffer->set_uv_layers(1);
|
||||||
|
auto vtx = m_quadBuffer->at(0);
|
||||||
|
vec3_set(vtx.position, 0, 0, 0);
|
||||||
|
vec4_set(vtx.uv[0], 0, 0, 0, 0);
|
||||||
|
vtx = m_quadBuffer->at(2);
|
||||||
|
vec3_set(vtx.position, 1, 0, 0);
|
||||||
|
vec4_set(vtx.uv[0], 1, 0, 0, 0);
|
||||||
|
vtx = m_quadBuffer->at(1);
|
||||||
|
vec3_set(vtx.position, 0, 1, 0);
|
||||||
|
vec4_set(vtx.uv[0], 0, 1, 0, 0);
|
||||||
|
vtx = m_quadBuffer->at(3);
|
||||||
|
vec3_set(vtx.position, 1, 1, 0);
|
||||||
|
vec4_set(vtx.uv[0], 1, 1, 0, 0);
|
||||||
|
m_quadBuffer->update(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
gfx::effect_source::~effect_source() {}
|
gfx::effect_source::~effect_source() {
|
||||||
|
m_quadBuffer = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
void gfx::effect_source::get_properties(obs_properties_t* properties) {
|
void gfx::effect_source::get_properties(obs_properties_t* properties) {
|
||||||
obs_property_t* p = nullptr;
|
obs_property_t* p = nullptr;
|
||||||
|
@ -88,7 +92,7 @@ void gfx::effect_source::get_properties(obs_properties_t* properties) {
|
||||||
obs_property_set_modified_callback2(p, property_input_modified, this);
|
obs_property_set_modified_callback2(p, property_input_modified, this);
|
||||||
|
|
||||||
{
|
{
|
||||||
char* tmp_path = obs_module_file(default_shader_path.c_str());
|
char* tmp_path = obs_module_file(m_defaultShaderPath.c_str());
|
||||||
p = obs_properties_add_path(properties, D_INPUT_FILE, P_TRANSLATE(T_INPUT_FILE), OBS_PATH_FILE,
|
p = obs_properties_add_path(properties, D_INPUT_FILE, P_TRANSLATE(T_INPUT_FILE), OBS_PATH_FILE,
|
||||||
"Any (*.effect *.shader *.hlsl);;Effect (*.effect);;Shader (*.shader);;DirectX (*.hlsl)", tmp_path);
|
"Any (*.effect *.shader *.hlsl);;Effect (*.effect);;Shader (*.shader);;DirectX (*.hlsl)", tmp_path);
|
||||||
obs_property_set_long_description(p, P_TRANSLATE(P_DESC(T_INPUT_FILE)));
|
obs_property_set_long_description(p, P_TRANSLATE(P_DESC(T_INPUT_FILE)));
|
||||||
|
@ -97,7 +101,7 @@ void gfx::effect_source::get_properties(obs_properties_t* properties) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ToDo: Place updated properties here or somewhere else?
|
// ToDo: Place updated properties here or somewhere else?
|
||||||
for (auto prm : parameters) {
|
for (auto prm : m_parameters) {
|
||||||
if (prm.first.second == gs::effect_parameter::type::Boolean) {
|
if (prm.first.second == gs::effect_parameter::type::Boolean) {
|
||||||
obs_properties_add_bool(properties, prm.second->ui.names[0], prm.second->ui.descs[0]);
|
obs_properties_add_bool(properties, prm.second->ui.names[0], prm.second->ui.descs[0]);
|
||||||
} else if (prm.first.second >= gs::effect_parameter::type::Integer && prm.first.second <= gs::effect_parameter::type::Integer4) {
|
} else if (prm.first.second >= gs::effect_parameter::type::Integer && prm.first.second <= gs::effect_parameter::type::Integer4) {
|
||||||
|
@ -110,7 +114,7 @@ void gfx::effect_source::get_properties(obs_properties_t* properties) {
|
||||||
size_t cnt = (size_t)prm.first.second - (size_t)gs::effect_parameter::type::Float;
|
size_t cnt = (size_t)prm.first.second - (size_t)gs::effect_parameter::type::Float;
|
||||||
|
|
||||||
for (size_t idx = 0; idx <= cnt; idx++) {
|
for (size_t idx = 0; idx <= cnt; idx++) {
|
||||||
obs_properties_add_float(properties, prm.second->ui.names[idx], prm.second->ui.descs[idx], FLT_MIN, FLT_MAX, 1);
|
obs_properties_add_float(properties, prm.second->ui.names[idx], prm.second->ui.descs[idx], FLT_MIN, FLT_MAX, 0.01);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -143,51 +147,55 @@ void gfx::effect_source::update(obs_data_t* data) {
|
||||||
bool gfx::effect_source::test_for_updates(const char* text, const char* path) {
|
bool gfx::effect_source::test_for_updates(const char* text, const char* path) {
|
||||||
bool is_shader_different = false;
|
bool is_shader_different = false;
|
||||||
if (text != nullptr) {
|
if (text != nullptr) {
|
||||||
if (text != shader.text) {
|
if (text != m_shader.text) {
|
||||||
shader.text = text;
|
m_shader.text = text;
|
||||||
is_shader_different = true;
|
is_shader_different = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_shader_different) {
|
if (is_shader_different) {
|
||||||
shader.effect = std::make_unique<gs::effect>(shader.text, "Text");
|
try {
|
||||||
|
m_shader.effect = std::make_unique<gs::effect>(m_shader.text, "Text");
|
||||||
|
} catch (...) {
|
||||||
|
m_shader.effect = nullptr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if (path != nullptr) {
|
} else if (path != nullptr) {
|
||||||
if (path != this->shader.path) {
|
if (path != this->m_shader.path) {
|
||||||
this->shader.path = path;
|
this->m_shader.path = path;
|
||||||
this->shader.file_info.time_updated = 0;
|
this->m_shader.file_info.time_updated = 0;
|
||||||
this->shader.file_info.time_create = 0;
|
this->m_shader.file_info.time_create = 0;
|
||||||
this->shader.file_info.time_modified = 0;
|
this->m_shader.file_info.time_modified = 0;
|
||||||
this->shader.file_info.file_size = 0;
|
this->m_shader.file_info.file_size = 0;
|
||||||
is_shader_different = true;
|
is_shader_different = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the update timer is 0 or less, grab new file information.
|
// If the update timer is 0 or less, grab new file information.
|
||||||
if (shader.file_info.time_updated <= 0) {
|
if (m_shader.file_info.time_updated <= 0) {
|
||||||
struct stat stats;
|
struct stat stats;
|
||||||
if (os_stat(shader.path.c_str(), &stats) == 0) {
|
if (os_stat(m_shader.path.c_str(), &stats) == 0) {
|
||||||
shader.file_info.modified = (shader.file_info.time_create != stats.st_ctime)
|
m_shader.file_info.modified = (m_shader.file_info.time_create != stats.st_ctime)
|
||||||
| (shader.file_info.time_modified != stats.st_mtime)
|
| (m_shader.file_info.time_modified != stats.st_mtime)
|
||||||
| (shader.file_info.file_size != stats.st_size);
|
| (m_shader.file_info.file_size != stats.st_size);
|
||||||
|
|
||||||
// Mark shader as different if the file was changed.
|
// Mark shader as different if the file was changed.
|
||||||
is_shader_different =
|
is_shader_different =
|
||||||
is_shader_different
|
is_shader_different
|
||||||
| shader.file_info.modified;
|
| m_shader.file_info.modified;
|
||||||
|
|
||||||
// Update own information
|
// Update own information
|
||||||
shader.file_info.time_create = stats.st_ctime;
|
m_shader.file_info.time_create = stats.st_ctime;
|
||||||
shader.file_info.time_modified = stats.st_mtime;
|
m_shader.file_info.time_modified = stats.st_mtime;
|
||||||
shader.file_info.file_size = stats.st_size;
|
m_shader.file_info.file_size = stats.st_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Increment timer so that the next check is a reasonable timespan away.
|
// Increment timer so that the next check is a reasonable timespan away.
|
||||||
shader.file_info.time_updated += 0.1f;
|
m_shader.file_info.time_updated += 0.1f;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_shader_different || shader.file_info.modified) {
|
if (is_shader_different || m_shader.file_info.modified) {
|
||||||
// gs_effect_create_from_file caches results, which is bad for us.
|
// gs_effect_create_from_file caches results, which is bad for us.
|
||||||
std::vector<char> content;
|
std::vector<char> content;
|
||||||
std::ifstream fs(shader.path.c_str(), std::ios::binary);
|
std::ifstream fs(m_shader.path.c_str(), std::ios::binary);
|
||||||
|
|
||||||
if (fs.good()) {
|
if (fs.good()) {
|
||||||
size_t beg = fs.tellg();
|
size_t beg = fs.tellg();
|
||||||
|
@ -199,18 +207,22 @@ bool gfx::effect_source::test_for_updates(const char* text, const char* path) {
|
||||||
fs.close();
|
fs.close();
|
||||||
content[sz] = '\0';
|
content[sz] = '\0';
|
||||||
|
|
||||||
shader.effect = std::make_unique<gs::effect>(std::string(content.data()), shader.path);
|
try {
|
||||||
|
m_shader.effect = std::make_unique<gs::effect>(std::string(content.data()), m_shader.path);
|
||||||
|
} catch (...) {
|
||||||
|
m_shader.effect = nullptr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the shader is different, rebuild the parameter list.
|
// If the shader is different, rebuild the parameter list.
|
||||||
if (is_shader_different) {
|
if (is_shader_different) {
|
||||||
if (shader.effect) {
|
if (m_shader.effect) {
|
||||||
// ToDo: Figure out if a recycling approach would work.
|
// ToDo: Figure out if a recycling approach would work.
|
||||||
// Might improve stability in low memory situations.
|
// Might improve stability in low memory situations.
|
||||||
std::map<paramident_t, std::shared_ptr<parameter>> new_params;
|
std::map<paramident_t, std::shared_ptr<parameter>> new_params;
|
||||||
auto effect_param_list = shader.effect->get_parameters();
|
auto effect_param_list = m_shader.effect->get_parameters();
|
||||||
for (auto effect_param : effect_param_list) {
|
for (auto effect_param : effect_param_list) {
|
||||||
paramident_t ident;
|
paramident_t ident;
|
||||||
ident.first = effect_param.get_name();
|
ident.first = effect_param.get_name();
|
||||||
|
@ -219,11 +231,11 @@ bool gfx::effect_source::test_for_updates(const char* text, const char* path) {
|
||||||
if (is_special_parameter(ident.first, ident.second))
|
if (is_special_parameter(ident.first, ident.second))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
auto entry = parameters.find(ident);
|
auto entry = m_parameters.find(ident);
|
||||||
if (entry != parameters.end()) {
|
if (entry != m_parameters.end()) {
|
||||||
entry->second->param = std::make_shared<gs::effect_parameter>(effect_param);
|
entry->second->param = std::make_shared<gs::effect_parameter>(effect_param);
|
||||||
new_params.insert_or_assign(ident, entry->second);
|
new_params.insert_or_assign(ident, entry->second);
|
||||||
parameters.erase(entry);
|
m_parameters.erase(entry);
|
||||||
} else {
|
} else {
|
||||||
std::shared_ptr<parameter> param;
|
std::shared_ptr<parameter> param;
|
||||||
|
|
||||||
|
@ -335,9 +347,9 @@ bool gfx::effect_source::test_for_updates(const char* text, const char* path) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
parameters = std::move(new_params);
|
m_parameters = std::move(new_params);
|
||||||
} else {
|
} else {
|
||||||
parameters.clear();
|
m_parameters.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -345,7 +357,7 @@ bool gfx::effect_source::test_for_updates(const char* text, const char* path) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void gfx::effect_source::update_parameters(obs_data_t* data) {
|
void gfx::effect_source::update_parameters(obs_data_t* data) {
|
||||||
for (auto prm : parameters) {
|
for (auto prm : m_parameters) {
|
||||||
if (prm.first.second == gs::effect_parameter::type::Boolean) {
|
if (prm.first.second == gs::effect_parameter::type::Boolean) {
|
||||||
auto param = std::static_pointer_cast<bool_parameter>(prm.second);
|
auto param = std::static_pointer_cast<bool_parameter>(prm.second);
|
||||||
param->value = obs_data_get_bool(data, prm.second->ui.names[0]);
|
param->value = obs_data_get_bool(data, prm.second->ui.names[0]);
|
||||||
|
@ -364,30 +376,56 @@ void gfx::effect_source::update_parameters(obs_data_t* data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void gfx::effect_source::apply_parameters() {
|
void gfx::effect_source::apply_parameters() {
|
||||||
for (auto prm : parameters) {
|
for (auto prm : m_parameters) {
|
||||||
if (prm.first.second == gs::effect_parameter::type::Boolean) {
|
if (prm.first.second == gs::effect_parameter::type::Boolean) {
|
||||||
auto param = std::static_pointer_cast<bool_parameter>(prm.second);
|
auto param = std::static_pointer_cast<bool_parameter>(prm.second);
|
||||||
|
param->param->set_bool(param->value);
|
||||||
} else if (prm.first.second >= gs::effect_parameter::type::Integer && prm.first.second <= gs::effect_parameter::type::Integer4) {
|
} else if (prm.first.second >= gs::effect_parameter::type::Integer && prm.first.second <= gs::effect_parameter::type::Integer4) {
|
||||||
auto param = std::static_pointer_cast<int_parameter>(prm.second);
|
auto param = std::static_pointer_cast<int_parameter>(prm.second);
|
||||||
|
switch (prm.first.second) {
|
||||||
|
case gs::effect_parameter::type::Integer:
|
||||||
|
param->param->set_int(param->value[0]);
|
||||||
|
break;
|
||||||
|
case gs::effect_parameter::type::Integer2:
|
||||||
|
param->param->set_int2(param->value[0], param->value[1]);
|
||||||
|
break;
|
||||||
|
case gs::effect_parameter::type::Integer3:
|
||||||
|
param->param->set_int3(param->value[0], param->value[1], param->value[2]);
|
||||||
|
break;
|
||||||
|
case gs::effect_parameter::type::Integer4:
|
||||||
|
param->param->set_int4(param->value[0], param->value[1], param->value[2], param->value[3]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
} else if (prm.first.second >= gs::effect_parameter::type::Float && prm.first.second <= gs::effect_parameter::type::Float4) {
|
} else if (prm.first.second >= gs::effect_parameter::type::Float && prm.first.second <= gs::effect_parameter::type::Float4) {
|
||||||
auto param = std::static_pointer_cast<float_parameter>(prm.second);
|
auto param = std::static_pointer_cast<float_parameter>(prm.second);
|
||||||
|
switch (prm.first.second) {
|
||||||
|
case gs::effect_parameter::type::Float:
|
||||||
|
param->param->set_float(param->value[0]);
|
||||||
|
break;
|
||||||
|
case gs::effect_parameter::type::Float2:
|
||||||
|
param->param->set_float2(param->value[0], param->value[1]);
|
||||||
|
break;
|
||||||
|
case gs::effect_parameter::type::Float3:
|
||||||
|
param->param->set_float3(param->value[0], param->value[1], param->value[2]);
|
||||||
|
break;
|
||||||
|
case gs::effect_parameter::type::Float4:
|
||||||
|
param->param->set_float4(param->value[0], param->value[1], param->value[2], param->value[3]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void gfx::effect_source::activate() {
|
void gfx::effect_source::activate() {
|
||||||
time_active = 0;
|
m_timeActive = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void gfx::effect_source::deactivate() {
|
void gfx::effect_source::deactivate() {
|
||||||
time_active = 0;
|
m_timeActive = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string gfx::effect_source::get_shader_file() {
|
std::string gfx::effect_source::get_shader_file() {
|
||||||
return shader.path;
|
return m_shader.path;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t gfx::effect_source::get_width() {
|
uint32_t gfx::effect_source::get_width() {
|
||||||
|
@ -399,9 +437,66 @@ uint32_t gfx::effect_source::get_height() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void gfx::effect_source::video_tick(float time) {
|
void gfx::effect_source::video_tick(float time) {
|
||||||
|
// Shader Timers
|
||||||
|
m_timeExisting += time;
|
||||||
|
m_timeActive += time;
|
||||||
|
|
||||||
|
// File Timer
|
||||||
|
m_shader.file_info.time_updated -= time;
|
||||||
|
|
||||||
video_tick_impl(time);
|
video_tick_impl(time);
|
||||||
}
|
}
|
||||||
|
|
||||||
void gfx::effect_source::video_render(gs_effect_t* parent_effect) {
|
void gfx::effect_source::video_render(gs_effect_t* parent_effect) {
|
||||||
video_render_impl(parent_effect);
|
if (!m_source) {
|
||||||
|
obs_source_skip_video_filter(m_source);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
obs_source_t *parent = obs_filter_get_parent(m_source);
|
||||||
|
obs_source_t *target = obs_filter_get_target(m_source);
|
||||||
|
if (!parent || !target || !m_shader.effect) {
|
||||||
|
obs_source_skip_video_filter(m_source);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t viewW = obs_source_get_base_width(target),
|
||||||
|
viewH = obs_source_get_base_height(target);
|
||||||
|
if (!viewW || !viewH) {
|
||||||
|
obs_source_skip_video_filter(m_source);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
apply_parameters();
|
||||||
|
if (!video_render_impl(parent_effect, viewW, viewH)) {
|
||||||
|
obs_source_skip_video_filter(m_source);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (m_shader.effect->has_parameter("ViewSize", gs::effect_parameter::type::Float2)) {
|
||||||
|
m_shader.effect->get_parameter("ViewSize").set_float2(float_t(viewW), float_t(viewH));
|
||||||
|
}
|
||||||
|
if (m_shader.effect->has_parameter("ViewSizeI"/*, gs::effect_parameter::type::Integer2*/)) {
|
||||||
|
m_shader.effect->get_parameter("ViewSizeI").set_int2(int32_t(viewW), int32_t(viewH));
|
||||||
|
}
|
||||||
|
if (m_shader.effect->has_parameter("Time", gs::effect_parameter::type::Float)) {
|
||||||
|
m_shader.effect->get_parameter("Time").set_float(m_timeExisting);
|
||||||
|
}
|
||||||
|
if (m_shader.effect->has_parameter("TimeActive", gs::effect_parameter::type::Float)) {
|
||||||
|
m_shader.effect->get_parameter("TimeActive").set_float(m_timeActive);
|
||||||
|
}
|
||||||
|
|
||||||
|
gs_load_indexbuffer(nullptr);
|
||||||
|
gs_load_vertexbuffer(m_quadBuffer->update());
|
||||||
|
|
||||||
|
gs_reset_blend_state();
|
||||||
|
gs_enable_depth_test(false);
|
||||||
|
gs_matrix_push();
|
||||||
|
gs_matrix_scale3f(viewW, viewH, 1);
|
||||||
|
while (gs_effect_loop(m_shader.effect->get_object(), "Draw")) {
|
||||||
|
gs_draw(gs_draw_mode::GS_TRISTRIP, 0, 4);
|
||||||
|
}
|
||||||
|
gs_matrix_pop();
|
||||||
|
|
||||||
|
gs_load_indexbuffer(nullptr);
|
||||||
|
gs_load_vertexbuffer(nullptr);
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
#include "gs-effect.h"
|
#include "gs-effect.h"
|
||||||
#include "gs-rendertarget.h"
|
#include "gs-rendertarget.h"
|
||||||
#include "gs-texture.h"
|
#include "gs-texture.h"
|
||||||
|
#include "gs-vertexbuffer.h"
|
||||||
#include "gfx-source-texture.h"
|
#include "gfx-source-texture.h"
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
@ -41,28 +42,11 @@
|
||||||
|
|
||||||
namespace gfx {
|
namespace gfx {
|
||||||
class effect_source {
|
class effect_source {
|
||||||
protected:
|
public:
|
||||||
obs_source_t* m_source;
|
|
||||||
std::unique_ptr<gs::rendertarget> m_renderTarget;
|
|
||||||
|
|
||||||
// Effect Information
|
|
||||||
struct {
|
|
||||||
std::shared_ptr<gs::effect> effect;
|
|
||||||
std::string text;
|
|
||||||
std::string path;
|
|
||||||
struct {
|
|
||||||
float_t time_updated;
|
|
||||||
time_t time_create;
|
|
||||||
time_t time_modified;
|
|
||||||
size_t file_size;
|
|
||||||
bool modified;
|
|
||||||
} file_info;
|
|
||||||
} shader;
|
|
||||||
|
|
||||||
struct parameter {
|
struct parameter {
|
||||||
std::string name = "";
|
std::string name = "";
|
||||||
std::shared_ptr<gs::effect_parameter> param;
|
std::shared_ptr<gs::effect_parameter> param;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
std::vector<char> buffer;
|
std::vector<char> buffer;
|
||||||
std::vector<const char*> names;
|
std::vector<const char*> names;
|
||||||
|
@ -104,26 +88,45 @@ namespace gfx {
|
||||||
} resample;
|
} resample;
|
||||||
};
|
};
|
||||||
struct matrix_parameter : parameter {
|
struct matrix_parameter : parameter {
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
|
};
|
||||||
typedef std::pair<std::string, gs::effect_parameter::type> paramident_t;
|
typedef std::pair<std::string, gs::effect_parameter::type> paramident_t;
|
||||||
std::map<paramident_t, std::shared_ptr<parameter>> parameters;
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
|
||||||
|
protected:
|
||||||
|
obs_source_t* m_source;
|
||||||
|
std::shared_ptr<gs::vertex_buffer> m_quadBuffer;
|
||||||
|
|
||||||
|
// Effect Information
|
||||||
|
struct {
|
||||||
|
std::shared_ptr<gs::effect> effect;
|
||||||
|
std::string text;
|
||||||
|
std::string path;
|
||||||
|
struct {
|
||||||
|
float_t time_updated;
|
||||||
|
time_t time_create;
|
||||||
|
time_t time_modified;
|
||||||
|
size_t file_size;
|
||||||
|
bool modified;
|
||||||
|
} file_info;
|
||||||
|
} m_shader;
|
||||||
|
std::map<paramident_t, std::shared_ptr<parameter>> m_parameters;
|
||||||
|
|
||||||
// Status
|
// Status
|
||||||
float_t time_existing;
|
float_t m_timeExisting;
|
||||||
float_t time_active;
|
float_t m_timeActive;
|
||||||
|
|
||||||
std::string default_shader_path = "shaders/";
|
std::string m_defaultShaderPath = "shaders/";
|
||||||
|
|
||||||
static bool property_type_modified(void* priv, obs_properties_t* props, obs_property_t* prop, obs_data_t* sett);
|
static bool property_type_modified(void* priv, obs_properties_t* props, obs_property_t* prop, obs_data_t* sett);
|
||||||
static bool property_input_modified(void* priv, obs_properties_t* props, obs_property_t* prop, obs_data_t* sett);
|
static bool property_input_modified(void* priv, obs_properties_t* props, obs_property_t* prop, obs_data_t* sett);
|
||||||
|
|
||||||
virtual bool is_special_parameter(std::string name, gs::effect_parameter::type type) = 0;
|
virtual bool is_special_parameter(std::string name, gs::effect_parameter::type type) = 0;
|
||||||
virtual bool apply_special_parameters() = 0;
|
|
||||||
|
|
||||||
virtual void video_tick_impl(float time) = 0;
|
virtual bool video_tick_impl(float_t time) = 0;
|
||||||
virtual void video_render_impl(gs_effect_t* parent_effect) = 0;
|
virtual bool video_render_impl(gs_effect_t* parent_effect, uint32_t viewW, uint32_t viewH) = 0;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
effect_source(obs_data_t* data, obs_source_t* owner);
|
effect_source(obs_data_t* data, obs_source_t* owner);
|
||||||
|
@ -146,6 +149,7 @@ namespace gfx {
|
||||||
void video_tick(float time);
|
void video_tick(float time);
|
||||||
void video_render(gs_effect_t* parent_effect);
|
void video_render(gs_effect_t* parent_effect);
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
enum class InputTypes {
|
enum class InputTypes {
|
||||||
Text,
|
Text,
|
||||||
|
|
Loading…
Reference in a new issue