mirror of
https://github.com/Xaymar/obs-StreamFX
synced 2024-11-30 23:33:02 +00:00
color-grade: Add further Tint options
This commit is contained in:
parent
3f77c32de5
commit
781307fbe6
3 changed files with 247 additions and 75 deletions
|
@ -5,11 +5,27 @@ uniform float4 pLift;
|
||||||
uniform float4 pGamma;
|
uniform float4 pGamma;
|
||||||
uniform float4 pGain;
|
uniform float4 pGain;
|
||||||
uniform float4 pOffset;
|
uniform float4 pOffset;
|
||||||
|
uniform int pTintDetection; // 0 = HSV, 1 = HSL, 2 = YUV HD SDR
|
||||||
|
uniform int pTintMode; // 0 = Linear, 1 = Exp, 2 = Exp2, 3 = Log, 4 = Log10
|
||||||
|
uniform float pTintLumaExponent;
|
||||||
uniform float3 pTintLow;
|
uniform float3 pTintLow;
|
||||||
uniform float3 pTintMid;
|
uniform float3 pTintMid;
|
||||||
uniform float3 pTintHig;
|
uniform float3 pTintHig;
|
||||||
uniform float4 pCorrection;
|
uniform float4 pCorrection;
|
||||||
|
|
||||||
|
#define TINT_DETECTION_HSV 0
|
||||||
|
#define TINT_DETECTION_HSL 1
|
||||||
|
#define TINT_DETECTION_YUV_SDR 2
|
||||||
|
|
||||||
|
#define TINT_MODE_LINEAR 0
|
||||||
|
#define TINT_MODE_EXP 1
|
||||||
|
#define TINT_MODE_EXP2 2
|
||||||
|
#define TINT_MODE_LOG 3
|
||||||
|
#define TINT_MODE_LOG10 4
|
||||||
|
|
||||||
|
#define C_e 2,7182818284590452353602874713527
|
||||||
|
#define C_log2_e 1.4426950408889634073599246810019 // Windows calculator: log(e(1)) / log(2)
|
||||||
|
|
||||||
// Data
|
// Data
|
||||||
sampler_state def_sampler {
|
sampler_state def_sampler {
|
||||||
Filter = Point;
|
Filter = Point;
|
||||||
|
@ -37,6 +53,90 @@ VertDataOut VSDefault(VertDataIn v)
|
||||||
return ov;
|
return ov;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Utility functions -----------------------------------------------------------
|
||||||
|
float4 RGBtoYUV(float4 rgba, float3x3 yuv) {
|
||||||
|
return float4(
|
||||||
|
rgba.r * yuv._m00 + rgba.g * yuv._m01 + rgba.b * yuv._m02,
|
||||||
|
rgba.r * yuv._m10 + rgba.g * yuv._m11 + rgba.b * yuv._m12,
|
||||||
|
rgba.r * yuv._m20 + rgba.g * yuv._m21 + rgba.b * yuv._m22,
|
||||||
|
rgba.a
|
||||||
|
) + float4(0,0.5,0.5,0);
|
||||||
|
}
|
||||||
|
|
||||||
|
float4 YUVtoRGB(float4 yuva, float3x3 yuvi) {
|
||||||
|
yuva.gb -= 0.5;
|
||||||
|
return float4(
|
||||||
|
yuva.r * yuvi._m00 + yuva.g * yuvi._m01 + yuva.b * yuvi._m02,
|
||||||
|
yuva.r * yuvi._m10 + yuva.g * yuvi._m11 + yuva.b * yuvi._m12,
|
||||||
|
yuva.r * yuvi._m20 + yuva.g * yuvi._m21 + yuva.b * yuvi._m22,
|
||||||
|
yuva.a);
|
||||||
|
}
|
||||||
|
|
||||||
|
float4 RGBtoHSV(float4 RGBA) {
|
||||||
|
const float4 K = float4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
|
||||||
|
const float e = 1.0e-10;
|
||||||
|
float4 p = lerp(float4(RGBA.bg, K.wz), float4(RGBA.gb, K.xy), step(RGBA.b, RGBA.g));
|
||||||
|
float4 q = lerp(float4(p.xyw, RGBA.r), float4(RGBA.r, p.yzx), step(p.x, RGBA.r));
|
||||||
|
float d = q.x - min(q.w, q.y);
|
||||||
|
return float4(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x, RGBA.a);
|
||||||
|
}
|
||||||
|
|
||||||
|
float4 HSVtoRGB(float4 HSVA) {
|
||||||
|
const float4 K = float4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
|
||||||
|
float4 v = float4(0,0,0,0);
|
||||||
|
v.rgb = HSVA.z * lerp(K.xxx, clamp(abs(frac(HSVA.xxx + K.xyz) * 6.0 - K.www) - K.xxx, 0.0, 1.0), HSVA.y);
|
||||||
|
v.a = HSVA.a;
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
float4 HSLtoRGB(float4 HSLA) {
|
||||||
|
float3 rgb = clamp(
|
||||||
|
abs(
|
||||||
|
mod(
|
||||||
|
HSLA.x * 6.0 + float3(0.0, 4.0, 2.0),
|
||||||
|
6.0
|
||||||
|
) - 3.0
|
||||||
|
) - 1.0,
|
||||||
|
0.0,
|
||||||
|
1.0
|
||||||
|
);
|
||||||
|
return float4(HSLA.z + HSLA.y * (rgb - 0.5) * (1.0 - abs(2.0 * HSLA.z - 1.0)), HSLA.a);
|
||||||
|
}
|
||||||
|
|
||||||
|
float4 RGBtoHSL(float4 RGBA) {
|
||||||
|
float h = 0.0;
|
||||||
|
float s = 0.0;
|
||||||
|
float l = 0.0;
|
||||||
|
float r = RGBA.r;
|
||||||
|
float g = RGBA.g;
|
||||||
|
float b = RGBA.b;
|
||||||
|
float cMin = min( r, min( g, b ) );
|
||||||
|
float cMax = max( r, max( g, b ) );
|
||||||
|
|
||||||
|
l = ( cMax + cMin ) / 2.0;
|
||||||
|
if ( cMax > cMin ) {
|
||||||
|
float cDelta = cMax - cMin;
|
||||||
|
|
||||||
|
//s = l < .05 ? cDelta / ( cMax + cMin ) : cDelta / ( 2.0 - ( cMax + cMin ) ); Original
|
||||||
|
s = l < .0 ? cDelta / ( cMax + cMin ) : cDelta / ( 2.0 - ( cMax + cMin ) );
|
||||||
|
|
||||||
|
if ( r == cMax ) {
|
||||||
|
h = ( g - b ) / cDelta;
|
||||||
|
} else if ( g == cMax ) {
|
||||||
|
h = 2.0 + ( b - r ) / cDelta;
|
||||||
|
} else {
|
||||||
|
h = 4.0 + ( r - g ) / cDelta;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( h < 0.0) {
|
||||||
|
h += 6.0;
|
||||||
|
}
|
||||||
|
h = h / 6.0;
|
||||||
|
}
|
||||||
|
return float4( h, s, l, RGBA.a );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Actual Code -----------------------------------------------------------------
|
||||||
float4 Lift(float4 v)
|
float4 Lift(float4 v)
|
||||||
{
|
{
|
||||||
v.rgb = pLift.aaa + v.rgb;
|
v.rgb = pLift.aaa + v.rgb;
|
||||||
|
@ -64,25 +164,33 @@ float4 Offset(float4 v)
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
float4 RGBtoHSV(float4 RGBA) {
|
|
||||||
const float4 K = float4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
|
|
||||||
const float e = 1.0e-10;
|
|
||||||
float4 p = lerp(float4(RGBA.bg, K.wz), float4(RGBA.gb, K.xy), step(RGBA.b, RGBA.g));
|
|
||||||
float4 q = lerp(float4(p.xyw, RGBA.r), float4(RGBA.r, p.yzx), step(p.x, RGBA.r));
|
|
||||||
float d = q.x - min(q.w, q.y);
|
|
||||||
return float4(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x, RGBA.a);
|
|
||||||
}
|
|
||||||
|
|
||||||
float4 HSVtoRGB(float4 HSVA) {
|
|
||||||
const float4 K = float4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
|
|
||||||
float4 v = float4(0,0,0,0);
|
|
||||||
v.rgb = HSVA.z * lerp(K.xxx, clamp(abs(frac(HSVA.xxx + K.xyz) * 6.0 - K.www) - K.xxx, 0.0, 1.0), HSVA.y);
|
|
||||||
v.a = HSVA.a;
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
|
|
||||||
float4 Tint(float4 v)
|
float4 Tint(float4 v)
|
||||||
{
|
{
|
||||||
|
float value = 0.;
|
||||||
|
if (pTintDetection == TINT_DETECTION_HSV) { // HSV
|
||||||
|
value = RGBtoHSV(v).z;
|
||||||
|
} else if (pTintDetection == TINT_DETECTION_HSL) { // HSL
|
||||||
|
value = RGBtoHSL(v).z;
|
||||||
|
} else if (pTintDetection == TINT_DETECTION_YUV_SDR) { // YUV HD SDR
|
||||||
|
const float3x3 mYUV709n = { // Normalized
|
||||||
|
0.2126, 0.7152, 0.0722,
|
||||||
|
-0.1145721060573399, -0.3854278939426601, 0.5,
|
||||||
|
0.5, -0.4541529083058166, -0.0458470916941834
|
||||||
|
};
|
||||||
|
value = RGBtoYUV(v, mYUV709n).r;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pTintMode == TINT_MODE_LINEAR) { // Linear
|
||||||
|
} else if (pTintMode == TINT_MODE_EXP) { // Exp
|
||||||
|
value = 1.0 - exp2(value * pTintLumaExponent * -C_log2_e);
|
||||||
|
} else if (pTintMode == TINT_MODE_EXP2) { // Exp2
|
||||||
|
value = 1.0 - exp2(value * value * pTintLumaExponent * pTintLumaExponent * -C_log2_e);
|
||||||
|
} else if (pTintMode == TINT_MODE_LOG) { // Log
|
||||||
|
value = (log2(value) + 2.) / 2.333333;
|
||||||
|
} else if (pTintMode == TINT_MODE_LOG10) { // Log10
|
||||||
|
value = (log10(value) + 1.) / 2.;
|
||||||
|
}
|
||||||
|
|
||||||
float4 v1 = RGBtoHSV(v);
|
float4 v1 = RGBtoHSV(v);
|
||||||
float3 tint = float3(0,0,0);
|
float3 tint = float3(0,0,0);
|
||||||
if (v1.b > 0.5) {
|
if (v1.b > 0.5) {
|
||||||
|
|
|
@ -44,6 +44,11 @@
|
||||||
#define ST_OFFSET ST ".Offset"
|
#define ST_OFFSET ST ".Offset"
|
||||||
#define ST_OFFSET_(x) ST_OFFSET "." D_VSTR(x)
|
#define ST_OFFSET_(x) ST_OFFSET "." D_VSTR(x)
|
||||||
#define ST_TINT ST ".Tint"
|
#define ST_TINT ST ".Tint"
|
||||||
|
#define ST_TINT_DETECTION ST_TINT ".Detection"
|
||||||
|
#define ST_TINT_DETECTION_(x) ST_TINT_DETECTION "." D_VSTR(x)
|
||||||
|
#define ST_TINT_MODE ST_TINT ".Mode"
|
||||||
|
#define ST_TINT_MODE_(x) ST_TINT_MODE "." D_VSTR(x)
|
||||||
|
#define ST_TINT_EXPONENT ST_TINT ".Exponent"
|
||||||
#define ST_TINT_(x, y) ST_TINT "." D_VSTR(x) "." D_VSTR(y)
|
#define ST_TINT_(x, y) ST_TINT "." D_VSTR(x) "." D_VSTR(y)
|
||||||
#define ST_CORRECTION ST ".Correction"
|
#define ST_CORRECTION ST ".Correction"
|
||||||
#define ST_CORRECTION_(x) ST_CORRECTION "." D_VSTR(x)
|
#define ST_CORRECTION_(x) ST_CORRECTION "." D_VSTR(x)
|
||||||
|
@ -59,6 +64,14 @@
|
||||||
#define TONE_LOW Shadow
|
#define TONE_LOW Shadow
|
||||||
#define TONE_MID Midtone
|
#define TONE_MID Midtone
|
||||||
#define TONE_HIG Highlight
|
#define TONE_HIG Highlight
|
||||||
|
#define DETECTION_HSV HSV
|
||||||
|
#define DETECTION_HSL HSL
|
||||||
|
#define DETECTION_YUV_SDR YUV.SDR
|
||||||
|
#define MODE_LINEAR Linear
|
||||||
|
#define MODE_EXP Exp
|
||||||
|
#define MODE_EXP2 Exp2
|
||||||
|
#define MODE_LOG Log
|
||||||
|
#define MODE_LOG10 Log2
|
||||||
|
|
||||||
// Initializer & Finalizer
|
// Initializer & Finalizer
|
||||||
P_INITIALIZER(FilterColorGradeInit)
|
P_INITIALIZER(FilterColorGradeInit)
|
||||||
|
@ -91,6 +104,9 @@ void get_defaults(obs_data_t* data)
|
||||||
obs_data_set_default_double(data, ST_OFFSET_(GREEN), 0.0);
|
obs_data_set_default_double(data, ST_OFFSET_(GREEN), 0.0);
|
||||||
obs_data_set_default_double(data, ST_OFFSET_(BLUE), 0.0);
|
obs_data_set_default_double(data, ST_OFFSET_(BLUE), 0.0);
|
||||||
obs_data_set_default_double(data, ST_OFFSET_(ALL), 0.0);
|
obs_data_set_default_double(data, ST_OFFSET_(ALL), 0.0);
|
||||||
|
obs_data_set_default_int(data, ST_TINT_MODE, static_cast<int64_t>(filter::color_grade::luma_mode::Exp2));
|
||||||
|
obs_data_set_default_int(data, ST_TINT_DETECTION, static_cast<int64_t>(filter::color_grade::detection_mode::HSL));
|
||||||
|
obs_data_set_default_double(data, ST_TINT_EXPONENT, 1.0);
|
||||||
obs_data_set_default_double(data, ST_TINT_(TONE_LOW, RED), 100.0);
|
obs_data_set_default_double(data, ST_TINT_(TONE_LOW, RED), 100.0);
|
||||||
obs_data_set_default_double(data, ST_TINT_(TONE_LOW, GREEN), 100.0);
|
obs_data_set_default_double(data, ST_TINT_(TONE_LOW, GREEN), 100.0);
|
||||||
obs_data_set_default_double(data, ST_TINT_(TONE_LOW, BLUE), 100.0);
|
obs_data_set_default_double(data, ST_TINT_(TONE_LOW, BLUE), 100.0);
|
||||||
|
@ -117,6 +133,9 @@ bool tool_modified(obs_properties_t* props, obs_property_t* property, obs_data_t
|
||||||
{ST_OFFSET, {ST_OFFSET_(RED), ST_OFFSET_(GREEN), ST_OFFSET_(BLUE), ST_OFFSET_(ALL)}},
|
{ST_OFFSET, {ST_OFFSET_(RED), ST_OFFSET_(GREEN), ST_OFFSET_(BLUE), ST_OFFSET_(ALL)}},
|
||||||
{ST_TINT,
|
{ST_TINT,
|
||||||
{
|
{
|
||||||
|
ST_TINT_MODE,
|
||||||
|
ST_TINT_DETECTION,
|
||||||
|
ST_TINT_EXPONENT,
|
||||||
ST_TINT_(TONE_LOW, RED),
|
ST_TINT_(TONE_LOW, RED),
|
||||||
ST_TINT_(TONE_LOW, GREEN),
|
ST_TINT_(TONE_LOW, GREEN),
|
||||||
ST_TINT_(TONE_LOW, BLUE),
|
ST_TINT_(TONE_LOW, BLUE),
|
||||||
|
@ -221,6 +240,34 @@ obs_properties_t* get_properties(void*)
|
||||||
obs_properties_add_group(pr, ST_TINT, D_TRANSLATE(ST_TINT), OBS_GROUP_NORMAL, grp);
|
obs_properties_add_group(pr, ST_TINT, D_TRANSLATE(ST_TINT), OBS_GROUP_NORMAL, grp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
auto p = obs_properties_add_list(grp, ST_TINT_MODE, D_TRANSLATE(ST_TINT_MODE), OBS_COMBO_TYPE_LIST,
|
||||||
|
OBS_COMBO_FORMAT_INT);
|
||||||
|
std::pair<const char*, filter::color_grade::luma_mode> els[] = {
|
||||||
|
{ST_TINT_MODE_(MODE_LINEAR), filter::color_grade::luma_mode::Linear},
|
||||||
|
{ST_TINT_MODE_(MODE_EXP), filter::color_grade::luma_mode::Exp},
|
||||||
|
{ST_TINT_MODE_(MODE_EXP2), filter::color_grade::luma_mode::Exp2},
|
||||||
|
{ST_TINT_MODE_(MODE_LOG), filter::color_grade::luma_mode::Log},
|
||||||
|
{ST_TINT_MODE_(MODE_LOG10), filter::color_grade::luma_mode::Log10}};
|
||||||
|
for (auto kv : els) {
|
||||||
|
obs_property_list_add_int(p, D_TRANSLATE(kv.first), static_cast<int64_t>(kv.second));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
auto p = obs_properties_add_list(grp, ST_TINT_DETECTION, D_TRANSLATE(ST_TINT_DETECTION),
|
||||||
|
OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT);
|
||||||
|
std::pair<const char*, filter::color_grade::detection_mode> els[] = {
|
||||||
|
{ST_TINT_DETECTION_(DETECTION_HSV), filter::color_grade::detection_mode::HSV},
|
||||||
|
{ST_TINT_DETECTION_(DETECTION_HSL), filter::color_grade::detection_mode::HSL},
|
||||||
|
{ST_TINT_DETECTION_(DETECTION_YUV_SDR), filter::color_grade::detection_mode::YUV_SDR}};
|
||||||
|
for (auto kv : els) {
|
||||||
|
obs_property_list_add_int(p, D_TRANSLATE(kv.first), static_cast<int64_t>(kv.second));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
obs_properties_add_float_slider(grp, ST_TINT_EXPONENT, D_TRANSLATE(ST_TINT_EXPONENT), 0., 10., 0.01);
|
||||||
|
|
||||||
obs_properties_add_float_slider(grp, ST_TINT_(TONE_LOW, RED), D_TRANSLATE(ST_TINT_(TONE_LOW, RED)), 0, 1000.0,
|
obs_properties_add_float_slider(grp, ST_TINT_(TONE_LOW, RED), D_TRANSLATE(ST_TINT_(TONE_LOW, RED)), 0, 1000.0,
|
||||||
0.01);
|
0.01);
|
||||||
obs_properties_add_float_slider(grp, ST_TINT_(TONE_LOW, GREEN), D_TRANSLATE(ST_TINT_(TONE_LOW, GREEN)), 0,
|
obs_properties_add_float_slider(grp, ST_TINT_(TONE_LOW, GREEN), D_TRANSLATE(ST_TINT_(TONE_LOW, GREEN)), 0,
|
||||||
|
@ -262,67 +309,58 @@ obs_properties_t* get_properties(void*)
|
||||||
return pr;
|
return pr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void* create(obs_data_t* data, obs_source_t* source)
|
void* create(obs_data_t* data, obs_source_t* source) try {
|
||||||
try {
|
|
||||||
return new filter::color_grade::color_grade_instance(data, source);
|
return new filter::color_grade::color_grade_instance(data, source);
|
||||||
} catch (std::exception& ex) {
|
} catch (std::exception& ex) {
|
||||||
P_LOG_ERROR("<filter-color-grade> Failed to create: %s", obs_source_get_name(source), ex.what());
|
P_LOG_ERROR("<filter-color-grade> Failed to create: %s", obs_source_get_name(source), ex.what());
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void destroy(void* ptr)
|
void destroy(void* ptr) try {
|
||||||
try {
|
|
||||||
delete reinterpret_cast<filter::color_grade::color_grade_instance*>(ptr);
|
delete reinterpret_cast<filter::color_grade::color_grade_instance*>(ptr);
|
||||||
} catch (std::exception& ex) {
|
} catch (std::exception& ex) {
|
||||||
P_LOG_ERROR("<filter-color-grade> Failed to destroy: %s", ex.what());
|
P_LOG_ERROR("<filter-color-grade> Failed to destroy: %s", ex.what());
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t get_width(void* ptr)
|
uint32_t get_width(void* ptr) try {
|
||||||
try {
|
|
||||||
return reinterpret_cast<filter::color_grade::color_grade_instance*>(ptr)->get_width();
|
return reinterpret_cast<filter::color_grade::color_grade_instance*>(ptr)->get_width();
|
||||||
} catch (std::exception& ex) {
|
} catch (std::exception& ex) {
|
||||||
P_LOG_ERROR("<filter-color-grade> Failed to get width: %s", ex.what());
|
P_LOG_ERROR("<filter-color-grade> Failed to get width: %s", ex.what());
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t get_height(void* ptr)
|
uint32_t get_height(void* ptr) try {
|
||||||
try {
|
|
||||||
return reinterpret_cast<filter::color_grade::color_grade_instance*>(ptr)->get_height();
|
return reinterpret_cast<filter::color_grade::color_grade_instance*>(ptr)->get_height();
|
||||||
} catch (std::exception& ex) {
|
} catch (std::exception& ex) {
|
||||||
P_LOG_ERROR("<filter-color-grade> Failed to get height: %s", ex.what());
|
P_LOG_ERROR("<filter-color-grade> Failed to get height: %s", ex.what());
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void update(void* ptr, obs_data_t* data)
|
void update(void* ptr, obs_data_t* data) try {
|
||||||
try {
|
|
||||||
reinterpret_cast<filter::color_grade::color_grade_instance*>(ptr)->update(data);
|
reinterpret_cast<filter::color_grade::color_grade_instance*>(ptr)->update(data);
|
||||||
} catch (std::exception& ex) {
|
} catch (std::exception& ex) {
|
||||||
P_LOG_ERROR("<filter-color-grade> Failed to update: %s", ex.what());
|
P_LOG_ERROR("<filter-color-grade> Failed to update: %s", ex.what());
|
||||||
}
|
}
|
||||||
|
|
||||||
void activate(void* ptr)
|
void activate(void* ptr) try {
|
||||||
try {
|
|
||||||
reinterpret_cast<filter::color_grade::color_grade_instance*>(ptr)->activate();
|
reinterpret_cast<filter::color_grade::color_grade_instance*>(ptr)->activate();
|
||||||
} catch (std::exception& ex) {
|
} catch (std::exception& ex) {
|
||||||
P_LOG_ERROR("<filter-color-grade> Failed to activate: %s", ex.what());
|
P_LOG_ERROR("<filter-color-grade> Failed to activate: %s", ex.what());
|
||||||
}
|
}
|
||||||
|
|
||||||
void deactivate(void* ptr)
|
void deactivate(void* ptr) try {
|
||||||
try {
|
|
||||||
reinterpret_cast<filter::color_grade::color_grade_instance*>(ptr)->deactivate();
|
reinterpret_cast<filter::color_grade::color_grade_instance*>(ptr)->deactivate();
|
||||||
} catch (std::exception& ex) {
|
} catch (std::exception& ex) {
|
||||||
P_LOG_ERROR("<filter-color-grade> Failed to deactivate: %s", ex.what());
|
P_LOG_ERROR("<filter-color-grade> Failed to deactivate: %s", ex.what());
|
||||||
}
|
}
|
||||||
|
|
||||||
void video_tick(void* ptr, float time)
|
void video_tick(void* ptr, float time) try {
|
||||||
try {
|
|
||||||
reinterpret_cast<filter::color_grade::color_grade_instance*>(ptr)->video_tick(time);
|
reinterpret_cast<filter::color_grade::color_grade_instance*>(ptr)->video_tick(time);
|
||||||
} catch (std::exception& ex) {
|
} catch (std::exception& ex) {
|
||||||
P_LOG_ERROR("<filter-color-grade> Failed to tick video: %s", ex.what());
|
P_LOG_ERROR("<filter-color-grade> Failed to tick video: %s", ex.what());
|
||||||
}
|
}
|
||||||
|
|
||||||
void video_render(void* ptr, gs_effect_t* effect)
|
void video_render(void* ptr, gs_effect_t* effect) try {
|
||||||
try {
|
|
||||||
reinterpret_cast<filter::color_grade::color_grade_instance*>(ptr)->video_render(effect);
|
reinterpret_cast<filter::color_grade::color_grade_instance*>(ptr)->video_render(effect);
|
||||||
} catch (std::exception& ex) {
|
} catch (std::exception& ex) {
|
||||||
P_LOG_ERROR("<filter-color-grade> Failed to render video: %s", ex.what());
|
P_LOG_ERROR("<filter-color-grade> Failed to render video: %s", ex.what());
|
||||||
|
@ -427,35 +465,38 @@ float_t fix_gamma_value(double_t v)
|
||||||
|
|
||||||
void filter::color_grade::color_grade_instance::update(obs_data_t* data)
|
void filter::color_grade::color_grade_instance::update(obs_data_t* data)
|
||||||
{
|
{
|
||||||
_lift.x = static_cast<float_t>(obs_data_get_double(data, ST_LIFT_(RED)) / 100.0);
|
_lift.x = static_cast<float_t>(obs_data_get_double(data, ST_LIFT_(RED)) / 100.0);
|
||||||
_lift.y = static_cast<float_t>(obs_data_get_double(data, ST_LIFT_(GREEN)) / 100.0);
|
_lift.y = static_cast<float_t>(obs_data_get_double(data, ST_LIFT_(GREEN)) / 100.0);
|
||||||
_lift.z = static_cast<float_t>(obs_data_get_double(data, ST_LIFT_(BLUE)) / 100.0);
|
_lift.z = static_cast<float_t>(obs_data_get_double(data, ST_LIFT_(BLUE)) / 100.0);
|
||||||
_lift.w = static_cast<float_t>(obs_data_get_double(data, ST_LIFT_(ALL)) / 100.0);
|
_lift.w = static_cast<float_t>(obs_data_get_double(data, ST_LIFT_(ALL)) / 100.0);
|
||||||
_gamma.x = fix_gamma_value(obs_data_get_double(data, ST_GAMMA_(RED)) / 100.0);
|
_gamma.x = fix_gamma_value(obs_data_get_double(data, ST_GAMMA_(RED)) / 100.0);
|
||||||
_gamma.y = fix_gamma_value(obs_data_get_double(data, ST_GAMMA_(GREEN)) / 100.0);
|
_gamma.y = fix_gamma_value(obs_data_get_double(data, ST_GAMMA_(GREEN)) / 100.0);
|
||||||
_gamma.z = fix_gamma_value(obs_data_get_double(data, ST_GAMMA_(BLUE)) / 100.0);
|
_gamma.z = fix_gamma_value(obs_data_get_double(data, ST_GAMMA_(BLUE)) / 100.0);
|
||||||
_gamma.w = fix_gamma_value(obs_data_get_double(data, ST_GAMMA_(ALL)) / 100.0);
|
_gamma.w = fix_gamma_value(obs_data_get_double(data, ST_GAMMA_(ALL)) / 100.0);
|
||||||
_gain.x = static_cast<float_t>(obs_data_get_double(data, ST_GAIN_(RED)) / 100.0);
|
_gain.x = static_cast<float_t>(obs_data_get_double(data, ST_GAIN_(RED)) / 100.0);
|
||||||
_gain.y = static_cast<float_t>(obs_data_get_double(data, ST_GAIN_(GREEN)) / 100.0);
|
_gain.y = static_cast<float_t>(obs_data_get_double(data, ST_GAIN_(GREEN)) / 100.0);
|
||||||
_gain.z = static_cast<float_t>(obs_data_get_double(data, ST_GAIN_(BLUE)) / 100.0);
|
_gain.z = static_cast<float_t>(obs_data_get_double(data, ST_GAIN_(BLUE)) / 100.0);
|
||||||
_gain.w = static_cast<float_t>(obs_data_get_double(data, ST_GAIN_(ALL)) / 100.0);
|
_gain.w = static_cast<float_t>(obs_data_get_double(data, ST_GAIN_(ALL)) / 100.0);
|
||||||
_offset.x = static_cast<float_t>(obs_data_get_double(data, ST_OFFSET_(RED)) / 100.0);
|
_offset.x = static_cast<float_t>(obs_data_get_double(data, ST_OFFSET_(RED)) / 100.0);
|
||||||
_offset.y = static_cast<float_t>(obs_data_get_double(data, ST_OFFSET_(GREEN)) / 100.0);
|
_offset.y = static_cast<float_t>(obs_data_get_double(data, ST_OFFSET_(GREEN)) / 100.0);
|
||||||
_offset.z = static_cast<float_t>(obs_data_get_double(data, ST_OFFSET_(BLUE)) / 100.0);
|
_offset.z = static_cast<float_t>(obs_data_get_double(data, ST_OFFSET_(BLUE)) / 100.0);
|
||||||
_offset.w = static_cast<float_t>(obs_data_get_double(data, ST_OFFSET_(ALL)) / 100.0);
|
_offset.w = static_cast<float_t>(obs_data_get_double(data, ST_OFFSET_(ALL)) / 100.0);
|
||||||
_tint_low.x = static_cast<float_t>(obs_data_get_double(data, ST_TINT_(TONE_LOW, RED)) / 100.0);
|
_tint_detection = static_cast<detection_mode>(obs_data_get_int(data, ST_TINT_DETECTION));
|
||||||
_tint_low.y = static_cast<float_t>(obs_data_get_double(data, ST_TINT_(TONE_LOW, GREEN)) / 100.0);
|
_tint_luma = static_cast<luma_mode>(obs_data_get_int(data, ST_TINT_MODE));
|
||||||
_tint_low.z = static_cast<float_t>(obs_data_get_double(data, ST_TINT_(TONE_LOW, BLUE)) / 100.0);
|
_tint_exponent = static_cast<float_t>(obs_data_get_double(data, ST_TINT_EXPONENT));
|
||||||
_tint_mid.x = static_cast<float_t>(obs_data_get_double(data, ST_TINT_(TONE_MID, RED)) / 100.0);
|
_tint_low.x = static_cast<float_t>(obs_data_get_double(data, ST_TINT_(TONE_LOW, RED)) / 100.0);
|
||||||
_tint_mid.y = static_cast<float_t>(obs_data_get_double(data, ST_TINT_(TONE_MID, GREEN)) / 100.0);
|
_tint_low.y = static_cast<float_t>(obs_data_get_double(data, ST_TINT_(TONE_LOW, GREEN)) / 100.0);
|
||||||
_tint_mid.z = static_cast<float_t>(obs_data_get_double(data, ST_TINT_(TONE_MID, BLUE)) / 100.0);
|
_tint_low.z = static_cast<float_t>(obs_data_get_double(data, ST_TINT_(TONE_LOW, BLUE)) / 100.0);
|
||||||
_tint_hig.x = static_cast<float_t>(obs_data_get_double(data, ST_TINT_(TONE_HIG, RED)) / 100.0);
|
_tint_mid.x = static_cast<float_t>(obs_data_get_double(data, ST_TINT_(TONE_MID, RED)) / 100.0);
|
||||||
_tint_hig.y = static_cast<float_t>(obs_data_get_double(data, ST_TINT_(TONE_HIG, GREEN)) / 100.0);
|
_tint_mid.y = static_cast<float_t>(obs_data_get_double(data, ST_TINT_(TONE_MID, GREEN)) / 100.0);
|
||||||
_tint_hig.z = static_cast<float_t>(obs_data_get_double(data, ST_TINT_(TONE_HIG, BLUE)) / 100.0);
|
_tint_mid.z = static_cast<float_t>(obs_data_get_double(data, ST_TINT_(TONE_MID, BLUE)) / 100.0);
|
||||||
_correction.x = static_cast<float_t>(obs_data_get_double(data, ST_CORRECTION_(HUE)) / 360.0);
|
_tint_hig.x = static_cast<float_t>(obs_data_get_double(data, ST_TINT_(TONE_HIG, RED)) / 100.0);
|
||||||
_correction.y = static_cast<float_t>(obs_data_get_double(data, ST_CORRECTION_(SATURATION)) / 100.0);
|
_tint_hig.y = static_cast<float_t>(obs_data_get_double(data, ST_TINT_(TONE_HIG, GREEN)) / 100.0);
|
||||||
_correction.z = static_cast<float_t>(obs_data_get_double(data, ST_CORRECTION_(LIGHTNESS)) / 100.0);
|
_tint_hig.z = static_cast<float_t>(obs_data_get_double(data, ST_TINT_(TONE_HIG, BLUE)) / 100.0);
|
||||||
_correction.w = static_cast<float_t>(obs_data_get_double(data, ST_CORRECTION_(CONTRAST)) / 100.0);
|
_correction.x = static_cast<float_t>(obs_data_get_double(data, ST_CORRECTION_(HUE)) / 360.0);
|
||||||
|
_correction.y = static_cast<float_t>(obs_data_get_double(data, ST_CORRECTION_(SATURATION)) / 100.0);
|
||||||
|
_correction.z = static_cast<float_t>(obs_data_get_double(data, ST_CORRECTION_(LIGHTNESS)) / 100.0);
|
||||||
|
_correction.w = static_cast<float_t>(obs_data_get_double(data, ST_CORRECTION_(CONTRAST)) / 100.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void filter::color_grade::color_grade_instance::activate()
|
void filter::color_grade::color_grade_instance::activate()
|
||||||
|
@ -532,6 +573,12 @@ void filter::color_grade::color_grade_instance::video_render(gs_effect_t*)
|
||||||
_effect->get_parameter("pGain")->set_float4(_gain);
|
_effect->get_parameter("pGain")->set_float4(_gain);
|
||||||
if (_effect->has_parameter("pOffset"))
|
if (_effect->has_parameter("pOffset"))
|
||||||
_effect->get_parameter("pOffset")->set_float4(_offset);
|
_effect->get_parameter("pOffset")->set_float4(_offset);
|
||||||
|
if (_effect->has_parameter("pTintDetection"))
|
||||||
|
_effect->get_parameter("pTintDetection")->set_int(static_cast<int32_t>(_tint_detection));
|
||||||
|
if (_effect->has_parameter("pTintMode"))
|
||||||
|
_effect->get_parameter("pTintMode")->set_int(static_cast<int32_t>(_tint_luma));
|
||||||
|
if (_effect->has_parameter("pTintExponent"))
|
||||||
|
_effect->get_parameter("pTintExponent")->set_float(_tint_exponent);
|
||||||
if (_effect->has_parameter("pTintLow"))
|
if (_effect->has_parameter("pTintLow"))
|
||||||
_effect->get_parameter("pTintLow")->set_float3(_tint_low);
|
_effect->get_parameter("pTintLow")->set_float3(_tint_low);
|
||||||
if (_effect->has_parameter("pTintMid"))
|
if (_effect->has_parameter("pTintMid"))
|
||||||
|
|
|
@ -29,11 +29,11 @@
|
||||||
namespace filter {
|
namespace filter {
|
||||||
namespace color_grade {
|
namespace color_grade {
|
||||||
class color_grade_factory {
|
class color_grade_factory {
|
||||||
obs_source_info sourceInfo;
|
obs_source_info sourceInfo;
|
||||||
|
|
||||||
public: // Singleton
|
public: // Singleton
|
||||||
static void initialize();
|
static void initialize();
|
||||||
static void finalize();
|
static void finalize();
|
||||||
static std::shared_ptr<color_grade_factory> get();
|
static std::shared_ptr<color_grade_factory> get();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -41,6 +41,20 @@ namespace filter {
|
||||||
~color_grade_factory();
|
~color_grade_factory();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class detection_mode {
|
||||||
|
HSV,
|
||||||
|
HSL,
|
||||||
|
YUV_SDR,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class luma_mode {
|
||||||
|
Linear,
|
||||||
|
Exp,
|
||||||
|
Exp2,
|
||||||
|
Log,
|
||||||
|
Log10,
|
||||||
|
};
|
||||||
|
|
||||||
class color_grade_instance {
|
class color_grade_instance {
|
||||||
bool _active;
|
bool _active;
|
||||||
obs_source_t* _self;
|
obs_source_t* _self;
|
||||||
|
@ -58,14 +72,17 @@ namespace filter {
|
||||||
bool _grade_updated;
|
bool _grade_updated;
|
||||||
|
|
||||||
// Parameters
|
// Parameters
|
||||||
vec4 _lift;
|
vec4 _lift;
|
||||||
vec4 _gamma;
|
vec4 _gamma;
|
||||||
vec4 _gain;
|
vec4 _gain;
|
||||||
vec4 _offset;
|
vec4 _offset;
|
||||||
vec3 _tint_low;
|
detection_mode _tint_detection;
|
||||||
vec3 _tint_mid;
|
luma_mode _tint_luma;
|
||||||
vec3 _tint_hig;
|
float_t _tint_exponent;
|
||||||
vec4 _correction;
|
vec3 _tint_low;
|
||||||
|
vec3 _tint_mid;
|
||||||
|
vec3 _tint_hig;
|
||||||
|
vec4 _correction;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
~color_grade_instance();
|
~color_grade_instance();
|
||||||
|
|
Loading…
Reference in a new issue