diff --git a/app/node/keying/chromakey/chromakey.cpp b/app/node/keying/chromakey/chromakey.cpp index 43ca49f88..9a399a386 100644 --- a/app/node/keying/chromakey/chromakey.cpp +++ b/app/node/keying/chromakey/chromakey.cpp @@ -26,6 +26,10 @@ const QString ChromaKeyNode::kColorInput = QStringLiteral("color_key"); const QString ChromaKeyNode::kMaskOnlyInput = QStringLiteral("mask_only_in"); const QString ChromaKeyNode::kUpperToleranceInput = QStringLiteral("upper_tolerence_in"); const QString ChromaKeyNode::kLowerToleranceInput = QStringLiteral("lower_tolerence_in"); +const QString ChromaKeyNode::kGarbageMatteInput = QStringLiteral("garbage_in"); +const QString ChromaKeyNode::kCoreMatteInput = QStringLiteral("core_in"); +const QString ChromaKeyNode::kShadowsInput = QStringLiteral("shadows_in"); +const QString ChromaKeyNode::kHighlightsInput = QStringLiteral("highlights_in"); ChromaKeyNode::ChromaKeyNode() { @@ -37,6 +41,16 @@ ChromaKeyNode::ChromaKeyNode() AddInput(kLowerToleranceInput, NodeValue::kFloat, 5.0); SetInputProperty(kLowerToleranceInput, QStringLiteral("min"), 0.0); + AddInput(kGarbageMatteInput, NodeValue::kTexture, InputFlags(kInputFlagNotKeyframable)); + + AddInput(kCoreMatteInput, NodeValue::kTexture, InputFlags(kInputFlagNotKeyframable)); + + AddInput(kHighlightsInput, NodeValue::kFloat, 100.0f); + SetInputProperty(kHighlightsInput, QStringLiteral("min"), 0.0); + + AddInput(kShadowsInput, NodeValue::kFloat, 100.0f); + SetInputProperty(kShadowsInput, QStringLiteral("min"), 0.0); + AddInput(kMaskOnlyInput, NodeValue::kBoolean, false); SetEffectInput(kTextureInput); @@ -66,12 +80,11 @@ void ChromaKeyNode::Retranslate() { super::Retranslate(); SetInputName(kTextureInput, tr("Input")); - //SetInputName(kGarbageMatteInput, tr("Garbage Matte")); - //SetInputName(kCoreMatteInput, tr("Core Matte")); + SetInputName(kGarbageMatteInput, tr("Garbage Matte")); + SetInputName(kCoreMatteInput, tr("Core Matte")); SetInputName(kColorInput, tr("Key Color")); - //SetComboBoxStrings(kColorInput, {tr("Green"), tr("Blue")}); - //SetInputName(kShadowsInput, tr("Shadows")); - //SetInputName(kHighlightsInput, tr("Highlights")); + SetInputName(kShadowsInput, tr("Shadows")); + SetInputName(kHighlightsInput, tr("Highlights")); SetInputName(kUpperToleranceInput, tr("Upper Tolerance")); SetInputName(kLowerToleranceInput, tr("Lower Tolerance")); SetInputName(kMaskOnlyInput, tr("Show Mask Only")); diff --git a/app/node/keying/chromakey/chromakey.h b/app/node/keying/chromakey/chromakey.h index 84e4c2ca1..3344ef019 100644 --- a/app/node/keying/chromakey/chromakey.h +++ b/app/node/keying/chromakey/chromakey.h @@ -46,6 +46,10 @@ class ChromaKeyNode : public OCIOBaseNode { static const QString kMaskOnlyInput; static const QString kUpperToleranceInput; static const QString kLowerToleranceInput; + static const QString kGarbageMatteInput; + static const QString kCoreMatteInput; + static const QString kShadowsInput; + static const QString kHighlightsInput; private: void GenerateProcessor(); diff --git a/app/shaders/chromakey.frag b/app/shaders/chromakey.frag index fbc4da00c..0b3fb132f 100644 --- a/app/shaders/chromakey.frag +++ b/app/shaders/chromakey.frag @@ -5,6 +5,14 @@ uniform bool mask_only_in; uniform float upper_tolerence_in; uniform float lower_tolerence_in; +uniform sampler2D garbage_in; +uniform sampler2D core_in; +uniform bool garbage_in_enabled; +uniform bool core_in_enabled; + +uniform float highlights_in; +uniform float shadows_in; + // Main texture coordinate in vec2 ove_texcoord; @@ -38,11 +46,11 @@ vec4 CIExyz_to_Lab(vec4 CIE) { } float colorclose(vec4 col, vec4 key, float tola,float tolb) { - /*decides if a color is close to the specified hue*/ - float temp = sqrt(((key.g-col.g)*(key.g-col.g))+((key.b-col.b)*(key.b-col.b))); - if (temp < tola) {return (0.0);} - if (temp < tolb) {return ((temp-tola)/(tolb-tola));} - return (1.0); + /*decides if a color is close to the specified hue*/ + float temp = sqrt(((key.g-col.g)*(key.g-col.g))+((key.b-col.b)*(key.b-col.b))); + if (temp < tola) {return (0.0);} + if (temp < tolb) {return ((temp-tola)/(tolb-tola));} + return (1.0); } @@ -50,8 +58,13 @@ void main() { vec4 col = texture(tex_in, ove_texcoord); + vec4 unassoc = col; + if (unassoc.a > 0) { + unassoc.rgb /= unassoc.a; + } + // Perform color conversion - vec4 cie_xyz = SceneLinearToCIEXYZ_d65(col); + vec4 cie_xyz = SceneLinearToCIEXYZ_d65(unassoc); vec4 lab = CIExyz_to_Lab(cie_xyz); vec4 cie_xyz_key = SceneLinearToCIEXYZ_d65(color_key); @@ -59,12 +72,34 @@ void main() { float mask = colorclose(lab, lab_key, lower_tolerence_in, upper_tolerence_in); + mask = clamp(mask, 0.0, 1.0); + + if (garbage_in_enabled) { + // Force anything we want to remove to be 0.0 + vec4 garbage = texture(garbage_in, ove_texcoord); + // Assumes garbage is achromatic + mask -= garbage.r; + mask = clamp(mask, 0.0, 1.0); + } + + if (core_in_enabled) { + // Force anything we want to keep to be 1.0 + vec3 core = texture(core_in, ove_texcoord).rgb; + // Assumes core is achromatic + mask += core.r; + mask = clamp(mask, 0.0, 1.0); + } + + // Crush blacks and push whites + mask = shadows_in * 0.01 * (highlights_in * 0.01 * mask - 1.0) + 1.0; + mask = clamp(mask, 0.0, 1.0); + col.rgb *= mask; col.w = mask; if (!mask_only_in) { - frag_color = col; - } else { - frag_color = vec4(vec3(mask), 1.0); - } + frag_color = col; + } else { + frag_color = vec4(vec3(mask), 1.0); + } }