オノッチ https://twitter.com/onotchi_ さんのこちら http://onoty3d.hatenablog.com/entry/2016/02/06/141002 の記事を元にして、クロマキー合成(クロマキー透過)ではなくクロマキー抽出で肌の色を取り出すシェーダを作ってみた
ChromaKeyOverlay.shader
Shader "Custom/ChromaKeyOverlay" {
Properties{
_KeyColor("Key Color", Color) = (0,1,0)
_HueNear("Hue Near", Range(0, 0.5)) = 0.1
_SatNear("Saturation Near", Range(0, 0.5)) = 0.1
_MainTex("Base (RGB) Trans (A)", 2D) = "white" {}
}
SubShader{
Tags{ "Queue" = "Transparent" "IgnoreProjector" = "True" "RenderType" = "Transparent" }
CGPROGRAM
#pragma surface surf Lambert alpha
sampler2D _MainTex;
fixed3 _KeyColor;
fixed _HueNear;
fixed _SatNear;
struct Input {
float2 uv_MainTex;
};
fixed GetHue(fixed3 rgb) {
fixed hue = 0;
fixed minValue = min(rgb.r, min(rgb.g, rgb.b));
fixed maxValue = max(rgb.r, max(rgb.g, rgb.b));
fixed delta = maxValue - minValue;
if (delta != 0) {
if (maxValue == rgb.r) {
hue = (rgb.g - rgb.b) / delta;
}
else if (maxValue == rgb.g) {
hue = 2.0 + (rgb.b - rgb.r) / delta;
}
else {
hue = 4.0 + (rgb.r - rgb.g) / delta;
}
hue /= 6.0;
if (hue < 0) {
hue += 1.0;
}
}
return hue;
}
fixed GetSaturation(fixed3 rgb) {
fixed sat = 0;
fixed minValue = min(rgb.r, min(rgb.g, rgb.b));
fixed maxValue = max(rgb.r, max(rgb.g, rgb.b));
sat = (maxValue - minValue) / maxValue;
return sat;
}
void surf(Input IN, inout SurfaceOutput o) {
fixed4 c = tex2D(_MainTex, IN.uv_MainTex);
fixed distance = GetHue(c.rgb) - GetHue(_KeyColor);
fixed distance2 = GetSaturation(_KeyColor)- GetSaturation(c.rgb);
fixed alpha = 0.0;
if (distance > 0.5) {
distance = 1.0 - distance;
}
else if (distance < -0.5) {
distance = 1.0 + distance;
}
else {
distance = abs(distance);
}
clip(_HueNear - distance);
clip(_SatNear - distance2);
alpha = ((_HueNear - distance)/ _HueNear +(_SatNear - distance2)/ _SatNear)*1.0;
o.Albedo = c.rgb;
o.Alpha = alpha;
}
ENDCG
}
Fallback "Transparent/Diffuse"
}
Webカメラ画像をリアルタイム表示するRenderTextureにこのシェーダーを適用したマテリアルを割り当てると、手など肌の色だけが取り出されて他の部分は透過になる