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

Grayscale ONLY IF the color != white

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

  1. Mikeysee

    Mikeysee

    Joined:
    Oct 14, 2013
    Posts:
    155
    Hi,

    I have copy-pasted the default unity 2D sprite shader and altered it to make it greyscale:

    Code (CSharp):
    1. Shader "Mr Nbibles/Sprites"
    2. {
    3.     Properties
    4.     {
    5.         [PerRendererData] _MainTex ("Sprite Texture", 2D) = "white" {}
    6.         _Color ("Tint", Color) = (1,1,1,1)
    7.         [MaterialToggle] PixelSnap ("Pixel snap", Float) = 0
    8.     }
    9.  
    10.     SubShader
    11.     {
    12.         Tags
    13.         {
    14.             "Queue"="Transparent"
    15.             "IgnoreProjector"="True"
    16.             "RenderType"="Transparent"
    17.             "PreviewType"="Plane"
    18.             "CanUseSpriteAtlas"="True"
    19.         }
    20.  
    21.         Cull Off
    22.         Lighting Off
    23.         ZWrite Off
    24.         Fog { Mode Off }
    25.         Blend One OneMinusSrcAlpha
    26.  
    27.         Pass
    28.         {
    29.         CGPROGRAM
    30.             #pragma vertex vert
    31.             #pragma fragment frag
    32.             #pragma multi_compile DUMMY PIXELSNAP_ON
    33.             #include "UnityCG.cginc"
    34.          
    35.             struct appdata_t
    36.             {
    37.                 float4 vertex   : POSITION;
    38.                 float4 color    : COLOR;
    39.                 float2 texcoord : TEXCOORD0;
    40.             };
    41.  
    42.             struct v2f
    43.             {
    44.                 float4 vertex   : SV_POSITION;
    45.                 fixed4 color    : COLOR;
    46.                 half2 texcoord  : TEXCOORD0;
    47.             };
    48.          
    49.             fixed4 _Color;
    50.  
    51.             v2f vert(appdata_t IN)
    52.             {
    53.                 v2f OUT;
    54.                 OUT.vertex = mul(UNITY_MATRIX_MVP, IN.vertex);
    55.                 OUT.texcoord = IN.texcoord;
    56.                 OUT.color = IN.color * _Color;
    57.                 #ifdef PIXELSNAP_ON
    58.                 OUT.vertex = UnityPixelSnap (OUT.vertex);
    59.                 #endif
    60.  
    61.                 return OUT;
    62.             }
    63.  
    64.             sampler2D _MainTex;
    65.  
    66.             const float4 white = float4(1,1,1,1);
    67.  
    68.             fixed4 frag(v2f IN) : SV_Target
    69.             {
    70.                 fixed4 c = tex2D(_MainTex, IN.texcoord);
    71.                 c.rgb *= c.a;
    72.                 c = dot (c.rgb, fixed3 (.222, .707, .071));            
    73.                 return c * IN.color;
    74.             }
    75.         ENDCG
    76.         }
    77.     }
    78. }
    79.  
    The result:

    upload_2015-2-16_14-5-0.png

    Now I only want the grayscale effect to be applied if the tint color supplied is anything other than white.

    I could do something with an if statement:

    Code (CSharp):
    1. fixed4 frag(v2f IN) : SV_Target
    2.             {
    3.                 fixed4 c = tex2D(_MainTex, IN.texcoord);
    4.                 c.rgb *= c.a;
    5.  
    6.                 if(IN.color.r != 1 || IN.color.g != 1 || IN.color.b != 1)
    7.                 {
    8.                     c = dot (c.rgb, fixed3 (.222, .707, .071));      
    9.                 }
    10.                        
    11.                 return c * IN.color;
    12.             }
    But im thinking that the performance will suffer so im trying to think of a way that does it without the conditional.

    Any of you clever shader peeps have any clue?
     
  2. Dolkar

    Dolkar

    Joined:
    Jun 8, 2013
    Posts:
    576
    You shouldn't need to worry about that. Simple conditions like this that decide simply whether or not to assign a value to that register are not implemented using dynamic branching, but instead by evaluating all branches in any case (in your case just the dot product) and then just deciding which one to assign. So there is little to no cost associated with your if statement.

    One thing is quite clumsy though.. instead of
    if(IN.color.r!=1||IN.color.g!=1||IN.color.b!=1)
    you can write just:
    if(IN.color.rgb != fixed3(1, 1, 1))
     
  3. Mikeysee

    Mikeysee

    Joined:
    Oct 14, 2013
    Posts:
    155
    Thats good to know!



    I tried that already, results in the following error:

    Shader error in 'Mr Nbibles/Sprites': if statement conditional expressions must evaluate to a scalar at line 79
     
  4. Dolkar

    Dolkar

    Joined:
    Jun 8, 2013
    Posts:
    576
    Oh, right.. stoopid me.
    if(any(IN.color.rgb != fixed3(1, 1, 1)))
     
  5. Mikeysee

    Mikeysee

    Joined:
    Oct 14, 2013
    Posts:
    155
    Oh nice, didnt know you could do that.