** http://irrlicht.sourceforge.net/phpBB2/viewtopic.php?t=21057
*/
- vec3 ContrastSaturationBrightness(vec3 color, float brt, float sat, float con)
+ vec3 ContrastSaturationBrightness(vec4 color, float brt, float sat, float con)
{
const float AvgLumR = 0.5;
const float AvgLumG = 0.5;
? vec3(0.0722, 0.7152, 0.2126)
: vec3(0.114, 0.587, 0.299);
+ if (color.a > 0.0)
+ color.rgb /= color.a;
+
vec3 AvgLumin = vec3(AvgLumR, AvgLumG, AvgLumB);
- vec3 brtColor = color * brt;
+ vec3 brtColor = color.rgb * brt;
vec3 intensity = vec3(dot(brtColor, LumCoeff));
vec3 satColor = mix(intensity, brtColor, sat);
vec3 conColor = mix(AvgLumin, satColor, con);
+
+ conColor.rgb *= color.a;
+
return conColor;
}
// by F. van den Bergh & V. Lalioti
// but as a pixel shader algorithm.
//
-
- float chroma_blend_w = chroma_blend.y - chroma_blend.x;
- const vec4 grey_xfer = vec4(0.3, 0.59, 0.11, 0.0);
-
- float fma(float a, float b, float c) { return a*b + c; }
+ vec4 grey_xfer = is_hd
+ ? vec4(0.2126, 0.7152, 0.0722, 0)
+ : vec4(0.299, 0.587, 0.114, 0);
// This allows us to implement the paper's alphaMap curve in software
// rather than a largeish array
float alpha_map(float d)
{
- return 1.0-smoothstep(chroma_blend.x, chroma_blend.y, d);
+ return 1.0 - smoothstep(1.0, chroma_softness, d);
+ }
+
+ // http://stackoverflow.com/questions/15095909/from-rgb-to-hsv-in-opengl-glsl
+ vec3 rgb2hsv(vec3 c)
+ {
+ vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
+ vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));
+ vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));
+
+ float d = q.x - min(q.w, q.y);
+ float e = 1.0e-10;
+ return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);
+ }
+
+ // From the same page
+ vec3 hsv2rgb(vec3 c)
+ {
+ vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
+ vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
+ return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
+ }
+
+ float AngleDiff(float angle1, float angle2)
+ {
+ return 0.5 - abs(abs(angle1 - angle2) - 0.5);
}
- vec4 supress_spill(vec4 c, float d)
+ float AngleDiffDirectional(float angle1, float angle2)
{
- float ds = smoothstep(chroma_spill, 1.0, d/chroma_blend.y);
- float gl = dot(grey_xfer, c);
- return mix(c, vec4(vec3(gl*gl), gl), ds);
+ float diff = angle1 - angle2;
+
+ return diff < -0.5
+ ? diff + 1.0
+ : (diff > 0.5 ? diff - 1.0 : diff);
+ }
+
+ float Distance(float actual, float target)
+ {
+ return min(0.0, target - actual);
}
- // Key on green
- vec4 ChromaOnGreen(vec4 c)
+ float ColorDistance(vec3 hsv)
{
- float d = fma(2.0, c.g, -c.r - c.b)/2.0;
- c *= alpha_map(d);
- return supress_spill(c, d);
+ float hueDiff = AngleDiff(hsv.x, chroma_target_hue) * 2;
+ float saturationDiff = Distance(hsv.y, chroma_min_saturation);
+ float brightnessDiff = Distance(hsv.z, chroma_min_brightness);
+
+ float saturationBrightnessScore = max(brightnessDiff, saturationDiff);
+ float hueScore = hueDiff - chroma_hue_width;
+
+ return -hueScore * saturationBrightnessScore;
}
- //Key on blue
- vec4 ChromaOnBlue(vec4 c)
+ vec3 supress_spill(vec3 c)
{
- float d = fma(2.0, c.b, -c.r - c.g)/2.0;
- c *= alpha_map(d);
- return supress_spill(c, d);
+ float hue = c.x;
+ float diff = AngleDiffDirectional(hue, chroma_target_hue);
+ float distance = abs(diff) / chroma_spill_suppress;
+
+ if (distance < 1)
+ {
+ c.x = diff < 0
+ ? chroma_target_hue - chroma_spill_suppress
+ : chroma_target_hue + chroma_spill_suppress;
+ c.y *= min(1.0, distance + chroma_spill_suppress_saturation);
+ }
+
+ return c;
+ }
+
+ // Key on any color
+ vec4 ChromaOnCustomColor(vec4 c)
+ {
+ vec3 hsv = rgb2hsv(c.rgb);
+ float distance = ColorDistance(hsv);
+ float d = distance * -2.0 + 1.0;
+ vec4 suppressed = vec4(hsv2rgb(supress_spill(hsv)), 1.0);
+ float alpha = alpha_map(d);
+
+ suppressed *= alpha;
+
+ return chroma_show_mask ? vec4(suppressed.a, suppressed.a, suppressed.a, 1) : suppressed;
}
)shader";