How to remove complete green background of video

Hi,
I am developing an app with unity. In that, I want to remove the green background of the video and should make transparent. I have used shader script to remove the background. It’s removing background but still, it’s not clearing border of the content.

I used this script please tell any correction in this or tell me any other best way to do that

Shader "Custom/ChromaKey" {
Properties {
  _MainTex ("Base (RGB)", 2D) = "white" {}
  _AlphaValue ("Alpha Value", Range(0.0,1.0)) = 1.0
}
SubShader {
  Tags { "Queue"="Transparent" "RenderType"="Transparent" }
  LOD 800
  CGPROGRAM
  #pragma surface surf Lambert alpha
  sampler2D _MainTex;
  float _AlphaValue;
  struct Input {
   float2 uv_MainTex;
  };
  void surf (Input IN, inout SurfaceOutput o) {
   half4 c = tex2D (_MainTex, IN.uv_MainTex);
   o.Emission = c.rgb;
   // Green screen level - leaves minor green glow
   if (c.g == 1) {
       o.Alpha = 0.0;
   }else{
       o.Alpha = c.a;
   }
  }
  ENDCG
}
FallBack "Diffuse"
}

Hi ssuresh1295,

if it’s one-pixel border that this doesn’t remove (and it seems so to me) then you probably need to sample more texels than just the current one. The border will likely not be completely green, so you can take a look on some texels around the one you’re sampling already (3x3 area, for example). If the majority of the pixels are green, this pixel can be considered part of the background.
Btw, the check you have will work for fully white pixels as well, so it’s probably a good idea to check full rgb value.

1 Like

Using c.g == 1 to determine green is pretty ridiculous. It for one thing considers pure yellow or white to also be green. But #00FE00 would be considered not green at all.

What you want is to specify a reference color and falloff. And fade transparency based on that:

half alpha_pass = saturate(distance(c.rgb, _AlphaColor) / _AlphaFalloff); // Amount of not matching the color
c.a *= alpha_pass; // Adjustment of alpha
half alpha_pass_limit = max(0.1, alpha_pass); // Prevents a division by zero
c.rgb = (c.rgb - (1 - alpha_pass_limit) * _AlphaColor) / alpha_pass_limit; // Adjustment of color

Where _AlphaColor is a half3 color input for the color to remove and _AlphaFalloff a half input for the range to remove. I just made up those last two lines to adjust the color, but if my math is right, it should work. Note that this is still a pretty simple approach to a green screen shader, but it should be half decent.

Hi jvo3dc,

Where should I add this code in my script.

Between half4 c=… and o.Emission=…

The whole if below that should then be replaced by just:

o.Alpha = c.a;

Hi jvo3dc,

I used your code but now video not even showing. Fully came with the white screen only audio is coming. I used your code like this please tell any wrong on this

Shader "Custom/ChromaKey" {
 
Properties {
  _MainTex ("Base (RGB)", 2D) = "white" {}
  _AlphaValue ("Alpha Value", Range(0.0,1.0)) = 1.0
  _Threshold ("Threshold Value", Range(0.0,1.0)) = 1.0
}
 
SubShader {
  Tags { "Queue"="Transparent" "RenderType"="Transparent" }
  LOD 800
  
  CGPROGRAM
  #pragma surface surf Lambert alpha
  sampler2D _MainTex;
  float _AlphaValue;
  struct Input {
   float2 uv_MainTex;
  };
  void surf (Input IN, inout SurfaceOutput o) {
   half4 c = tex2D (_MainTex, IN.uv_MainTex);
   o.Emission = c.rgb;
   
   // Green screen level - leaves minor green glow
   //c.g >= 0.39215686274f && c.r <= 0.0f && c.b <= 0.0f && _AlphaValue == 0.0
   if (c.g == 1) {
       o.Alpha = 0.0;
       //o.glow = 1;
   }else{
       //o.Alpha = c.a;
        half alpha_pass = saturate(distance(c.rgb, _AlphaColor) / _AlphaFalloff); // Amount of not matching the color
        c.a *= alpha_pass; // Adjustment of alpha
        half alpha_pass_limit = max(0.1, alpha_pass); // Prevents a division by zero
        c.rgb = (c.rgb - (1 - alpha_pass_limit) * _AlphaColor) / alpha_pass_limit; // Adjustment of color
   }
  }
  ENDCG
}
FallBack "Diffuse"
}
void surf (Input IN, inout SurfaceOutput o) {
   half4 c = tex2D (_MainTex, IN.uv_MainTex);
   half alpha_pass = saturate(distance(c.rgb, _AlphaColor) / _AlphaFalloff); // Amount of not matching the color
   c.a *= alpha_pass; // Adjustment of alpha
   half alpha_pass_limit = max(0.1, alpha_pass); // Prevents a division by zero
   c.rgb = (c.rgb - (1 - alpha_pass_limit) * _AlphaColor) / alpha_pass_limit; // Adjustment of color
   o.Emission = c.rgb;
   o.Alpha = c.a;
}

Tried this also but same white screen only coming. If there is no if conditio then how can I check my green color to remove.

Well, you’re doing something else wrong, since your code before just said:

half4 c = tex2D (_MainTex, IN.uv_MainTex);
o.Emission = c.rgb;

After you’ve fixed whatever is going wrong, what are your values of _AlphaColor and _AlphaFallof?

Finally, there is no reason to use an if to replace a color with transparency. It’s like fuzzy logic.

I want remove r= 0, g=255 , b=0 This rgb value I want to remove. How to give value for that.

Set _AlphaColor to 0, 1, 0 and then play with the _AlphaFalloff value. (Between 0 and 1 roughly)

@jvo3dc
I have tried Like this

 half4 c = tex2D (_MainTex, IN.uv_MainTex);
   half alpha_pass = saturate(distance(c.rgb, 0, 1, 0) / 1); // Amount of not matching the color

And this

half4 c = tex2D (_MainTex, IN.uv_MainTex);
   half alpha_pass = saturate(distance(0, 1, 0, 0) / 1); // Amount of not matching the color

But I am getting following error at compile time for both

Shader error in ‘Custom/ChromaKeyWhite’: unable to find compatible overloaded function “distance(half3, int, int, int)” unable to find compatible overloaded function “saturate(error)” at line 39 (on d3d9)

Well, distance takes 2 parameters of the same vector type and not 4 parameters. So
distance (c.rgb, half3 (0.0, 1.0, 0.0))

I managed to get it working but my model shows white instead of its normal albedo colors.