Chroma Key Shader

Chroma Key in unity 3d. I’m surprised to see so many chroma key shaders on the unity asset store. The chroma key shader isn’t anything revolutionary, and there are plenty of resources online to use when creating your shader. Most notably, :http://pilcrowpipe.blogspot.jp/2013/03/chroma-keying-transparent-background.html . This is going to be the first written tutorial that I did so please don’t judge too harshly. The Unity Shader code can be found on :https://unexpectedend.wordpress.com/2014/11/04/unity3d-chroma-key-shader/ but I wanted to describe the translation between Open GL shaders to Unity. The screen grabs below are from the Open Gl Shader in the first linked blog. This shader also works in Unity 5 . There are some assets offer Chroma Key for Unity 5 but this one is probably the simplest and it’s free.

static const char videoPlaybackFragmentShader[] =
"#extension GL_OES_EGL_image_external : require \n"
"precision mediump float; \n"
"uniform samplerExternalOES texSamplerOES; \n"
" varying vec2 texCoord;\n"
" varying vec2 texdim0;\n"
" void main()\n\n"
" {\n"
" vec3 keying_color = vec3(%f, %f, %f);\n"
" float thresh = 0.8; // [0, 1.732]\n"
" float slope = 0.2; // [0, 1]\n"
" vec3 input_color = texture2D(texSamplerOES, texCoord).rgb;\n"
" float d = abs(length(abs(keying_color.rgb - input_color.rgb)));\n"
" float edge0 = thresh * (1.0 - slope);\n"
" float alpha = smoothstep(edge0, thresh, d);\n"
" gl_FragColor = vec4(input_color, alpha);\n"
}";

So now lets take the time to translate this code into Unity’s shader language.

First lets get a better understanding shader code.

Start off by writing shader and then a path with a name.

Shader “Custom/ChromaKey” {

This allows are shader to exist. The path name is where the shader will appear.

Next we have to give our shader some properties. The properties are just translated from the Open GL code to Unities shader code:

Open GL

vec3 keying_color = vec3(%f, %f, %f);\n"
" float thresh = 0.8; // [0, 1.732]\n"
" float slope = 0.2; // [0, 1]\n"

Unity:

Properties {

_MainTex ("Base (RGB)", 2D) = "white" {}
_thresh ("Threshold", Range (0, 16))
_slope ("Slope", Range (0, 1))
_keyingColor ("Key Colour", Color) = (1,1,1,1)
}

We also included a MainText so that we could pass the original image into the texture. Now we start with the SubShader. This is where all the code is going to go. The tags are the rendering type of the material. These Properties are written in strings so you will have to use the double quotation. The tags that we are going to use in this demonstration are exactly the same as in the Unlit Transparent texture .

SubShader {

Tags {"Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent"}

We are going to use CG for this shader because it is the most common shader language , There are other languages such as GLSL and Open GL. So you have to declare that it is a CG shader program. What you need to do for CG programing is that you tell the graphics card that this is a shader program but you have to follow it up by writing ENDCG.

A Pragma is telling unity that we are using a shader type in our shader. In this case we are going to try to create a low GPU shader so we will specify the following pragmas.

Lastly we are going to tell the shader that we want to use the variables that we specified earlier . And we have to define their type.

A float is a float and a float3 has 3 perimeters and a float 4 has 4 float perimeters.

Lighting Off
ZWrite Off
AlphaTest Off
Blend SrcAlpha OneMinusSrcAlpha

Pass {
CGPROGRAM
#pragma vertex vert_img
#pragma fragment frag
#pragma fragmentoption ARB_precision_hint_fastest

sampler2D _MainTex;
float3 _keyingColor;
float _thresh;
float _slope;

Next we want to say that we are going to include unities native functions and predefined shader variables. This is achieved by writing #include “UnityCG.cginc”

Then we are going to do the same functions as the open Gl shader did.

Original

float d =[URL='http://unity3d.com/support/documentation/ScriptReference/30_search.html?q=length']length[/URL](_keyingColor.rgb- input_color.rgb);"
" float edge0 = thresh * (1.0 - slope);"
" float alpha = smoothstep(edge0, thresh, d);"
" gl_FragColor = vec4(input_color, alpha);"

Unity

#include "UnityCG.cginc"

float4 frag(v2f_img i) : COLOR{
float3 input_color = tex2D(_MainTex,i.uv).rgb * _Color;
float d = abs(length(abs(_keyingColor.rgb - input_color.rgb)));
float edge0 = _thresh*(1 - _slope);
float alpha = smoothstep(edge0,_thresh,d);
return float4(input_color,alpha);

Complete Code

Shader"Custom/ChromaKey" {

Properties {
_MainTex ("Base (RGB)", 2D) = "white" {}
_thresh ("Threshold", Range (0, 16)) = 0.65
_slope ("Slope", Range (0, 1)) = 0.63
_keyingColor ("KeyColour", Color) = (1,1,1,1)
}

SubShader {
Tags {"Queue"="Transparent""IgnoreProjector"="True""RenderType"="Transparent"}
LOD100

LightingOff
ZWriteOff
AlphaTestOff
BlendSrcAlphaOneMinusSrcAlpha

Pass {
CGPROGRAM
#pragmavertexvert_img
#pragmafragmentfrag
#pragmafragmentoptionARB_precision_hint_fastest

sampler2D_MainTex;
float3_keyingColor;
float_thresh; //0.8
float_slope; //0.2

#include "UnityCG.cginc"

float4frag(v2f_imgi) : COLOR{
float3input_color = tex2D(_MainTex,i.uv).rgb;
floatd = abs(length(abs(_keyingColor.rgb - input_color.rgb)));
floatedge0 = _thresh*(1 - _slope);
floatalpha = smoothstep(edge0,_thresh,d);
returnfloat4(input_color,alpha);

}

ENDCG
}
}

FallBack"Unlit/Texture"
}