Search Unity

Using a texture's RGB as an Alpha

Discussion in 'Shaders' started by vinceparker, Jun 21, 2008.

  1. vinceparker

    vinceparker

    Joined:
    Oct 11, 2007
    Posts:
    7
    What is the code for using the RGB channels of a texture in the alpha channel?
    I'm looking to use a greyscale ogg movie as an animated alpha channel. I know that you can pull the alpha information into the color channels by using:

    Code (csharp):
    1. Combine texture alpha, texture
    Is there an equivalent for referencing the RGB of a texture?

    -Vince
     
  2. Aras

    Aras

    Unity Technologies

    Joined:
    Nov 7, 2005
    Posts:
    4,770
    It's not easily possible in a fixed function texture combiner. It's easy in a fragment program though, just read texture and use the colors any way you like. For example:
    Code (csharp):
    1.  
    2. half4 color = tex2D(_MainTex, i.uv);
    3. // output RGB color, and R as alpha
    4. return half4(color.r, color.g, color.b, color.r);
    5.  
     
  3. mattimus

    mattimus

    Joined:
    Mar 8, 2008
    Posts:
    576
    I'm trying to do something similar, but I'd like to use a texture's RGB as three alphas (see img 1).

    The idea is to create an object with three random colors assigned. Right now, I can modify the whole texture's color with a random (img 2) by shifting the base color:

    Code (csharp):
    1. function Start () {
    2.     var color = Color(Random.Range(.1,.8), Random.Range(.1,.8), Random.Range(.1,.8));
    3.     renderer.material.SetColor ("_Color", color);
    4. }
    Rather than using the object's main color, I'd like to use the individual R, G, and B channels to mask out three random colors that would replace the RGB texture (img 3). I'd like it if the random colors could mix on areas that have varied RGB values (such as (255,150,20), etc) but at this point I'd easily settle for an aliased mask. The white portion of the example texture is an experiment to see what happens with mixed RGB values.
     

    Attached Files:

  4. mattimus

    mattimus

    Joined:
    Mar 8, 2008
    Posts:
    576
    Sucess!

    after about 4 hours and much dueling between my head and a proverbial brick wall, I came up with this. It seems to work out great.

    Code (csharp):
    1. function Start () {
    2.     // duplicate the original texture and assign to the material
    3.     var texture : Texture2D = Instantiate(renderer.material.mainTexture);
    4.     renderer.material.mainTexture = texture;
    5.    
    6.     var randRed = Color(Random.Range(.1,1), Random.Range(.1,1), Random.Range(.1,1));
    7.     var randGreen = Color(Random.Range(.1,1), Random.Range(.1,1), Random.Range(.1,1));
    8.     var randBlue = Color(Random.Range(.1,1), Random.Range(.1,1), Random.Range(.1,1));
    9.     var randWhite = Color(Random.Range(.1,1), Random.Range(.1,1), Random.Range(.1,1));
    10.  
    11.  
    12.         var cols = texture.GetPixels();
    13.         for( var i = 0; i < cols.Length; ++i ) {
    14.            
    15.             //white pixels
    16.             if ((cols[i].r > .8)(cols[i].g > .8)(cols[i].b > .8))
    17.                 cols[i] = randWhite;
    18.                
    19.             //red pixels
    20.             else if (cols[i].r > .8)
    21.                 cols[i] = randRed;
    22.                
    23.             //green pixels
    24.             else if (cols[i].g > .8)
    25.                 cols[i] = randGreen;
    26.            
    27.             //blue pixels
    28.             else if (cols[i].b > .8)
    29.                 cols[i] = randBlue;
    30.         }          
    31.            
    32.         texture.SetPixels( cols );
    33.    
    34.     // actually apply all SetPixels, disregard mips
    35.     texture.Apply( false );  
    36. }
     
  5. bliprob

    bliprob

    Joined:
    May 13, 2007
    Posts:
    901
    I thought I'd give Aras' shader code a try, and make a chroma-key shader that turns green into an alpha value. I basically copied and pasted his two lines into a generic shader shell. However, surprise, it fails to compile. I get errors like:

    Can anyone explain what function reference I overloaded? And why there are too few parameters when it makes the half4?


    Code (csharp):
    1.  
    2. Shader "GreenToAlpha" {
    3.     Properties {
    4.         _MainTex ("Base (RGB)", 2D) = "white" {}
    5.     }
    6.     SubShader {
    7.         Pass {
    8. CGPROGRAM
    9. #pragma fragment frag
    10. #include "UnityCG.cginc"
    11.  
    12. sampler2D _MainTex;
    13.  
    14. struct v2f {
    15.     float4 pos : POSITION;
    16.     float4 uv : TEXCOORD0;
    17. };
    18.  
    19. half4 frag (v2f i) : COLOR
    20. {
    21.     half4 color = tex2D(_MainTex, i.uv);
    22.     return half4(color.r, color.g, color.b, color.g);
    23. }
    24. ENDCG
    25.         } // pass
    26.     } // subshader
    27.     Fallback off
    28. } // shader
    29.  
    30.  
     
  6. Aras

    Aras

    Unity Technologies

    Joined:
    Nov 7, 2005
    Posts:
    4,770
    I think texture sampling needs to be:
    Code (csharp):
    1. tex2D(_MainTex, i.uv.xy);
    Since 'uv' is a float4, and sampling a 2D texture needs two coordinates, not four.
     
  7. bliprob

    bliprob

    Joined:
    May 13, 2007
    Posts:
    901
    Success! Thanks Ara, that cleared up all but one of the errors. I still get "no subshaders can run on this graphics card", which is bizarre, because the shader works. And every other shader works (including the fractal shader from another thread) on my gear (MacBook Pro, ATI Radeon X1600).

    Code (csharp):
    1.  
    2. Shader "FX/GreenToAlpha" {
    3.  
    4. Properties {
    5.     _MainTex ("Base (RGB)", 2D) = "white" {}
    6.     _Cutoff ("Cutoff", Range (0,1)) = .5
    7. }
    8.  
    9. SubShader {
    10.  
    11.    Pass {
    12.    
    13. CGPROGRAM
    14. #pragma fragment frag
    15. #include "UnityCG.cginc"
    16.  
    17. sampler2D _MainTex;
    18.  
    19. struct v2f {
    20.     float4 pos : POSITION;
    21.     float4 uv : TEXCOORD0;
    22. };
    23.  
    24. half4 frag (v2f i) : COLOR
    25. {
    26.     half4 color = tex2D(_MainTex, i.uv.xy);
    27.     return half4(color.r, color.g, color.b, color.g - ( (color.r * .5) + (color.b * .5)));
    28.    //return half4(color.r, color.g, color.b, color.g);
    29.  
    30. }
    31. ENDCG
    32.         AlphaTest Less [_Cutoff]
    33.         } // pass
    34.     } // subshader
    35.     Fallback "Transparent/Diffuse"
    36. } // shader
    37.  
    I couldn't use the straight green value as the alpha, since it left a green fringe around the edges, and some colors (i.e. white) would result in alpha. This works pretty well. If anyone has a better algorithm for this, let me know.

    Using the Colbert green screen video from another thread, this is what it looks like.

     
  8. Charles Hinshaw

    Charles Hinshaw

    Joined:
    Feb 6, 2008
    Posts:
    1,070
    Today, I think that even the most simple chroma key is doing HSV lookups so that only the hue of a color is used. That way shadows are treated properly and V can be checked so that whites and blacks aren't keyed out. More complex algorithms result in better results though. Try looking here for one http://bmrc.berkeley.edu/courseware/cs294-3/fall97/projects/ashikhmin/

    For another example (Primatte) my understanding is that you are actually creating a series of 3 polyhedra centered on each other in a three dimensional color space and that the 4 color spaces then represent colors ranging from 100% background (inside the smallest) to 100% foreground (outside the largest) with edges and spill suppressed foreground in between.
     
  9. Charles Hinshaw

    Charles Hinshaw

    Joined:
    Feb 6, 2008
    Posts:
    1,070
  10. seabass223

    seabass223

    Joined:
    Aug 11, 2010
    Posts:
    1
    Similarly
    you could test for the color value range as seen in the if statement below. If the colors reach the value that you wish to alpha out, simply return 0 as the alpha param. Great work everybody!

    Code (csharp):
    1. Shader "Particles/SplitAlpha"
    2. {
    3. Properties
    4. {
    5.     _MainTex ("Base (RGB)", 2D) = "black" {}
    6.     _Cutoff ("Cutoff", Range (0,1)) = .5
    7. }
    8.  
    9. SubShader
    10. {
    11.     Tags {"Queue"="Transparent"}
    12.  
    13.     ZWrite Off
    14.     Blend SrcAlpha OneMinusSrcAlpha
    15.  
    16.     Pass
    17.     {    
    18.         CGPROGRAM
    19.             #pragma fragment frag
    20.             #include "UnityCG.cginc"  
    21.  
    22.             sampler2D _MainTex;
    23.  
    24.             struct v2f
    25.             {
    26.                 float4 pos : POSITION;
    27.                 float4 uv : TEXCOORD0;
    28.                 float4 uv2 : TEXCOORD1;                
    29.             };
    30.  
    31.             half4 frag (v2f i) : COLOR
    32.             {
    33.                 half4 color = tex2D(_MainTex, i.uv.xy);
    34.                
    35.                 if(color.rgb <= .5){
    36.                     return half4(color.r, color.g, color.b, 0);
    37.                 }
    38.                 else{
    39.                     return half4(color.r, color.g, color.b, 1);
    40.                 }
    41.             }
    42.         ENDCG        
    43.     }    
    44. }
    45.  
    46. Fallback "Transparent/Diffuse"
    47. }
    48.  
     
  11. BloodArk

    BloodArk

    Joined:
    Jun 27, 2011
    Posts:
    2
    Hello

    How could i use your shaders on a video (avi or mov) ???
    I don't know how to apply a shader to a video in Unity :(

    Please help

    Thanks

    BloodArk
     
  12. rmagnatera

    rmagnatera

    Joined:
    Mar 6, 2013
    Posts:
    1
    hi you have the project?
     
  13. wccrawford

    wccrawford

    Joined:
    Sep 30, 2011
    Posts:
    2,039
    You just resurrected a thread from 5 years ago which has failed to get any replies after being resurrected twice before.