Search Unity

Changing the rendered color of a specific color of an image with a shader

Discussion in 'Shaders' started by unwitty, Feb 23, 2015.

  1. unwitty

    unwitty

    Joined:
    Jan 18, 2015
    Posts:
    31
    Working with shaders is a lot harder than I had imagined. I'm hoping you can help me out here.

    I have a raw image that's generated by script. The raw image contains procedurally generated black text with a transparent background. What I can't figure out is: changing the color of the text (in the image) to white.

    Since I can't change the raw image itself, I've thought about creating a shader that inverts black with white, and apply that shader to a material, and then apply that material to the image itself.

    After a few hours of trying this, I couldn't get it to work -- not even with this great example posted by someone here: http://forum.unity3d.com/threads/be...ixels-in-a-single-sprite.223030/#post-1491019

    Help!
     
  2. bricevdm

    bricevdm

    Joined:
    Nov 4, 2009
    Posts:
    34
    I assume you already have a version working with one of the transparent shader. if so your texture is probably composed of rgb channels fully black, and an alpha channel with the text showing in white and the bg black. in this case all you need to modify (starting from the transparent shader) is to output your custom color (probably "_Color") instead of the rgb of the texture.
    return fixed4(_Color.rgb, texture.a);

    if the rgb channels contains information you need to combine it with the color, but it depends on the content : if black you can multiply, if white you can add. if something else it becomes trickier and you need to use lerp() or other blending methods.
     
  3. unwitty

    unwitty

    Joined:
    Jan 18, 2015
    Posts:
    31
    No version working yet, although what I have now sort of works when viewed at from the very fringes of the Oculus Rift. Meaning, the text becomes white when I move my head so that the text is at the very edge of my peripheral vision.

    I'm not sure if it matters or not but I'm not applying a texture to my material. Rather, I am applying the material with shader to a raw image.

    Here's my shader (admittedly I understand very little about shaders so I might be missing something basic):

    Code (CSharp):
    1. Shader "Custom/Black2White" {
    2.     Properties
    3.     {
    4.         [PerRendererData] _MainTex ("Sprite Texture", 2D) = "white" {}
    5.         _ColorTint ("Tint", Color) = (1,1,1,1)
    6.         _Color1in ("Color 1 In", Color) = (0,0,0,1) //this selects all color that are black right?
    7.         _Color1out ("Color 1 Out", Color) = (1,1,1,1) //and this changes the selected black color to white?
    8.         [MaterialToggle] PixelSnap ("Pixel snap", Float) = 0
    9.     }
    10.     SubShader
    11.     {
    12.         Tags
    13.         {
    14.             "Queue"="Transparent"
    15.             "IgnoreProjector"="True"
    16.             "RenderType"="Transparent"
    17.             "PreviewType"="Plane"
    18.             "CanUseSpriteAtlas"="True"
    19.         }
    20.         Cull Off
    21.         Lighting Off
    22.         ZWrite Off
    23.         Fog { Mode Off }
    24.         Blend SrcAlpha OneMinusSrcAlpha
    25.         Pass
    26.         {
    27.         CGPROGRAM
    28.             #pragma vertex vert
    29.             #pragma fragment frag        
    30.             #pragma multi_compile DUMMY PIXELSNAP_ON
    31.             #include "UnityCG.cginc"
    32.          
    33.             struct appdata_t
    34.             {
    35.                 float4 vertex   : POSITION;
    36.                 float4 color    : COLOR;
    37.                 float2 texcoord : TEXCOORD0;
    38.             };
    39.             struct v2f
    40.             {
    41.                 float4 vertex   : SV_POSITION;
    42.                 fixed4 color    : COLOR;
    43.                 half2 texcoord  : TEXCOORD0;
    44.             };
    45.          
    46.             fixed4 _ColorTint;
    47.             fixed4 _Color1in;
    48.             fixed4 _Color1out;
    49.             v2f vert(appdata_t IN)
    50.             {
    51.                 v2f OUT;
    52.                 OUT.vertex = mul(UNITY_MATRIX_MVP, IN.vertex);
    53.                 OUT.texcoord = IN.texcoord;          
    54.                 OUT.color = IN.color * _ColorTint;
    55.                 #ifdef PIXELSNAP_ON
    56.                 OUT.vertex = UnityPixelSnap (OUT.vertex);
    57.                 #endif
    58.                 return OUT;
    59.             }
    60.             sampler2D _MainTex;      
    61.          
    62.             fixed4 frag(v2f IN) : COLOR
    63.             {
    64.                 float4 texColor = tex2D( _MainTex, IN.texcoord );
    65.                 texColor = all(texColor == _Color1in) ? _Color1out : texColor;
    66.                
    67.                 return texColor * IN.color;
    68.             }
    69.         ENDCG
    70.         }
    71.     }
    72. }
     
  4. jvo3dc

    jvo3dc

    Joined:
    Oct 11, 2013
    Posts:
    1,520
    Comparing colors won't usually work well in a shader. If all text is black, just keep the alpha from the source and replace the color with your own color:
    Code (csharp):
    1.  
    2. texColor = float4(_Color1out.rgb, texColor.a);
    3.  
     
    unwitty likes this.
  5. unwitty

    unwitty

    Joined:
    Jan 18, 2015
    Posts:
    31
    That worked! Thank you jvo3dc!