1. We've introduced thread tags, search within a thread and similar thread search. Read more here.
    Dismiss Notice
  2. 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
  3. 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
  4. We've released our first Timeline Experimental Preview, our new tool for creating cutscenes and more! To check it out click here.
    Dismiss Notice
  5. Unity 5.5 is now released.
    Dismiss Notice
  6. Check out all the fixes for 5.5 in patch releases 1 & 2.
    Dismiss Notice
  7. Unity 5.6 beta is now available for download.
    Dismiss Notice

Sprite Tint Shader, Not Multiplied

Discussion in 'Shaders' started by DougMcFarlane, Mar 20, 2017.

  1. DougMcFarlane

    DougMcFarlane

    Joined:
    Apr 25, 2009
    Posts:
    184
    This question is mainly for 2D sprites in the new UI system.

    Using the following grey-scale button texture (the top color is white):
    upload_2017-3-20_16-23-26.png

    If I apply a tint / color of RGB(205, 205, 255), I get this result:
    (the tint color is multiplied by the texture colors.
    The result is replacing all while values with the tint color, and the others progressively darker)
    upload_2017-3-20_16-24-18.png

    This kind of works to dynamically change the button color, but it isn't flexible / predictable enough.
    I want the tint color to be the middle color, not the highlight color.

    It would be better to supply a source grey-scale image of:
    upload_2017-3-20_16-29-15.png

    Where the grey color of RGB(128,128,128) (middle of the three greys in the pic) is substituted for the tint color. Darker greys get darker, brighter ones get brighter.

    For example, this would be the result of setting tint color to RGB(110, 110, 255) (now the center / main color):
    upload_2017-3-20_16-32-42.png

    Is this difficult to do? Do I need a custom shader? Is this a blend mode? (if so, how do I change it?)
    Can the shader just multiply the texture color by the tint color, then multiple that by two?
    I've never created a shader, so I don't know the syntax for this.

    Any help or tips would be appreciated! Thanks.
     

    Attached Files:

    Last edited: Mar 20, 2017
  2. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    2,438
    What you want a Photoshop style "overlay", for which you need a custom shader.

    The cheap version of this is the 2x multiply, which is literally "col * tint * 2". This is what many of Unity's particle shaders do. This will make middle grey match the color, but whites won't necessarily go white.

    An actual overlay is fairly complex by comparison, but you can find examples of it online. Look for "Photoshop HLSL".
     
  3. DougMcFarlane

    DougMcFarlane

    Joined:
    Apr 25, 2009
    Posts:
    184
    Thanks for your help, @bgolus.
    I just did as you suggested - multiplied the color by two (as I asked in my question).

    It seems to work - I included the shader below.
    Wow, the shader language seems unnecessarily complicated. More C like than C#.

    But now the shader doesn't use the uGui Image control's 'Color' property, yet it uses it's 'Souce Image' property.
    I have to set the color via the material. I hope this doesn't require a new draw call for each color I use.

    Code (CSharp):
    1. Shader "Custom/GUI" {
    2.  
    3.     Properties {
    4.         _Color ("Main Color", Color) = (1,1,1,1)
    5.        _MainTex ("Texture", 2D) = "white" {}
    6.     }
    7.  
    8.     SubShader {
    9.         Pass {
    10.             CGPROGRAM
    11.             #pragma vertex vert            
    12.             #pragma fragment frag
    13.  
    14.             struct vertInput {
    15.                 float4 vertex : POSITION;        // vertex position
    16.                 float2 uv : TEXCOORD0;            // texture coordinate
    17.             };
    18.  
    19.             struct vertOutput {
    20.                 float2 uv : TEXCOORD0;            // texture coordinate
    21.                 float4 vertex : SV_POSITION;    // clip space position
    22.             };
    23.  
    24.             // vertex shader
    25.             vertOutput vert (vertInput v) {
    26.                 vertOutput o;
    27.                 // transform position to clip space (multiply with model*view*projection matrix)
    28.                 o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);  
    29.                 // just pass the texture coordinate
    30.                 o.uv = v.uv;                              
    31.                 return o;
    32.             }
    33.  
    34.             sampler2D _MainTex;
    35.             fixed4 _Color;
    36.  
    37.             fixed4 frag(vertOutput output) : COLOR {
    38.                 fixed4 col = tex2D(_MainTex, output.uv);
    39.                 return col * _Color * 2.0;
    40.             }        
    41.  
    42.             ENDCG
    43.         }
    44.     }
    45. }
    46.  
    47.  
     
  4. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    2,438
  5. brownboot67

    brownboot67

    Joined:
    Jan 5, 2013
    Posts:
    104
    Image components color property sets vertex color. Let's it preserve batching if possible.