Search Unity

Texture with solid color for image's alpha?

Discussion in 'Shaders' started by mbowen89, Jul 18, 2014.

  1. mbowen89

    mbowen89

    Joined:
    Jan 21, 2013
    Posts:
    639
    OK, I don't know if it's just too late or I'm stupid.

    Basically here is my issue simplified. Lets say I have a plane, and I UV mapped it, that works great. My texture is just a big red circle with alpha around it.

    If I use a diffuse shader, it works great, but all the alpha does is become black. If I change the color in the diffuse shader, it changes the tint of the red texture, but the alpha is all black. What if I wanted the alpha to be orange? Basically I want my texture to apply to a background color material like a big sticker, that I change the color of.

    I'd actually want it to be specular on the background color and image.

    I've played with all the standard shaders and nothing seems to be like this. I'm pretty sure I could write my own CG shader, but I want to make sure I'm not going crazy first.

    Thanks for any insight!

    -Michael
     
  2. mbowen89

    mbowen89

    Joined:
    Jan 21, 2013
    Posts:
    639
    Well, I ended up just modifying the standard specular shader to do what I wanted:

    Code (CSharp):
    1. Shader "Custom/Sticker Specular" {
    2. Properties {
    3.     _Color ("Main Color", Color) = (1,1,1,1)
    4.     _SpecColor ("Specular Color", Color) = (0.5, 0.5, 0.5, 1)
    5.     _Shininess ("Shininess", Range (0.03, 1)) = 0.078125
    6.     _MainTex ("Base (RGB) Gloss (A)", 2D) = "white" {}
    7. }
    8. SubShader {
    9.     Tags { "RenderType"="Opaque" }
    10.     LOD 400
    11.  
    12. CGPROGRAM
    13. #pragma surface surf BlinnPhong
    14.  
    15.  
    16. sampler2D _MainTex;
    17. fixed4 _Color;
    18. half _Shininess;
    19.  
    20. struct Input {
    21.     float2 uv_MainTex;
    22. };
    23.  
    24. void surf (Input IN, inout SurfaceOutput o) {
    25.     fixed4 tex = tex2D(_MainTex, IN.uv_MainTex);
    26.     if (tex.r < 0.01 && tex.g < 0.01 && tex.b < 0.01) {
    27.         o.Albedo = _Color.rgb;
    28.     } else {
    29.         o.Albedo = tex.rgb;
    30.     }
    31.  
    32.     o.Gloss = tex.a;
    33.     o.Alpha = tex.a * _Color.a;
    34.     o.Specular = _Shininess;
    35. }
    36. ENDCG
    37. }
    38.  
    39. FallBack "Specular"
    40. }
    41.  
    So basically I just detect if the color in the texture is pretty much pure black, and if it is that is the "transparent" area around the image I want to be the color set by _Color. I get specular on the image and surrounding colored area this way.

    Can anyone tell me why this didn't work though:

    if (tex.a < 0.1 ) {
    o.Albedo = _Color.rgb;
    } else {
    o.Albedo = tex.rgb;
    }

    I had to replace the alpha with black and remove alpha channel from my png and then check if it was black, it's like it never would realize there was an alpha value or something.

    Is this the best way to do this? I'm not sure how bad it is to use the if else like that...
     
  3. msl_manni

    msl_manni

    Joined:
    Jul 5, 2011
    Posts:
    272
    Try the following, replace the if with the following code. It should work.

    o.Albedo = (tex.rgb * tex.a) + ((1 - tex.a) * _Color.rgb);
     
  4. mbowen89

    mbowen89

    Joined:
    Jan 21, 2013
    Posts:
    639
    Thanks, it worked!

    So basically if you can think of "math" to do the trick of if/else statements, it's a lot more efficient as well?
     
  5. msl_manni

    msl_manni

    Joined:
    Jul 5, 2011
    Posts:
    272
    If you can think in Maths then you can solve very large if/else into a compact form. :)