1. Help us improve the editor usability and artist workflows. Join our discussion to provide your feedback.
    Dismiss Notice
  2. We're looking for feedback on Unity Starter Kits! Let us know what you’d like.
    Dismiss Notice
  3. We’re giving 2017.1 beta testers a chance to win t-shirts and a Nintendo Switch. Read more on the blog.
    Dismiss Notice
  4. Unity 2017.1 beta is now available for download.
    Dismiss Notice
  5. Unity 5.6 is now released.
    Dismiss Notice
  6. Get further faster with the Unity Plus Accelerator Pack, free for new Unity Plus subscribers for a limited time. Click here for more details.
    Dismiss Notice
  7. Check out all the fixes for 5.6 on the patch releases page.
    Dismiss Notice
  8. Learn how you'll soon be able to publish your games to China in four simple steps with Xiaomi. Sign up now for early access.
    Dismiss Notice

@ chroma key shader with any colours

Discussion in 'Shaders' started by PSpiroz, Mar 17, 2017.

  1. PSpiroz


    Feb 15, 2015
    Two things into one:
    1) Can there be a chroma key shader that I choose what solid colour (even under restrictions) will turn to transparent by entering key code values from inspector? Example not green but also custom pink, yellow, etc.
    2) Can there be a chroma key shader that can "key" two different colours to transparent? example. Green and Blue?
    3) Can there be a shader that combines two two above (example picture)?

    Please anyone have a shader script of any, or instructions will help because I don;t understand how to write shader code.

    Attached Files:

  2. goal2112


    May 8, 2013
    1) Yes. You can set chroma keying to be done for any color. I've personally used even a full texture for keying rather than a particular color. If your camera is fixed you can have it take a picture of the set without your subject, and then use each pixel of that as your key.

    2) If you wanna key out 2 particular colors per pixel then the cost grows, but yes, it's doable.

    3) I think your example kind of asks more for what I described in 1, unless your camera has to move. Either way, yes.

    The way to perform keying accurately is to convert each RGB color space pixel into "Lab" color space values, and then find the "distance" between the values. You can find more specifics here: http://www.brucelindbloom.com/index.html?Equations.html

    The steps you'd need to run through are as follows:
    1. Convert your destination color (key color) to XYZ, and then to Lab.
    2. Do the same with your source color (texture you want parts of keyed out).
    3. Use Delta E (CIE 1994) to calculate the overall difference in the color to determine how transparent the pixel should be. Lower values approaching 0 should be more transparent, higher values more opaque. There are other Delta E that improve on accuracy at the cost of performance. It's up to you to choose which one you can afford to use.
    4. Return your source color with the newly calculated alpha.

    Done! :)
    PSpiroz likes this.
  3. PSpiroz


    Feb 15, 2015
    Thank you very much.
    Very interesting what your (Goal2112) replying. These are concepts I have never though I should take under consideration.
    Still I don't get it, and moreover, I don't get how to apply the above in unity.
    I also found this tool: http://colormine.org/delta-e-calculator/cie94
    Never-mind. I think I'll get it as soon as I manage to understand all the previous steps and the mechanism behind it.

    In a more simple version that I don't really understand what I did and need further assistance, I have modified this standard shader chroma key script for green screen:
    Code (CSharp):
    1. Shader "Custom/ChromaKey" {
    2. Properties {
    3.   _MainTex ("Base (RGB)", 2D) = "white" {}
    4.   _AlphaValue ("Alpha Value", Range(0.0,1.0)) = 1.0
    5. }
    6. SubShader {
    7.   Tags { "Queue"="Transparent" "RenderType"="Transparent" }
    8.   LOD 200
    10.   CGPROGRAM
    11.   #pragma surface surf Lambert alpha
    12.   sampler2D _MainTex;
    13.   float _AlphaValue;
    14.   struct Input {
    15.    float2 uv_MainTex;
    16.   };
    17.   void surf (Input IN, inout SurfaceOutput o) {
    18.    half4 c = tex2D (_MainTex, IN.uv_MainTex);
    19.    o.Emission = c.rgb;
    21.    // Green screen level - leaves minor green glow
    22.    if (c.g >= 0.67f && c.r <= 0.65f && c.b <= 0.65f && _AlphaValue == 0.0)
    23.          {
    24.           o.Alpha = 0.0;
    25.          }
    26.          else
    27.          {
    28.           o.Alpha = c.a;
    29.          }
    30.   }
    31.   ENDCG
    32. }
    33. FallBack "Diffuse"
    34. }
    by changing the "if" statement to:

    Code (CSharp):
    1. if ((c.g <= 0.65f && c.r >= 0.67f && c.b <= 0.65f && _AlphaValue == 0.0)|| (c.g >= 0.67f && c.r <= 0.65f && c.b <= 0.65f && _AlphaValue == 0.0))
    that made unity to set alpha == 0 for green and red colour.
    I can assume that c.g / c.r / c.b stands for rgb green / red / blue values in a range of [0,1] instead of [0,255].

    My question are
    1) How to set / calculate these equations lets say for pink colour.
    2) What is the memory cost? Is it just almost the same with the original script or it is double the cost?
    3) The author of the original script refers that his equation "..leaves a minor green glow" . How can we control / omit this glow, as well as other colour attributes?
  4. NikhilUnity


    Dec 28, 2015
    I figured it out. Here is the code, btw I have no idea of how to do shaders and I wanted this as well. After looking at various syntaxes, I figured it out myself:

    Code (CSharp):
    1. Shader "Custom/ChromaKey" {
    3. Properties {
    4.   _MainTex ("Base (RGB)", 2D) = "white" {}
    5.   _AlphaValue ("Alpha Value", Range(0.0,1.0)) = 1.0
    6.   _Color("Color", Color) = (1,1,1,1)
    8. }
    10. SubShader {
    11.   Tags { "Queue"="Transparent" "RenderType"="Transparent" }
    12.   LOD 200
    14.   CGPROGRAM
    15.   #pragma surface surf Lambert alpha
    16.   sampler2D _MainTex;
    17.   float _AlphaValue;
    18.   float4 _Color;
    20.   struct Input {
    21.    float2 uv_MainTex;
    22.   };
    23.   void surf (Input IN, inout SurfaceOutput o) {
    24.    half4 c = tex2D (_MainTex, IN.uv_MainTex);
    25.    o.Emission = c.rgb;
    27.    // Green screen level - leaves minor green glow
    28.    // Note how the green value operator check is greater than and rest is less than
    29.    if (c.g >= _Color.g && c.r <= _Color.r && c.b <= _Color.b)
    30.          {
    31.           o.Alpha = 0.0;
    32.          }
    33.          else
    34.          {
    35.           o.Alpha = c.a;
    36.          }
    37.   }
    38.   ENDCG
    39. }
    40. FallBack "Diffuse"
    41. }
    Now you can choose any color and it will work.
  5. jvo3dc


    Oct 11, 2013
    That is a very poor approach to a chroma key shader. Like goal2112 said, you want to enable partial transparency and you want to use a color space other than rgb to make the comparison more stable under varying shadows and lighting.