Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

if...then...else...if...then.. performance within Shader

Discussion in 'Shaders' started by alejobrainz, Feb 16, 2015.

  1. alejobrainz

    alejobrainz

    Joined:
    Sep 10, 2005
    Posts:
    288
    Hello.

    I'm trying to make a pixel shader that shifts the color of the texture based on a grayscale mask when we set certain areas to certain shades of grey (example mask attached). As I understand if then statements within a surf method in a shader are really bad and I wanted to know if you guys can suggest better alternatives to something like this:

    half3col = ( (mask.a <= 0.1 )? shift_col(base.rgb, hsv0) :
    (mask.a <= 0.25)? shift_col(base.rgb, hsv1) :
    (mask.a <= 0.45)? shift_col(base.rgb, hsv2) :
    (mask.a <= 0.65)? shift_col(base.rgb, hsv3) :
    (mask.a <= 0.85)? shift_col(base.rgb, hsv4) :
    shift_col(base.rgb, hsv5) );

    Any ideas are welcome!

    Best,

    Alejandro.
     

    Attached Files:

  2. McDev02

    McDev02

    Joined:
    Nov 22, 2010
    Posts:
    661
    +1 Would also like to get more information on how to do Palette shaders and what performance is like.
    But I also think that branching is bad in shaders. Your question forced me to think about it, thanks for that!
    I just came up with those methods:

    Masks
    You could split your texture in 4 masks per channel (Color1 in Red, Color2 in Blue,Prop in Green and Skin in Alpha). Now Hair would be missing.
    Code (csharp):
    1. half4 col = base;
    2. col = lerp(col,color1, mask.r);
    3. col = lerp(col,color2, mask.g);
    4. col = lerp(col,color3, mask.b);
    5. col = lerp(col,color4, mask.a);
    Texture Palette
    You use a texture for all colors available and sample the texture based on your mask.
    This seems to be a good example: Dithering Shaders
    The downside is that this is not dynamic (except you create palettes dynamically). But I assume you want to have custom colors.

    Color Palette
    Just tested this one and it works great. You would need to set the color in a fraction of all colors you use. For instance color value of about 170 would be color4 (255/6 * 4).
    Here I use ColorArray in the shader.
    Code (csharp):
    1. //Member
    2. fixed4 _Colors[6];
    3.  
    4. //Fragment
    5. half4 col = _Colors[mask * 6];   //We have 6 colors to mask
    The colors can not be set in the material Inspector. You probably want to create your own ShaderGUI script. They have to be set in code like this. Shader arrays are accessed by "nameX" where X is the index.
    Code (csharp):
    1. Color[] m_Colors;
    2. Material m_Mat;
    3.  
    4. for ( int i = 0; i < 6; i++ )
    5. {
    6.    m_Mat.SetColor ( "_Colors" + i, m_Colors[i] );
    7. }
     
    Last edited: Feb 17, 2015
    alejobrainz likes this.
  3. alejobrainz

    alejobrainz

    Joined:
    Sep 10, 2005
    Posts:
    288
    Hi. This approach greatly increased performance (about 10fps -> 30 fps):

    half3 col = lerp(base.rgb, shift_col(base.rgb, hsv1), mask.r);
    col = lerp(col, shift_col(base.rgb, hsv2), mask.g);
    col = lerp(col, shift_col(base.rgb, hsv3), mask.b);
    col = lerp(col, shift_col(base.rgb, hsv4), maska);

    Thanks again!!
     
  4. McDev02

    McDev02

    Joined:
    Nov 22, 2010
    Posts:
    661
    That sounds great. This was on mobile I assume?
     
  5. alejobrainz

    alejobrainz

    Joined:
    Sep 10, 2005
    Posts:
    288
    Yes. We will start profiling in different iOS and Android devices. This benchmark was don on a ipad mini retina.
     
  6. McDev02

    McDev02

    Joined:
    Nov 22, 2010
    Posts:
    661
    Maybe you can profile the Color Palette method as well? I can't do that myself.
    If I am right this will be even faster and there are more possibilities.
    If you want I can make a Material Inspector script for you to handle color array.
     
  7. alejobrainz

    alejobrainz

    Joined:
    Sep 10, 2005
    Posts:
    288
    I'm not sure I'm following you, but I'd appreciate understanding a bit more ho the Color Palette Method Works. In essence my shader allows us to recolor areas of a texture using Hue Saturation and Values. I made 3 variants, a diffuse, a specular and a rim specular. Please find them attached for anyone looking for this kind of functionality. Any improvements are appreciated.

    I'm not very experienced in shader dev so any feedback is welcome!

    Cheers.
     

    Attached Files: