X-Git-Url: https://cinelerra-gg.org/git/?a=blobdiff_plain;f=cinelerra-5.1%2Fplugins%2Fchromakeyavid%2Fchromakeyavid.sl;fp=cinelerra-5.1%2Fplugins%2Fchromakeyavid%2Fchromakeyavid.sl;h=2fd86da4070ecc4e90667f0ffa7843865ab96759;hb=5dd11b748e5409f8376376f51d0a18d111cbcfdc;hp=0000000000000000000000000000000000000000;hpb=30cad318c058b80002aea28a0968c56485635c7b;p=goodguy%2Fcinelerra.git diff --git a/cinelerra-5.1/plugins/chromakeyavid/chromakeyavid.sl b/cinelerra-5.1/plugins/chromakeyavid/chromakeyavid.sl new file mode 100644 index 00000000..2fd86da4 --- /dev/null +++ b/cinelerra-5.1/plugins/chromakeyavid/chromakeyavid.sl @@ -0,0 +1,230 @@ +uniform sampler2D tex; +uniform float red; +uniform float green; +uniform float blue; +uniform float in_slope; +uniform float out_slope; +uniform float tolerance; +uniform float tolerance_in; +uniform float tolerance_out; +uniform float sat_x; +uniform float sat_y; +uniform float min_s; +uniform float min_s_in; +uniform float min_s_out; +uniform float min_v; +uniform float min_v_in; +uniform float min_v_out; +uniform float max_v; +uniform float max_v_in; +uniform float max_v_out; +uniform float spill_distance; +uniform float spill_x; +uniform float spill_y; +uniform float spill_tolerance; +uniform float min_h; +uniform float max_h; +uniform bool desaturate_only; +uniform float alpha_offset; +uniform float hue_key; +uniform float saturation_key; +uniform float value_key; + + + +// shortest distance between 2 hues +float hue_distance(float h1, float h2) +{ + float result = h1 - h2; + if(result < -180.0) result += 360.0; + else + if(result > 180.0) result -= 360.0; + return result; +} + +// shift H & S based on an X & Y offset +void shift_hs(out float h_shifted, + out float s_shifted, + float h, + float s, + float x_offset, + float y_offset) +{ + float h_rad = radians(h); + float x = cos(h_rad) * s; + float y = sin(h_rad) * s; + x += x_offset; + y += y_offset; + h_shifted = degrees(atan(y, x)); + s_shifted = length(vec2(x, y)); +} + + +void main() +{ + vec4 color = texture2D(tex, gl_TexCoord[0].st); +/* Contribution to alpha from each component */ + float ah = 1.0; + float as = 1.0; + float av = 1.0; + float a = 1.0; + vec4 color2; + +/* Convert to HSV */ + color2 = yuv_to_rgb(color); + color2 = rgb_to_hsv(color2); + float h = color2.r; + float s = color2.g; + float v = color2.b; + +// shift the color in XY to shift the wedge point + float h_shifted, s_shifted; + shift_hs(h_shifted, + s_shifted, + h, + s, + sat_x, + sat_y); + +/* Get the difference between the current hue & the hue key */ + float h_diff = abs(hue_distance(h_shifted, hue_key)); + +// alpha contribution from hue difference +// outside wedge < tolerance_out < tolerance_in < inside wedge < tolerance_in < tolerance_out < outside wedge + if (tolerance_out > 0.0) + { +// completely inside the wedge + if (h_diff < tolerance_in) + ah = 0.0; + else +// between the outer & inner slope + if(h_diff < tolerance_out) + ah = (h_diff - tolerance_in) / (tolerance_out - tolerance_in); + if(ah > 1.0) ah = 1.0; + } + +// alpha contribution from saturation +// outside wedge < min_s_out < min_s_in < inside wedge + if(s_shifted > min_s_out) + { +// saturation with offset applied +// completely inside the wedge + if(s_shifted > min_s_in) + as = 0.0; +// inside the gradient + if(s_shifted >= min_s_out) + as = (min_s_in - s_shifted) / (min_s_in - min_s_out); + } + + +// alpha contribution from brightness range +// brightness range is defined by 4 in/out variables +// outside wedge < min_v_out < min_v_in < inside wedge < max_v_in < max_v_out < outside wedge + if(v > min_v_out) + { + if(v < min_v_in || max_v_in >= 1.0) + av = (min_v_in - v) / (min_v_in - min_v_out); + else + if(v <= max_v_in) + av = 0.0; + else + if(v <= max_v_out) + av = (v - max_v_in) / (max_v_out - max_v_in); + } + +// combine the alpha contribution of every component into a single alpha + a = max(as, ah); + a = max(a, av); + +// Spill light processing + if(spill_tolerance > 0.0) + { +// get the difference between the shifted input color to the unshifted spill wedge + if(spill_distance != 0.0) + { + shift_hs(h_shifted, + s_shifted, + h, + s, + spill_x, + spill_y); + } + else + { + h_shifted = h; + s_shifted = s; + } + +// Difference between the shifted hue & the unshifted hue key + h_diff = hue_distance(h_shifted, hue_key); + +// inside the wedge + if(abs(h_diff) < spill_tolerance) + { + if(!desaturate_only) + { +// the shifted input color in the unshifted wedge +// gives 2 unshifted border colors & the weighting + float blend = 0.5 + h_diff / spill_tolerance / 2.0; +// shift the 2 border colors to the output wedge + float min_h_shifted; + float min_s_shifted; + shift_hs(min_h_shifted, + min_s_shifted, + min_h, + s_shifted, + -spill_x, + -spill_y); + float max_h_shifted; + float max_s_shifted; + shift_hs(max_h_shifted, + max_s_shifted, + max_h, + s_shifted, + -spill_x, + -spill_y); + + +// blend the shifted border colors using the unshifted weighting +// the only thing which doesn't restore the key color & doesn't make an edge is +// fading the saturation to 0 in the middle + if(blend > 0.5) + { + h = max_h_shifted; + s = max_s_shifted; + } + else + { + h = min_h_shifted; + s = min_s_shifted; + } + } + else // !desaturate_only + { + +// fade the saturation to 0 in the middle + s *= abs(h_diff) / spill_tolerance; + } + + + if(h < 0.0) h += 360.0; + +// store new color + color2.r = h; + color2.g = s; + color2.b = v; + color2 = hsv_to_rgb(color2); + color.rgb = rgb_to_yuv(color2).rgb; + } + } + + + + a += alpha_offset; + a = min(a, 1.0); + color.a = a; +/* Convert mask into image */ + gl_FragColor = show_mask(color, color2); +} + +