From 0a7283b2ba87b3b6083b82db4ec797cf84c01b07 Mon Sep 17 00:00:00 2001 From: Michael Fabian 'Xaymar' Dirks Date: Sat, 29 Sep 2018 15:57:25 +0200 Subject: [PATCH] filter-transform: more Formatting, add mipmap options --- data/locale/en-US.ini | 11 ++++ source/filter-transform.cpp | 107 ++++++++++++++++++++++++------------ source/filter-transform.h | 43 ++++++++------- source/strings.h | 24 +++++++- 4 files changed, 128 insertions(+), 57 deletions(-) diff --git a/data/locale/en-US.ini b/data/locale/en-US.ini index b3c5496b..ad71d566 100644 --- a/data/locale/en-US.ini +++ b/data/locale/en-US.ini @@ -1,5 +1,14 @@ # Generic Advanced="Advanced" +MipGenerator="Mipmap Generator" +MipGenerator.Description="Which mip generator should be used?" +MipGenerator.Point="Point" +MipGenerator.Linear="Linear" +MipGenerator.Sharpen="Sharpen" +MipGenerator.Smoothen="Smoothen" +MipGenerator.Bicubic="Bicubic" +MipGenerator.Lanczos="Lanczos" +MipGenerator.Strength="Strength" # Custom Shader CustomShader.Type="Type" @@ -102,6 +111,8 @@ Filter.Transform.Rotation.Description="Euler rotation of the rendered quad, appl Filter.Transform.Rotation.X="Pitch (X)" Filter.Transform.Rotation.Y="Yaw (Y)" Filter.Transform.Rotation.Z="Roll (Z)" +Filter.Transform.Mipmapping="Enable Mipmapping" +Filter.Transform.Mipmapping.Description="Generate mipmaps for the source, so that angled and far away parts are smoother." # Source - Mirror Source.Mirror="Source Mirror" diff --git a/source/filter-transform.cpp b/source/filter-transform.cpp index 9f4e0fb4..ed4853d6 100644 --- a/source/filter-transform.cpp +++ b/source/filter-transform.cpp @@ -64,6 +64,7 @@ INITIALIZER(FilterTransformInit) #define ST_ROTATION_ORDER_YZX "Filter.Transform.Rotation.Order.YZX" #define ST_ROTATION_ORDER_ZXY "Filter.Transform.Rotation.Order.ZXY" #define ST_ROTATION_ORDER_ZYX "Filter.Transform.Rotation.Order.ZYX" +#define ST_MIPMAPPING "Filter.Transform.Mipmapping" static const float farZ = 2097152.0f; // 2 pow 21 static const float nearZ = 1.0f / farZ; @@ -199,6 +200,31 @@ obs_properties_t* Filter::Transform::get_properties(void*) obs_property_list_add_int(p, P_TRANSLATE(ST_ROTATION_ORDER_ZXY), RotationOrder::ZXY); obs_property_list_add_int(p, P_TRANSLATE(ST_ROTATION_ORDER_ZYX), RotationOrder::ZYX); + p = obs_properties_add_bool(pr, ST_MIPMAPPING, P_TRANSLATE(ST_MIPMAPPING)); + obs_property_set_modified_callback(p, modified_properties); + obs_property_set_long_description(p, P_TRANSLATE(P_DESC(ST_MIPMAPPING))); + + p = obs_properties_add_list(pr, plugin::strings::MipGenerator::Name, + P_TRANSLATE(plugin::strings::MipGenerator::Name), OBS_COMBO_TYPE_LIST, + OBS_COMBO_FORMAT_INT); + obs_property_set_long_description(p, P_TRANSLATE(plugin::strings::MipGenerator::Description)); + + obs_property_list_add_int(p, P_TRANSLATE(plugin::strings::MipGenerator::Point), + (long long)gs::mipmapper::generator::Point); + obs_property_list_add_int(p, P_TRANSLATE(plugin::strings::MipGenerator::Linear), + (long long)gs::mipmapper::generator::Linear); + obs_property_list_add_int(p, P_TRANSLATE(plugin::strings::MipGenerator::Sharpen), + (long long)gs::mipmapper::generator::Sharpen); + obs_property_list_add_int(p, P_TRANSLATE(plugin::strings::MipGenerator::Smoothen), + (long long)gs::mipmapper::generator::Smoothen); + obs_property_list_add_int(p, P_TRANSLATE(plugin::strings::MipGenerator::Bicubic), + (long long)gs::mipmapper::generator::Bicubic); + obs_property_list_add_int(p, P_TRANSLATE(plugin::strings::MipGenerator::Lanczos), + (long long)gs::mipmapper::generator::Lanczos); + + p = obs_properties_add_float(pr, plugin::strings::MipGenerator::Strength, + P_TRANSLATE(plugin::strings::MipGenerator::Strength), 0.0, 100.0, 0.01); + return pr; } @@ -217,6 +243,11 @@ bool Filter::Transform::modified_properties(obs_properties_t* pr, obs_property_t bool advancedVisible = obs_data_get_bool(d, S_ADVANCED); obs_property_set_visible(obs_properties_get(pr, ST_ROTATION_ORDER), advancedVisible); + obs_property_set_visible(obs_properties_get(pr, ST_MIPMAPPING), advancedVisible); + + bool mipmappingVisible = obs_data_get_bool(d, ST_MIPMAPPING) && advancedVisible; + obs_property_set_visible(obs_properties_get(pr, plugin::strings::MipGenerator::Name), mipmappingVisible); + obs_property_set_visible(obs_properties_get(pr, plugin::strings::MipGenerator::Strength), mipmappingVisible); return true; } @@ -268,7 +299,7 @@ void Filter::Transform::video_render(void* ptr, gs_effect_t* effect) Filter::Transform::Instance::Instance(obs_data_t* data, obs_source_t* context) : source_context(context), is_orthographic(true), field_of_view(90.0), is_inactive(false), is_hidden(false), - is_mesh_update_required(false), m_rotation_order(RotationOrder::ZXY) + is_mesh_update_required(false), rotation_order(RotationOrder::ZXY) { position = std::make_unique(); rotation = std::make_unique(); @@ -279,6 +310,10 @@ Filter::Transform::Instance::Instance(obs_data_t* data, obs_source_t* context) vec3_set(rotation.get(), 0, 0, 0); vec3_set(scale.get(), 1, 1, 1); + enable_mipmapping = false; + generator = gs::mipmapper::generator::Linear; + generator_strength = 50.0; + obs_enter_graphics(); source_rt = std::make_shared(GS_RGBA, GS_ZS_NONE); shape_rt = std::make_shared(GS_RGBA, GS_ZS_NONE); @@ -304,19 +339,24 @@ void Filter::Transform::Instance::update(obs_data_t* data) field_of_view = (float)obs_data_get_double(data, ST_CAMERA_FIELDOFVIEW); // Source - position->x = (float)obs_data_get_double(data, ST_POSITION_X) / 100.0f; - position->y = (float)obs_data_get_double(data, ST_POSITION_Y) / 100.0f; - position->z = (float)obs_data_get_double(data, ST_POSITION_Z) / 100.0f; - scale->x = (float)obs_data_get_double(data, ST_SCALE_X) / 100.0f; - scale->y = (float)obs_data_get_double(data, ST_SCALE_Y) / 100.0f; - scale->z = 1.0f; - m_rotation_order = (int)obs_data_get_int(data, ST_ROTATION_ORDER); - rotation->x = (float)(obs_data_get_double(data, ST_ROTATION_X) / 180.0f * PI); - rotation->y = (float)(obs_data_get_double(data, ST_ROTATION_Y) / 180.0f * PI); - rotation->z = (float)(obs_data_get_double(data, ST_ROTATION_Z) / 180.0f * PI); - shear->x = (float)obs_data_get_double(data, ST_SHEAR_X) / 100.0f; - shear->y = (float)obs_data_get_double(data, ST_SHEAR_Y) / 100.0f; - shear->z = 0.0f; + position->x = (float)obs_data_get_double(data, ST_POSITION_X) / 100.0f; + position->y = (float)obs_data_get_double(data, ST_POSITION_Y) / 100.0f; + position->z = (float)obs_data_get_double(data, ST_POSITION_Z) / 100.0f; + scale->x = (float)obs_data_get_double(data, ST_SCALE_X) / 100.0f; + scale->y = (float)obs_data_get_double(data, ST_SCALE_Y) / 100.0f; + scale->z = 1.0f; + rotation_order = (int)obs_data_get_int(data, ST_ROTATION_ORDER); + rotation->x = (float)(obs_data_get_double(data, ST_ROTATION_X) / 180.0f * PI); + rotation->y = (float)(obs_data_get_double(data, ST_ROTATION_Y) / 180.0f * PI); + rotation->z = (float)(obs_data_get_double(data, ST_ROTATION_Z) / 180.0f * PI); + shear->x = (float)obs_data_get_double(data, ST_SHEAR_X) / 100.0f; + shear->y = (float)obs_data_get_double(data, ST_SHEAR_Y) / 100.0f; + shear->z = 0.0f; + + // Mipmapping + enable_mipmapping = obs_data_get_bool(data, ST_MIPMAPPING); + generator_strength = obs_data_get_double(data, plugin::strings::MipGenerator::Strength); + generator = (gs::mipmapper::generator)obs_data_get_int(data, plugin::strings::MipGenerator::Name); is_mesh_update_required = true; } @@ -351,7 +391,7 @@ void Filter::Transform::Instance::video_render(gs_effect_t* paramEffect) obs_source_t* parent = obs_filter_get_parent(source_context); obs_source_t* target = obs_filter_get_target(source_context); - uint32_t width = obs_source_get_base_width(target); + uint32_t width = obs_source_get_base_width(target); uint32_t height = obs_source_get_base_height(target); gs_effect_t* default_effect = obs_get_base_effect(OBS_EFFECT_DEFAULT); @@ -371,7 +411,7 @@ void Filter::Transform::Instance::video_render(gs_effect_t* paramEffect) // Mesh matrix4 ident; matrix4_identity(&ident); - switch (m_rotation_order) { + switch (rotation_order) { case RotationOrder::XYZ: // XYZ matrix4_rotate_aa4f(&ident, &ident, 1, 0, 0, rotation->x); matrix4_rotate_aa4f(&ident, &ident, 0, 1, 0, rotation->y); @@ -473,28 +513,26 @@ void Filter::Transform::Instance::video_render(gs_effect_t* paramEffect) } source_rt->get_texture(source_tex); - if ((!source_texture) || (source_texture->get_width() != width) || (source_texture->get_height() != height)) { - size_t mip_levels = 1; - if (util::math::is_power_of_two(width) && util::math::is_power_of_two(height)) { - size_t w_level = util::math::get_power_of_two_floor(width); - size_t h_level = util::math::get_power_of_two_floor(height); - if (h_level < w_level) { - mip_levels = h_level; - } else { - mip_levels = w_level; + if (enable_mipmapping) { + if ((!source_texture) || (source_texture->get_width() != width) || (source_texture->get_height() != height)) { + size_t mip_levels = 1; + if (util::math::is_power_of_two(width) && util::math::is_power_of_two(height)) { + size_t w_level = util::math::get_power_of_two_floor(width); + size_t h_level = util::math::get_power_of_two_floor(height); + if (h_level < w_level) { + mip_levels = h_level; + } else { + mip_levels = w_level; + } } + + source_texture = std::make_shared(width, height, GS_RGBA, mip_levels, nullptr, + gs::texture::flags::BuildMipMaps); } - // OBS does not allow creating an uninitalized texture, which means that we actually have to give it mip_data. - size_t store_size = (width * height * sizeof(uint32_t)); - source_texture_store.resize(store_size * mip_levels); - const uint8_t* data = (uint8_t*)source_texture_store.data(); - source_texture = std::make_shared(width, height, GS_RGBA, mip_levels, nullptr, - gs::texture::flags::BuildMipMaps); + mipmapper.rebuild(source_tex, source_texture, generator, generator_strength); } - mipmapper.rebuild(source_tex, source_texture, gs::mipmapper::generator::Linear, 0.5); - // Draw shape to texture try { auto op = shape_rt->render(width, height); @@ -523,7 +561,8 @@ void Filter::Transform::Instance::video_render(gs_effect_t* paramEffect) gs_load_vertexbuffer(vertex_buffer->update(false)); gs_load_indexbuffer(nullptr); while (gs_effect_loop(default_effect, "Draw")) { - gs_effect_set_texture(gs_effect_get_param_by_name(default_effect, "image"), source_texture->get_object()); + gs_effect_set_texture(gs_effect_get_param_by_name(default_effect, "image"), + enable_mipmapping ? source_texture->get_object() : source_tex->get_object()); gs_draw(GS_TRISTRIP, 0, 4); } gs_load_vertexbuffer(nullptr); diff --git a/source/filter-transform.h b/source/filter-transform.h index 2a98a6ff..f48237db 100644 --- a/source/filter-transform.h +++ b/source/filter-transform.h @@ -28,6 +28,8 @@ namespace Filter { class Transform { + obs_source_info sourceInfo; + public: Transform(); ~Transform(); @@ -49,32 +51,21 @@ namespace Filter { static void video_tick(void*, float); static void video_render(void*, gs_effect_t*); - private: - obs_source_info sourceInfo; - private: class Instance { - public: - Instance(obs_data_t*, obs_source_t*); - ~Instance(); - - void update(obs_data_t*); - uint32_t get_width(); - uint32_t get_height(); - void activate(); - void deactivate(); - void video_tick(float); - void video_render(gs_effect_t*); - - private: obs_source_t* source_context; + // Graphics Data std::shared_ptr vertex_buffer; std::shared_ptr source_rt; std::shared_ptr shape_rt; - std::shared_ptr source_texture; - std::vector source_texture_store; - gs::mipmapper mipmapper; + + // Mipmapping + bool enable_mipmapping; + double_t generator_strength; + gs::mipmapper::generator generator; + std::shared_ptr source_texture; + gs::mipmapper mipmapper; // Camera bool is_orthographic; @@ -86,13 +77,25 @@ namespace Filter { bool is_mesh_update_required; // 3D Information - uint32_t m_rotation_order; + uint32_t rotation_order; struct { std::unique_ptr position; std::unique_ptr rotation; std::unique_ptr scale; std::unique_ptr shear; }; + + public: + Instance(obs_data_t*, obs_source_t*); + ~Instance(); + + void update(obs_data_t*); + uint32_t get_width(); + uint32_t get_height(); + void activate(); + void deactivate(); + void video_tick(float); + void video_render(gs_effect_t*); }; }; } // namespace Filter diff --git a/source/strings.h b/source/strings.h index 2abba287..767ffd15 100644 --- a/source/strings.h +++ b/source/strings.h @@ -20,7 +20,25 @@ #pragma once #include "plugin.h" -#define P_TRANSLATE(x) obs_module_text(x) -#define P_DESC(x) x ".Description" +#define P_TRANSLATE(x) obs_module_text(x) +#define P_DESC(x) x ".Description" -#define S_ADVANCED "Advanced" +#define S_ADVANCED "Advanced" + +namespace plugin { + namespace strings { + static const char* Advanced = "Advanced"; + namespace MipGenerator { + static const char* Name = "MipGenerator"; + static const char* Description = "MipGenerator.Description"; + static const char* Point = "MipGenerator.Point"; + static const char* Linear = "MipGenerator.Linear"; + static const char* Sharpen = "MipGenerator.Sharpen"; + static const char* Smoothen = "MipGenerator.Smoothen"; + static const char* Bicubic = "MipGenerator.Bicubic"; + static const char* Lanczos = "MipGenerator.Lanczos"; + static const char* Strength = "MipGenerator.Strength"; + } // namespace MipGenerator + + } // namespace strings +} // namespace plugin