1
\$\begingroup\$

I have a white circle sprite. I know how to change its color to a solid fill color. using GetComponent<Renderer>().material.color. But how would I give it a gradient fill color.

example

I've been trying to do this with a shader. But so far the shader I've created doesn't take the circle sprite into account, simply its bounding box. It also looks a bit weird.

enter image description here

here's my shader code

   Shader "Custom/SpriteGradient" {
 Properties {
 [PerRendererData] _MainTex ("Sprite Texture", 2D) = "white" {}
 _Color ("Left Color", Color) = (1,1,1,1)
 _Color2 ("Right Color", Color) = (1,1,1,1)
 _Scale ("Scale", Float) = 1
 }

 SubShader {
 Tags {"Queue"="Background"  "IgnoreProjector"="True"}
 LOD 100

 ZWrite On

 Pass {
     CGPROGRAM
     #pragma vertex vert  
     #pragma fragment frag
     #include "UnityCG.cginc"

     fixed4 _Color;
     fixed4 _Color2;
     fixed  _Scale;

     struct v2f {
         float4 pos : SV_POSITION;
         fixed4 col : COLOR;
     };

     v2f vert (appdata_full v)
     {
         v2f o;
         o.pos = mul (UNITY_MATRIX_MVP, v.vertex);
         o.col = lerp(_Color,_Color2, v.texcoord.x );
         return o;
     }


     float4 frag (v2f i) : COLOR {
         float4 c = i.col;
         c.a = 1;
         return c;
     }
         ENDCG
     }
 }
 }
\$\endgroup\$
  • \$\begingroup\$ Can you show your shader code, and maybe a picture of what you are trying to achieve? \$\endgroup\$ – Alan Wolfe Jun 21 '15 at 1:28
  • \$\begingroup\$ updated the question \$\endgroup\$ – Ramin Afshar Jun 21 '15 at 8:40
  • \$\begingroup\$ Unfortunately i don't have time at the moment to write up a full answer but if nobody else gives useful info, how I would approach this is by faking 3d lighting on the circle. Basically per pixel, I would calculate a normal for that point on the circle if it was a sphere, then I would use standard lighting equations to calculate diffuse color. You could even do specular if you want, depending on whether that's part of your desired effect or not! \$\endgroup\$ – Alan Wolfe Jun 21 '15 at 17:15
  • \$\begingroup\$ wow, that sounds really complicated... any resources online where I can find more info about all this? \$\endgroup\$ – Ramin Afshar Jun 21 '15 at 21:41
  • \$\begingroup\$ Yeah check this out. tomdalling.com/blog/modern-opengl/06-diffuse-point-lighting \$\endgroup\$ – Alan Wolfe Jun 21 '15 at 21:58
1
\$\begingroup\$

Pretty old question, but I recently bumped into similar problem and solved it with few more lines of code to my shader. I don't know details of how transparency is handled by Unity when it uses sprite as a texture, but I decided to do same thing Unity does in their default shaders.

You can download 'Built In shaders' from this page: https://unity3d.com/get-unity/download/archive. In DefaultResources folder you'll find Sprites-Default.shader.

Below I paste default shader code where I added my comments to indicate bits that I added to my shader to solve my problem. In general it looks like Unity is using separate alpha mask texture for such sprites, and you need to account for it in your shader.

Shader "Sprites/Default"
{
    Properties
    {
        [PerRendererData] _MainTex ("Sprite Texture", 2D) = "white" {}
        _Color ("Tint", Color) = (1,1,1,1)
        [MaterialToggle] PixelSnap ("Pixel snap", Float) = 0
    }
SubShader
{
    Tags
    { 
        "Queue"="Transparent" 
        "IgnoreProjector"="True" 
        "RenderType"="Transparent" 
        "PreviewType"="Plane"
        "CanUseSpriteAtlas"="True"
    }

    Cull Off
    Lighting Off
    ZWrite Off
    Blend One OneMinusSrcAlpha    // I added this line

    Pass
    {
    CGPROGRAM
        #pragma vertex vert
        #pragma fragment frag
        #pragma multi_compile _ PIXELSNAP_ON
        #pragma shader_feature ETC1_EXTERNAL_ALPHA   // and this line
        #include "UnityCG.cginc"

        struct appdata_t
        {
            float4 vertex   : POSITION;
            float4 color    : COLOR;
            float2 texcoord : TEXCOORD0;
        };

        struct v2f
        {
            float4 vertex   : SV_POSITION;
            fixed4 color    : COLOR;
            float2 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;
        sampler2D _AlphaTex;  // And this line

// I added this whole function
            fixed4 SampleSpriteTexture (float2 uv)
            {
                fixed4 color = tex2D (_MainTex, uv);
#if ETC1_EXTERNAL_ALPHA
            // get the color from an external texture (usecase: Alpha support for ETC1 on android)
            color.a = tex2D (_AlphaTex, uv).r;
#endif //ETC1_EXTERNAL_ALPHA
            return color;
        }

        fixed4 frag(v2f IN) : SV_Target
        {
            // And used it here to get the color of pixel
            fixed4 c = SampleSpriteTexture (IN.texcoord) * IN.color;
            // and apply alpha
            c.rgb *= c.a;
            return c;
        }
    ENDCG
    }
}
}

Hope it helps.

\$\endgroup\$
  • \$\begingroup\$ Two warnings ,Shader warning in 'Sprites/Default': shader_feature keywords must start with a letter or underscore, ignoring '//' (on ) ,Material property block is used to modify this value . I have just applied it on material and thats on a white sprite is that way its intended to be used. \$\endgroup\$ – Sourav Sachdeva Sep 2 '16 at 21:05

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.