Sprite Shader with GreyScale

Hey Guys,

I am new to shading but somehow managed to acomplish this for the new 2D Sprite system of Unity.
You can use sliders to control the grayscalevalue :slight_smile:

If someone needs grayscale for his textures there you go: :slight_smile:

Shader "Sprites/GrayScale"
{
	Properties
	{
		[PerRendererData] _MainTex ("Sprite Texture", 2D) = "white" {}
		_Color ("Tint", Color) = (1,1,1,1)
		[MaterialToggle] PixelSnap ("Pixel snap", Float) = 0
		_EffectAmount ("Effect Amount", Range (0, 1)) = 1.0
	}

	SubShader
	{
		Tags
		{ 
			"Queue"="Transparent" 
			"IgnoreProjector"="True" 
			"RenderType"="Transparent" 
			"PreviewType"="Plane"
			"CanUseSpriteAtlas"="True"
		}

		Cull Off
		Lighting Off
		ZWrite Off
		Fog { Mode Off }
		Blend SrcAlpha OneMinusSrcAlpha

		Pass
		{
		CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag
			#pragma multi_compile DUMMY PIXELSNAP_ON
			#include "UnityCG.cginc"
			
			struct appdata_t
			{
				float4 vertex   : POSITION;
				float4 color    : COLOR;
				float2 texcoord : TEXCOORD0;
			};

			struct v2f
			{
				float4 vertex   : SV_POSITION;
				fixed4 color    : COLOR;
				half2 texcoord  : TEXCOORD0;
			};
			
			fixed4 _Color;

			v2f vert(appdata_t IN)
			{
				v2f OUT;
				OUT.vertex = mul(UNITY_MATRIX_MVP, IN.vertex);
				OUT.texcoord = IN.texcoord;
				OUT.color = IN.color * _Color;
				#ifdef PIXELSNAP_ON
				OUT.vertex = UnityPixelSnap (OUT.vertex);
				#endif

				return OUT;
			}

			sampler2D _MainTex;
			uniform float _EffectAmount;

			fixed4 frag(v2f IN) : COLOR
			{
				half4 texcol = tex2D (_MainTex, IN.texcoord);				
				texcol.rgb = lerp(texcol.rgb, dot(texcol.rgb, float3(0.3, 0.59, 0.11)), _EffectAmount);
				texcol = texcol * IN.color;
				return texcol;
			}
		ENDCG
		}
	}
	Fallback "Sprites/Default"
}

If you want to change things threw code use this:

_GAMEOBJECT_.renderer.material.SetFloat("_EffectAmount", 0.5f);

Cheers :slight_smile:

21 Likes

##EDIT##

fixed it with:

texcol = texcol * IN.color;
1 Like

This is great! I’m wondering though if it’s possible to modify the code so that parts of the original color gets permanently revealed based on a circle around some coordinates? Similar to how a fog of war shader would work, I would imagine?

Similar to this: http://codepen.io/cwolves/pen/prvnb

1 Like

Thanks a lot Dev6_RC, I was using a shader that was working well on unity editor, but on android the shader was broken, I don’t know why, but the yours worked really good! Thank you a lot! :slight_smile:

1 Like

Cheers Bro. Great work.

This is really awesome! But I would like to have the same shader effect on regular textures but I’m really bad at shaders…anyone have any clue?

This is very cool and works great, but it doesn’t seem to work with masking in the UI. I applied a material with this shader to a sprite on my canvas with a mask on top of it … and the grayscale texture doesnt get masked. If I change material to none it masks just fine. Is this something that can be added?

I am sorry, but I have no time ATM. If i had to guess: this shader is based on the Unity sprites shader ( with some modifications ) You could try to look into the base shader of the unity UI system and add the required features into this one. If you do so feel free to post it here! :slight_smile: Help the Community! :smile:

Wow! You are awesome!

That helped me a lot~ Thank you!

Thanks, this was really helpful.
However, as noted by azmundai, it doesn’t work with Unity UI’s Image, so I used your shader to modify Unity’s default shader and came up with this:

Shader "Grayscale"
{
    Properties
    {
        [PerRendererData] _MainTex ("Sprite Texture", 2D) = "white" {}
        _Color ("Tint", Color) = (1,1,1,1)
     
        _StencilComp ("Stencil Comparison", Float) = 8
        _Stencil ("Stencil ID", Float) = 0
        _StencilOp ("Stencil Operation", Float) = 0
        _StencilWriteMask ("Stencil Write Mask", Float) = 255
        _StencilReadMask ("Stencil Read Mask", Float) = 255

        _ColorMask ("Color Mask", Float) = 15
        _GrayscaleAmount ("Grayscale Amount", Range (0, 1)) = 1.0

        [Toggle(UNITY_UI_ALPHACLIP)] _UseUIAlphaClip ("Use Alpha Clip", Float) = 0
    }

    SubShader
    {
        Tags
        {
            "Queue"="Transparent"
            "IgnoreProjector"="True"
            "RenderType"="Transparent"
            "PreviewType"="Plane"
            "CanUseSpriteAtlas"="True"
        }
     
        Stencil
        {
            Ref [_Stencil]
            Comp [_StencilComp]
            Pass [_StencilOp]
            ReadMask [_StencilReadMask]
            WriteMask [_StencilWriteMask]
        }

        Cull Off
        Lighting Off
        ZWrite Off
        ZTest [unity_GUIZTestMode]
        Blend SrcAlpha OneMinusSrcAlpha
        ColorMask [_ColorMask]

        Pass
        {
        CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"
            #include "UnityUI.cginc"

            #pragma multi_compile __ UNITY_UI_ALPHACLIP
         
            struct appdata_t
            {
                float4 vertex   : POSITION;
                float4 color    : COLOR;
                float2 texcoord : TEXCOORD0;
            };

            struct v2f
            {
                float4 vertex   : SV_POSITION;
                fixed4 color    : COLOR;
                half2 texcoord  : TEXCOORD0;
                float4 worldPosition : TEXCOORD1;
            };
         
            fixed4 _Color;
            fixed4 _TextureSampleAdd;
            float4 _ClipRect;
            uniform float _GrayscaleAmount;

            v2f vert(appdata_t IN)
            {
                v2f OUT;
                OUT.worldPosition = IN.vertex;
                OUT.vertex = mul(UNITY_MATRIX_MVP, OUT.worldPosition);

                OUT.texcoord = IN.texcoord;
             
                #ifdef UNITY_HALF_TEXEL_OFFSET
                OUT.vertex.xy += (_ScreenParams.zw-1.0)*float2(-1,1);
                #endif
             
                OUT.color = IN.color * _Color;
                return OUT;
            }

            sampler2D _MainTex;

            fixed4 frag(v2f IN) : SV_Target
            {
                half4 color = (tex2D(_MainTex, IN.texcoord) + _TextureSampleAdd) * IN.color;
             
                color.a *= UnityGet2DClipping(IN.worldPosition.xy, _ClipRect);
                color.rgb = lerp(color.rgb, dot(color.rgb, float3(0.3, 0.59, 0.11)), _GrayscaleAmount);
             
                #ifdef UNITY_UI_ALPHACLIP
                clip (color.a - 0.001);
                #endif

                return color;
            }
        ENDCG
        }
    }
}

Hope it helps!

2459409–169118–UI-Grayscale.shader (2.3 KB)

15 Likes

Thanks you it’s Great !. Work on Android, tested !

Nice! Everything that helps improving this shader and unity itself is appriciated! :slight_smile:

Waow guys, it’s awesome ! Thank you very much for these two Grey Scale shader scripts.
There are very useful !

Thanks, this was really helpfull.

Just what I needed! Thanks @RChrispy !

FUN FACT: I was curious about the magic vector (0.3, 0.59, 0.11) in this line:

color.rgb= lerp(color.rgb, dot(color.rgb, float3(0.3, 0.59, 0.11)), _GrayscaleAmount);

…they’re saying something like “make the grayscale whiteness value of a color 0.3R + 0.59G + 0.11B” but where do those coefficients come from? I looked it up and it seems they come from the NTSC TV standard/the way human eyes work: ~60% of perceived luminosity comes from green, ~30% from red, ~10% from blue.

1 Like

Hey harleywinks :slight_smile: Thanks for your kind reply!
This happened a long time ago, but if I remember corectly this was the base Vector unity used in it’s Sprite Shader. I used it to modify the color so the “real” Color and the “Grayscaled” Color look best :slight_smile:

I was just beginning to look into grayscale sprites. This made my life a lot easier. Thank you!

Helloo, so no warnings, but GrayscaleAmount is not working, the image/sprite always looks gray.

I made a Sprite/Diffuse version from the builtin shader & the grayscale version:

// Unity built-in shader source. Copyright (c) 2016 Unity Technologies. MIT license (see license.txt)

Shader "Sprites/GrayScale"
{
    Properties
    {
        [PerRendererData] _MainTex ("Sprite Texture", 2D) = "white" {}
        _Color ("Tint", Color) = (1,1,1,1)
        [MaterialToggle] PixelSnap ("Pixel snap", Float) = 0
        [HideInInspector] _RendererColor ("RendererColor", Color) = (1,1,1,1)
        [HideInInspector] _Flip ("Flip", Vector) = (1,1,1,1)
        [PerRendererData] _AlphaTex ("External Alpha", 2D) = "white" {}
        [PerRendererData] _EnableExternalAlpha ("Enable External Alpha", Float) = 0
        _EffectAmount ("Effect Amount", Range (0, 1)) = 1.0
    }

    SubShader
    {
        Tags
        {
            "Queue"="Transparent"
            "IgnoreProjector"="True"
            "RenderType"="Transparent"
            "PreviewType"="Plane"
            "CanUseSpriteAtlas"="True"
        }

        Cull Off
        Lighting Off
        ZWrite Off
        Blend One OneMinusSrcAlpha

        CGPROGRAM
        #pragma surface surf Lambert vertex:vert nofog nolightmap nodynlightmap keepalpha noinstancing
        #pragma multi_compile _ PIXELSNAP_ON
        #pragma multi_compile _ ETC1_EXTERNAL_ALPHA
        #include "UnitySprites.cginc"

        struct Input
        {
            float2 uv_MainTex;
            fixed4 color;
        };
       
        void vert (inout appdata_full v, out Input o)
        {
            v.vertex.xy *= _Flip.xy;

            #if defined(PIXELSNAP_ON)
            v.vertex = UnityPixelSnap (v.vertex);
            #endif
           
            UNITY_INITIALIZE_OUTPUT(Input, o);
            o.color = v.color * _Color * _RendererColor;
        }
        uniform float _EffectAmount;

        void surf (Input IN, inout SurfaceOutput o)
        {
            fixed4 c = SampleSpriteTexture (IN.uv_MainTex) * IN.color;
            c.rgb = lerp(c.rgb, dot(c.rgb, float3(0.3, 0.59, 0.11)), _EffectAmount);
            o.Albedo = c.rgb * c.a;
            o.Alpha = c.a;
        }
        ENDCG
    }

Fallback "Sprite/Diffuse"
}
2 Likes