mirror of https://github.com/Xaymar/obs-StreamFX
filter/transform: Modernize code base for future expansion
This commit is contained in:
parent
a40021b17b
commit
e0c6e55259
|
@ -87,46 +87,50 @@ using namespace streamfx::filter::transform;
|
||||||
|
|
||||||
static constexpr std::string_view HELP_URL = "https://github.com/Xaymar/obs-StreamFX/wiki/Filter-3D-Transform";
|
static constexpr std::string_view HELP_URL = "https://github.com/Xaymar/obs-StreamFX/wiki/Filter-3D-Transform";
|
||||||
|
|
||||||
static const float_t farZ = 2097152.0f; // 2 pow 21
|
static const float farZ = 2097152.0f; // 2 pow 21
|
||||||
static const float_t nearZ = 1.0f / farZ;
|
static const float nearZ = 1.0f / farZ;
|
||||||
|
|
||||||
enum class CameraMode : int64_t { Orthographic, Perspective };
|
|
||||||
|
|
||||||
enum RotationOrder : int64_t {
|
enum RotationOrder : int64_t {
|
||||||
XYZ,
|
XYZ = 0,
|
||||||
XZY,
|
XZY = 1,
|
||||||
YXZ,
|
YXZ = 2,
|
||||||
YZX,
|
YZX = 3,
|
||||||
ZXY,
|
ZXY = 4,
|
||||||
ZYX,
|
ZYX = 5,
|
||||||
};
|
};
|
||||||
|
|
||||||
transform_instance::transform_instance(obs_data_t* data, obs_source_t* context)
|
transform_instance::transform_instance(obs_data_t* data, obs_source_t* context)
|
||||||
: obs::source_instance(data, context), _cache_rendered(), _mipmap_enabled(), _source_rendered(), _source_size(),
|
: obs::source_instance(data, context), _camera_mode(), _camera_fov(), _standard_effect(), _sampler(), _params(),
|
||||||
_update_mesh(), _rotation_order(), _camera_orthographic(), _camera_fov()
|
_cache_rendered(), _mipmap_enabled(), _source_rendered(), _source_size(), _update_mesh(true)
|
||||||
{
|
{
|
||||||
_cache_rt = std::make_shared<streamfx::obs::gs::rendertarget>(GS_RGBA, GS_ZS_NONE);
|
_cache_rt = std::make_shared<streamfx::obs::gs::rendertarget>(GS_RGBA, GS_ZS_NONE);
|
||||||
_source_rt = std::make_shared<streamfx::obs::gs::rendertarget>(GS_RGBA, GS_ZS_NONE);
|
_source_rt = std::make_shared<streamfx::obs::gs::rendertarget>(GS_RGBA, GS_ZS_NONE);
|
||||||
_vertex_buffer = std::make_shared<streamfx::obs::gs::vertex_buffer>(uint32_t(4u), uint8_t(1u));
|
_vertex_buffer = std::make_shared<streamfx::obs::gs::vertex_buffer>(uint32_t(4u), uint8_t(1u));
|
||||||
|
{
|
||||||
|
auto file = streamfx::data_file_path("effects/standard.effect");
|
||||||
|
try {
|
||||||
|
_standard_effect = streamfx::obs::gs::effect::create(file.generic_u8string());
|
||||||
|
} catch (const std::exception& ex) {
|
||||||
|
DLOG_ERROR("Error loading '%s' from disk: %s", file.generic_u8string().c_str(), ex.what());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{
|
||||||
|
_sampler.set_address_mode_u(GS_ADDRESS_CLAMP);
|
||||||
|
_sampler.set_address_mode_v(GS_ADDRESS_CLAMP);
|
||||||
|
_sampler.set_address_mode_w(GS_ADDRESS_CLAMP);
|
||||||
|
_sampler.set_filter(GS_FILTER_LINEAR);
|
||||||
|
}
|
||||||
|
|
||||||
_position = std::make_unique<streamfx::util::vec3a>();
|
vec3_set(&_params.position, 0, 0, 0);
|
||||||
_rotation = std::make_unique<streamfx::util::vec3a>();
|
vec3_set(&_params.rotation, 0, 0, 0);
|
||||||
_scale = std::make_unique<streamfx::util::vec3a>();
|
vec3_set(&_params.scale, 1, 1, 1);
|
||||||
_shear = std::make_unique<streamfx::util::vec3a>();
|
vec3_set(&_params.shear, 0, 0, 0);
|
||||||
|
|
||||||
vec3_set(_position.get(), 0, 0, 0);
|
|
||||||
vec3_set(_rotation.get(), 0, 0, 0);
|
|
||||||
vec3_set(_scale.get(), 1, 1, 1);
|
|
||||||
|
|
||||||
update(data);
|
update(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
transform_instance::~transform_instance()
|
transform_instance::~transform_instance()
|
||||||
{
|
{
|
||||||
_shear.reset();
|
|
||||||
_scale.reset();
|
|
||||||
_rotation.reset();
|
|
||||||
_position.reset();
|
|
||||||
_vertex_buffer.reset();
|
_vertex_buffer.reset();
|
||||||
_cache_rt.reset();
|
_cache_rt.reset();
|
||||||
_cache_texture.reset();
|
_cache_texture.reset();
|
||||||
|
@ -179,7 +183,7 @@ void transform_instance::migrate(obs_data_t* settings, uint64_t version)
|
||||||
COPY_UNSET(double, ST_KEY_MIPMAPPING, "Filter.Transform.Mipmapping");
|
COPY_UNSET(double, ST_KEY_MIPMAPPING, "Filter.Transform.Mipmapping");
|
||||||
|
|
||||||
if (!obs_data_has_user_value(settings, ST_KEY_CAMERA_MODE)) {
|
if (!obs_data_has_user_value(settings, ST_KEY_CAMERA_MODE)) {
|
||||||
SET_IF_UNSET(int, ST_KEY_CAMERA_MODE, static_cast<int>(CameraMode::Orthographic));
|
SET_IF_UNSET(int, ST_KEY_CAMERA_MODE, static_cast<int>(transform_mode::ORTHOGRAPHIC));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -191,23 +195,24 @@ void transform_instance::migrate(obs_data_t* settings, uint64_t version)
|
||||||
void transform_instance::update(obs_data_t* settings)
|
void transform_instance::update(obs_data_t* settings)
|
||||||
{
|
{
|
||||||
// Camera
|
// Camera
|
||||||
_camera_orthographic = obs_data_get_int(settings, ST_KEY_CAMERA_MODE) == 0;
|
_camera_mode = static_cast<transform_mode>(obs_data_get_int(settings, ST_KEY_CAMERA_MODE));
|
||||||
_camera_fov = static_cast<float_t>(obs_data_get_double(settings, ST_KEY_CAMERA_FIELDOFVIEW));
|
_camera_fov = static_cast<float>(obs_data_get_double(settings, ST_KEY_CAMERA_FIELDOFVIEW));
|
||||||
|
|
||||||
// Source
|
{ // Parametrized Mesh
|
||||||
_position->x = static_cast<float_t>(obs_data_get_double(settings, ST_KEY_POSITION_X) / 100.0);
|
_params.position.x = static_cast<float>(obs_data_get_double(settings, ST_KEY_POSITION_X) / 100.0);
|
||||||
_position->y = static_cast<float_t>(obs_data_get_double(settings, ST_KEY_POSITION_Y) / 100.0);
|
_params.position.y = static_cast<float>(obs_data_get_double(settings, ST_KEY_POSITION_Y) / 100.0);
|
||||||
_position->z = static_cast<float_t>(obs_data_get_double(settings, ST_KEY_POSITION_Z) / 100.0);
|
_params.position.z = static_cast<float>(obs_data_get_double(settings, ST_KEY_POSITION_Z) / 100.0);
|
||||||
_scale->x = static_cast<float_t>(obs_data_get_double(settings, ST_KEY_SCALE_X) / 100.0);
|
_params.scale.x = static_cast<float>(obs_data_get_double(settings, ST_KEY_SCALE_X) / 100.0);
|
||||||
_scale->y = static_cast<float_t>(obs_data_get_double(settings, ST_KEY_SCALE_Y) / 100.0);
|
_params.scale.y = static_cast<float>(obs_data_get_double(settings, ST_KEY_SCALE_Y) / 100.0);
|
||||||
_scale->z = 1.0f;
|
_params.scale.z = 1.0f;
|
||||||
_rotation_order = static_cast<uint32_t>(obs_data_get_int(settings, ST_KEY_ROTATION_ORDER));
|
_params.rotation_order = static_cast<uint32_t>(obs_data_get_int(settings, ST_KEY_ROTATION_ORDER));
|
||||||
_rotation->x = static_cast<float_t>(obs_data_get_double(settings, ST_KEY_ROTATION_X) / 180.0 * S_PI);
|
_params.rotation.x = static_cast<float>(obs_data_get_double(settings, ST_KEY_ROTATION_X) / 180.0 * S_PI);
|
||||||
_rotation->y = static_cast<float_t>(obs_data_get_double(settings, ST_KEY_ROTATION_Y) / 180.0 * S_PI);
|
_params.rotation.y = static_cast<float>(obs_data_get_double(settings, ST_KEY_ROTATION_Y) / 180.0 * S_PI);
|
||||||
_rotation->z = static_cast<float_t>(obs_data_get_double(settings, ST_KEY_ROTATION_Z) / 180.0 * S_PI);
|
_params.rotation.z = static_cast<float>(obs_data_get_double(settings, ST_KEY_ROTATION_Z) / 180.0 * S_PI);
|
||||||
_shear->x = static_cast<float_t>(obs_data_get_double(settings, ST_KEY_SHEAR_X) / 100.0);
|
_params.shear.x = static_cast<float>(obs_data_get_double(settings, ST_KEY_SHEAR_X) / 100.0);
|
||||||
_shear->y = static_cast<float_t>(obs_data_get_double(settings, ST_KEY_SHEAR_Y) / 100.0);
|
_params.shear.y = static_cast<float>(obs_data_get_double(settings, ST_KEY_SHEAR_Y) / 100.0);
|
||||||
_shear->z = 0.0f;
|
_params.shear.z = 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
// Mip-mapping
|
// Mip-mapping
|
||||||
_mipmap_enabled = obs_data_get_bool(settings, ST_KEY_MIPMAPPING);
|
_mipmap_enabled = obs_data_get_bool(settings, ST_KEY_MIPMAPPING);
|
||||||
|
@ -215,7 +220,7 @@ void transform_instance::update(obs_data_t* settings)
|
||||||
_update_mesh = true;
|
_update_mesh = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void transform_instance::video_tick(float_t)
|
void transform_instance::video_tick(float)
|
||||||
{
|
{
|
||||||
uint32_t width = 0;
|
uint32_t width = 0;
|
||||||
uint32_t height = 0;
|
uint32_t height = 0;
|
||||||
|
@ -248,79 +253,80 @@ void transform_instance::video_tick(float_t)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculate Aspect Ratio
|
// Calculate Aspect Ratio
|
||||||
float_t aspectRatioX = float_t(width) / float_t(height);
|
float aspect_ratio_x = float(width) / float(height);
|
||||||
if (_camera_orthographic)
|
|
||||||
aspectRatioX = 1.0;
|
if (_camera_mode == transform_mode::ORTHOGRAPHIC)
|
||||||
|
aspect_ratio_x = 1.0;
|
||||||
|
|
||||||
// Mesh
|
// Mesh
|
||||||
matrix4 ident;
|
matrix4 ident;
|
||||||
matrix4_identity(&ident);
|
matrix4_identity(&ident);
|
||||||
switch (_rotation_order) {
|
switch (_params.rotation_order) {
|
||||||
case RotationOrder::XYZ: // XYZ
|
case RotationOrder::XYZ: // XYZ
|
||||||
matrix4_rotate_aa4f(&ident, &ident, 1, 0, 0, _rotation->x);
|
matrix4_rotate_aa4f(&ident, &ident, 1, 0, 0, _params.rotation.x);
|
||||||
matrix4_rotate_aa4f(&ident, &ident, 0, 1, 0, _rotation->y);
|
matrix4_rotate_aa4f(&ident, &ident, 0, 1, 0, _params.rotation.y);
|
||||||
matrix4_rotate_aa4f(&ident, &ident, 0, 0, 1, _rotation->z);
|
matrix4_rotate_aa4f(&ident, &ident, 0, 0, 1, _params.rotation.z);
|
||||||
break;
|
break;
|
||||||
case RotationOrder::XZY: // XZY
|
case RotationOrder::XZY: // XZY
|
||||||
matrix4_rotate_aa4f(&ident, &ident, 1, 0, 0, _rotation->x);
|
matrix4_rotate_aa4f(&ident, &ident, 1, 0, 0, _params.rotation.x);
|
||||||
matrix4_rotate_aa4f(&ident, &ident, 0, 0, 1, _rotation->z);
|
matrix4_rotate_aa4f(&ident, &ident, 0, 0, 1, _params.rotation.z);
|
||||||
matrix4_rotate_aa4f(&ident, &ident, 0, 1, 0, _rotation->y);
|
matrix4_rotate_aa4f(&ident, &ident, 0, 1, 0, _params.rotation.y);
|
||||||
break;
|
break;
|
||||||
case RotationOrder::YXZ: // YXZ
|
case RotationOrder::YXZ: // YXZ
|
||||||
matrix4_rotate_aa4f(&ident, &ident, 0, 1, 0, _rotation->y);
|
matrix4_rotate_aa4f(&ident, &ident, 0, 1, 0, _params.rotation.y);
|
||||||
matrix4_rotate_aa4f(&ident, &ident, 1, 0, 0, _rotation->x);
|
matrix4_rotate_aa4f(&ident, &ident, 1, 0, 0, _params.rotation.x);
|
||||||
matrix4_rotate_aa4f(&ident, &ident, 0, 0, 1, _rotation->z);
|
matrix4_rotate_aa4f(&ident, &ident, 0, 0, 1, _params.rotation.z);
|
||||||
break;
|
break;
|
||||||
case RotationOrder::YZX: // YZX
|
case RotationOrder::YZX: // YZX
|
||||||
matrix4_rotate_aa4f(&ident, &ident, 0, 1, 0, _rotation->y);
|
matrix4_rotate_aa4f(&ident, &ident, 0, 1, 0, _params.rotation.y);
|
||||||
matrix4_rotate_aa4f(&ident, &ident, 0, 0, 1, _rotation->z);
|
matrix4_rotate_aa4f(&ident, &ident, 0, 0, 1, _params.rotation.z);
|
||||||
matrix4_rotate_aa4f(&ident, &ident, 1, 0, 0, _rotation->x);
|
matrix4_rotate_aa4f(&ident, &ident, 1, 0, 0, _params.rotation.x);
|
||||||
break;
|
break;
|
||||||
case RotationOrder::ZXY: // ZXY
|
case RotationOrder::ZXY: // ZXY
|
||||||
matrix4_rotate_aa4f(&ident, &ident, 0, 0, 1, _rotation->z);
|
matrix4_rotate_aa4f(&ident, &ident, 0, 0, 1, _params.rotation.z);
|
||||||
matrix4_rotate_aa4f(&ident, &ident, 1, 0, 0, _rotation->x);
|
matrix4_rotate_aa4f(&ident, &ident, 1, 0, 0, _params.rotation.x);
|
||||||
matrix4_rotate_aa4f(&ident, &ident, 0, 1, 0, _rotation->y);
|
matrix4_rotate_aa4f(&ident, &ident, 0, 1, 0, _params.rotation.y);
|
||||||
break;
|
break;
|
||||||
case RotationOrder::ZYX: // ZYX
|
case RotationOrder::ZYX: // ZYX
|
||||||
matrix4_rotate_aa4f(&ident, &ident, 0, 0, 1, _rotation->z);
|
matrix4_rotate_aa4f(&ident, &ident, 0, 0, 1, _params.rotation.z);
|
||||||
matrix4_rotate_aa4f(&ident, &ident, 0, 1, 0, _rotation->y);
|
matrix4_rotate_aa4f(&ident, &ident, 0, 1, 0, _params.rotation.y);
|
||||||
matrix4_rotate_aa4f(&ident, &ident, 1, 0, 0, _rotation->x);
|
matrix4_rotate_aa4f(&ident, &ident, 1, 0, 0, _params.rotation.x);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
matrix4_translate3f(&ident, &ident, _position->x, _position->y, _position->z);
|
matrix4_translate3f(&ident, &ident, _params.position.x, _params.position.y, _params.position.z);
|
||||||
//matrix4_scale3f(&ident, &ident, _source_size.first / 2.f, _source_size.second / 2.f, 1.f);
|
//matrix4_scale3f(&ident, &ident, _source_size.first / 2.f, _source_size.second / 2.f, 1.f);
|
||||||
|
|
||||||
/// Calculate vertex position once only.
|
/// Calculate vertex position once only.
|
||||||
float_t p_x = aspectRatioX * _scale->x;
|
float p_x = aspect_ratio_x * _params.scale.x;
|
||||||
float_t p_y = 1.0f * _scale->y;
|
float p_y = 1.0f * _params.scale.y;
|
||||||
|
|
||||||
/// Generate mesh
|
/// Generate mesh
|
||||||
{
|
{
|
||||||
auto vtx = _vertex_buffer->at(0);
|
auto vtx = _vertex_buffer->at(0);
|
||||||
*vtx.color = 0xFFFFFFFF;
|
*vtx.color = 0xFFFFFFFF;
|
||||||
vec4_set(vtx.uv[0], 0, 0, 0, 0);
|
vec4_set(vtx.uv[0], 0, 0, 0, 0);
|
||||||
vec3_set(vtx.position, -p_x + _shear->x, -p_y - _shear->y, 0);
|
vec3_set(vtx.position, -p_x + _params.shear.x, -p_y - _params.shear.y, 0);
|
||||||
vec3_transform(vtx.position, vtx.position, &ident);
|
vec3_transform(vtx.position, vtx.position, &ident);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
auto vtx = _vertex_buffer->at(1);
|
auto vtx = _vertex_buffer->at(1);
|
||||||
*vtx.color = 0xFFFFFFFF;
|
*vtx.color = 0xFFFFFFFF;
|
||||||
vec4_set(vtx.uv[0], 1, 0, 0, 0);
|
vec4_set(vtx.uv[0], 1, 0, 0, 0);
|
||||||
vec3_set(vtx.position, p_x + _shear->x, -p_y + _shear->y, 0);
|
vec3_set(vtx.position, p_x + _params.shear.x, -p_y + _params.shear.y, 0);
|
||||||
vec3_transform(vtx.position, vtx.position, &ident);
|
vec3_transform(vtx.position, vtx.position, &ident);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
auto vtx = _vertex_buffer->at(2);
|
auto vtx = _vertex_buffer->at(2);
|
||||||
*vtx.color = 0xFFFFFFFF;
|
*vtx.color = 0xFFFFFFFF;
|
||||||
vec4_set(vtx.uv[0], 0, 1, 0, 0);
|
vec4_set(vtx.uv[0], 0, 1, 0, 0);
|
||||||
vec3_set(vtx.position, -p_x - _shear->x, p_y - _shear->y, 0);
|
vec3_set(vtx.position, -p_x - _params.shear.x, p_y - _params.shear.y, 0);
|
||||||
vec3_transform(vtx.position, vtx.position, &ident);
|
vec3_transform(vtx.position, vtx.position, &ident);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
auto vtx = _vertex_buffer->at(3);
|
auto vtx = _vertex_buffer->at(3);
|
||||||
*vtx.color = 0xFFFFFFFF;
|
*vtx.color = 0xFFFFFFFF;
|
||||||
vec4_set(vtx.uv[0], 1, 1, 0, 0);
|
vec4_set(vtx.uv[0], 1, 1, 0, 0);
|
||||||
vec3_set(vtx.position, p_x - _shear->x, p_y + _shear->y, 0);
|
vec3_set(vtx.position, p_x - _params.shear.x, p_y + _params.shear.y, 0);
|
||||||
vec3_transform(vtx.position, vtx.position, &ident);
|
vec3_transform(vtx.position, vtx.position, &ident);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -343,7 +349,7 @@ void transform_instance::video_render(gs_effect_t* effect)
|
||||||
if (!effect)
|
if (!effect)
|
||||||
effect = default_effect;
|
effect = default_effect;
|
||||||
|
|
||||||
if (!base_width || !base_height || !parent || !target) { // Skip if something is wrong.
|
if (!base_width || !base_height || !parent || !target || !_standard_effect) { // Skip if something is wrong.
|
||||||
obs_source_skip_video_filter(_self);
|
obs_source_skip_video_filter(_self);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -382,7 +388,7 @@ void transform_instance::video_render(gs_effect_t* effect)
|
||||||
|
|
||||||
auto op = _cache_rt->render(cache_width, cache_height);
|
auto op = _cache_rt->render(cache_width, cache_height);
|
||||||
|
|
||||||
gs_ortho(0, static_cast<float_t>(base_width), 0, static_cast<float_t>(base_height), -1, 1);
|
gs_ortho(0, static_cast<float>(base_width), 0, static_cast<float>(base_height), -1, 1);
|
||||||
|
|
||||||
vec4 clear_color = {0, 0, 0, 0};
|
vec4 clear_color = {0, 0, 0, 0};
|
||||||
gs_clear(GS_CLEAR_COLOR | GS_CLEAR_DEPTH, &clear_color, 0, 0);
|
gs_clear(GS_CLEAR_COLOR | GS_CLEAR_DEPTH, &clear_color, 0, 0);
|
||||||
|
@ -448,6 +454,9 @@ void transform_instance::video_render(gs_effect_t* effect)
|
||||||
|
|
||||||
auto op = _source_rt->render(base_width, base_height);
|
auto op = _source_rt->render(base_width, base_height);
|
||||||
|
|
||||||
|
vec4 clear_color = {0, 0, 0, 0};
|
||||||
|
gs_clear(GS_CLEAR_COLOR | GS_CLEAR_DEPTH, &clear_color, 0, 0);
|
||||||
|
|
||||||
gs_blend_state_push();
|
gs_blend_state_push();
|
||||||
gs_reset_blend_state();
|
gs_reset_blend_state();
|
||||||
gs_enable_blending(false);
|
gs_enable_blending(false);
|
||||||
|
@ -459,25 +468,28 @@ void transform_instance::video_render(gs_effect_t* effect)
|
||||||
gs_enable_color(true, true, true, true);
|
gs_enable_color(true, true, true, true);
|
||||||
gs_set_cull_mode(GS_NEITHER);
|
gs_set_cull_mode(GS_NEITHER);
|
||||||
|
|
||||||
if (_camera_orthographic) {
|
switch (_camera_mode) {
|
||||||
|
case transform_mode::ORTHOGRAPHIC:
|
||||||
gs_ortho(-1., 1., -1., 1., -farZ, farZ);
|
gs_ortho(-1., 1., -1., 1., -farZ, farZ);
|
||||||
} else {
|
break;
|
||||||
gs_perspective(_camera_fov, float_t(base_width) / float_t(base_height), nearZ, farZ);
|
case transform_mode::PERSPECTIVE:
|
||||||
|
gs_perspective(_camera_fov, float(base_width) / float(base_height), nearZ, farZ);
|
||||||
gs_matrix_scale3f(1.0, 1.0, 1.0);
|
gs_matrix_scale3f(1.0, 1.0, 1.0);
|
||||||
gs_matrix_translate3f(0., 0., -1.0);
|
gs_matrix_translate3f(0., 0., -1.0);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
vec4 clear_color = {0, 0, 0, 0};
|
|
||||||
gs_clear(GS_CLEAR_COLOR | GS_CLEAR_DEPTH, &clear_color, 0, 0);
|
|
||||||
|
|
||||||
gs_load_vertexbuffer(_vertex_buffer->update(false));
|
gs_load_vertexbuffer(_vertex_buffer->update(false));
|
||||||
gs_load_indexbuffer(nullptr);
|
gs_load_indexbuffer(nullptr);
|
||||||
gs_effect_set_texture(gs_effect_get_param_by_name(default_effect, "image"),
|
if (auto v = _standard_effect.get_parameter("InputA");
|
||||||
_mipmap_enabled
|
v.get_type() == ::streamfx::obs::gs::effect_parameter::type::Texture) {
|
||||||
? (_mipmap_texture ? _mipmap_texture->get_object() : _cache_texture->get_object())
|
v.set_texture(_mipmap_enabled
|
||||||
: _cache_texture->get_object());
|
? (_mipmap_texture ? _mipmap_texture->get_object() : _cache_texture->get_object())
|
||||||
while (gs_effect_loop(default_effect, "Draw")) {
|
: _cache_texture->get_object());
|
||||||
gs_draw(GS_TRISTRIP, 0, 4);
|
v.set_sampler(_sampler.get_object());
|
||||||
|
}
|
||||||
|
while (gs_effect_loop(_standard_effect.get_object(), "Draw")) {
|
||||||
|
gs_draw(GS_TRISTRIP, 0, _vertex_buffer->size());
|
||||||
}
|
}
|
||||||
gs_load_vertexbuffer(nullptr);
|
gs_load_vertexbuffer(nullptr);
|
||||||
|
|
||||||
|
@ -521,7 +533,7 @@ const char* transform_factory::get_name()
|
||||||
|
|
||||||
void transform_factory::get_defaults2(obs_data_t* settings)
|
void transform_factory::get_defaults2(obs_data_t* settings)
|
||||||
{
|
{
|
||||||
obs_data_set_default_int(settings, ST_KEY_CAMERA_MODE, static_cast<int64_t>(CameraMode::Orthographic));
|
obs_data_set_default_int(settings, ST_KEY_CAMERA_MODE, static_cast<int64_t>(transform_mode::ORTHOGRAPHIC));
|
||||||
obs_data_set_default_double(settings, ST_KEY_CAMERA_FIELDOFVIEW, 90.0);
|
obs_data_set_default_double(settings, ST_KEY_CAMERA_FIELDOFVIEW, 90.0);
|
||||||
obs_data_set_default_double(settings, ST_KEY_POSITION_X, 0);
|
obs_data_set_default_double(settings, ST_KEY_POSITION_X, 0);
|
||||||
obs_data_set_default_double(settings, ST_KEY_POSITION_Y, 0);
|
obs_data_set_default_double(settings, ST_KEY_POSITION_Y, 0);
|
||||||
|
@ -539,10 +551,10 @@ void transform_factory::get_defaults2(obs_data_t* settings)
|
||||||
|
|
||||||
static bool modified_camera_mode(obs_properties_t* pr, obs_property_t*, obs_data_t* d) noexcept
|
static bool modified_camera_mode(obs_properties_t* pr, obs_property_t*, obs_data_t* d) noexcept
|
||||||
try {
|
try {
|
||||||
auto mode = static_cast<CameraMode>(obs_data_get_int(d, ST_KEY_CAMERA_MODE));
|
auto mode = static_cast<transform_mode>(obs_data_get_int(d, ST_KEY_CAMERA_MODE));
|
||||||
bool is_camera = true;
|
bool is_camera = true;
|
||||||
bool is_perspective = (mode == CameraMode::Perspective) && is_camera;
|
bool is_perspective = (mode == transform_mode::PERSPECTIVE) && is_camera;
|
||||||
bool is_orthographic = (mode == CameraMode::Orthographic) && is_camera;
|
bool is_orthographic = (mode == transform_mode::ORTHOGRAPHIC) && is_camera;
|
||||||
|
|
||||||
obs_property_set_visible(obs_properties_get(pr, ST_KEY_CAMERA_FIELDOFVIEW), is_perspective);
|
obs_property_set_visible(obs_properties_get(pr, ST_KEY_CAMERA_FIELDOFVIEW), is_perspective);
|
||||||
obs_property_set_visible(obs_properties_get(pr, ST_I18N_POSITION), is_camera);
|
obs_property_set_visible(obs_properties_get(pr, ST_I18N_POSITION), is_camera);
|
||||||
|
@ -580,9 +592,9 @@ obs_properties_t* transform_factory::get_properties2(transform_instance* data)
|
||||||
auto p = obs_properties_add_list(grp, ST_KEY_CAMERA_MODE, D_TRANSLATE(ST_I18N_CAMERA_MODE),
|
auto p = obs_properties_add_list(grp, ST_KEY_CAMERA_MODE, D_TRANSLATE(ST_I18N_CAMERA_MODE),
|
||||||
OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT);
|
OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT);
|
||||||
obs_property_list_add_int(p, D_TRANSLATE(ST_I18N_CAMERA_MODE_ORTHOGRAPHIC),
|
obs_property_list_add_int(p, D_TRANSLATE(ST_I18N_CAMERA_MODE_ORTHOGRAPHIC),
|
||||||
static_cast<int64_t>(CameraMode::Orthographic));
|
static_cast<int64_t>(transform_mode::ORTHOGRAPHIC));
|
||||||
obs_property_list_add_int(p, D_TRANSLATE(ST_I18N_CAMERA_MODE_PERSPECTIVE),
|
obs_property_list_add_int(p, D_TRANSLATE(ST_I18N_CAMERA_MODE_PERSPECTIVE),
|
||||||
static_cast<int64_t>(CameraMode::Perspective));
|
static_cast<int64_t>(transform_mode::PERSPECTIVE));
|
||||||
obs_property_set_modified_callback(p, modified_camera_mode);
|
obs_property_set_modified_callback(p, modified_camera_mode);
|
||||||
}
|
}
|
||||||
{ // Field Of View
|
{ // Field Of View
|
||||||
|
@ -606,8 +618,8 @@ obs_properties_t* transform_factory::get_properties2(transform_instance* data)
|
||||||
};
|
};
|
||||||
for (auto opt : opts) {
|
for (auto opt : opts) {
|
||||||
auto p = obs_properties_add_float(grp, opt.first.c_str(), D_TRANSLATE(opt.second.c_str()),
|
auto p = obs_properties_add_float(grp, opt.first.c_str(), D_TRANSLATE(opt.second.c_str()),
|
||||||
std::numeric_limits<float_t>::lowest(),
|
std::numeric_limits<float>::lowest(),
|
||||||
std::numeric_limits<float_t>::max(), 0.01);
|
std::numeric_limits<float>::max(), 0.01);
|
||||||
}
|
}
|
||||||
|
|
||||||
obs_properties_add_group(pr, ST_I18N_POSITION, D_TRANSLATE(ST_I18N_POSITION), OBS_GROUP_NORMAL, grp);
|
obs_properties_add_group(pr, ST_I18N_POSITION, D_TRANSLATE(ST_I18N_POSITION), OBS_GROUP_NORMAL, grp);
|
||||||
|
|
|
@ -27,7 +27,27 @@
|
||||||
#include "obs/obs-source-factory.hpp"
|
#include "obs/obs-source-factory.hpp"
|
||||||
|
|
||||||
namespace streamfx::filter::transform {
|
namespace streamfx::filter::transform {
|
||||||
|
enum class transform_mode {
|
||||||
|
ORTHOGRAPHIC = 0,
|
||||||
|
PERSPECTIVE = 1,
|
||||||
|
};
|
||||||
|
|
||||||
class transform_instance : public obs::source_instance {
|
class transform_instance : public obs::source_instance {
|
||||||
|
// Settings
|
||||||
|
transform_mode _camera_mode;
|
||||||
|
float _camera_fov;
|
||||||
|
struct {
|
||||||
|
vec3 position;
|
||||||
|
vec3 rotation;
|
||||||
|
uint32_t rotation_order;
|
||||||
|
vec3 scale;
|
||||||
|
vec3 shear;
|
||||||
|
} _params;
|
||||||
|
|
||||||
|
// Data
|
||||||
|
streamfx::obs::gs::effect _standard_effect;
|
||||||
|
streamfx::obs::gs::sampler _sampler;
|
||||||
|
|
||||||
// Cache
|
// Cache
|
||||||
bool _cache_rendered;
|
bool _cache_rendered;
|
||||||
std::shared_ptr<streamfx::obs::gs::rendertarget> _cache_rt;
|
std::shared_ptr<streamfx::obs::gs::rendertarget> _cache_rt;
|
||||||
|
@ -48,15 +68,6 @@ namespace streamfx::filter::transform {
|
||||||
// Mesh
|
// Mesh
|
||||||
bool _update_mesh;
|
bool _update_mesh;
|
||||||
std::shared_ptr<streamfx::obs::gs::vertex_buffer> _vertex_buffer;
|
std::shared_ptr<streamfx::obs::gs::vertex_buffer> _vertex_buffer;
|
||||||
uint32_t _rotation_order;
|
|
||||||
std::unique_ptr<streamfx::util::vec3a> _position;
|
|
||||||
std::unique_ptr<streamfx::util::vec3a> _rotation;
|
|
||||||
std::unique_ptr<streamfx::util::vec3a> _scale;
|
|
||||||
std::unique_ptr<streamfx::util::vec3a> _shear;
|
|
||||||
|
|
||||||
// Camera
|
|
||||||
bool _camera_orthographic;
|
|
||||||
float_t _camera_fov;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
transform_instance(obs_data_t*, obs_source_t*);
|
transform_instance(obs_data_t*, obs_source_t*);
|
||||||
|
@ -66,7 +77,7 @@ namespace streamfx::filter::transform {
|
||||||
virtual void migrate(obs_data_t* data, uint64_t version) override;
|
virtual void migrate(obs_data_t* data, uint64_t version) override;
|
||||||
virtual void update(obs_data_t*) override;
|
virtual void update(obs_data_t*) override;
|
||||||
|
|
||||||
virtual void video_tick(float_t) override;
|
virtual void video_tick(float) override;
|
||||||
virtual void video_render(gs_effect_t*) override;
|
virtual void video_render(gs_effect_t*) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue