- Home /
Make 2D sprites glow?
I've tried a million things and can't seem to get the simple effect of making my sprites glow. I followed a tutorial to make a a glowing shader but it turned out it would only work on 3D objects. I found a script to put on the camera that makes everything glow from unity's built in assets, but can't make it only effect a specific object. Does anyone know how to either make a shader meant for 3D work on sprites, make the camera glow effect script effect only specific objects, or have any other ideas on how I can achieve a glowing effect on a sprite?? I'm looking for an effect similar to that in games like geometry wars or Ori and the Blind Forest where objects glow.
If you're curious, I need it so I can make certain body-parts of enemies glow to indicate to the player which parts are that enemy's weak points. Actually, if anyone has a better idea than making them glow I'd be open to suggestions :) Because this glow thing is starting to be more trouble than it's worth. I tried particle effects but can't figure out how to make them spawn based on the shape of an object (only in squares or spheres).
Thanks for any advice!!
Annoying isn't it! Such a simple thing takes an insanely complicated approach to solve! I would suggest to Unity that the "tint" option should have more blend modes than just "multiply".
Perhaps you can jst make white sprites in photoshop, and overlay them on the actual sprite. The white sprite can have an animation in opacity so it looks like the bodypart is glowing.
Answer by $$anonymous$$ · Dec 25, 2015 at 12:48 PM
Here is the shader we copied from Unity's standart sprite shader and modified to shine certain location of sprite.
You can change ShineLocation and ShineWidth to make an shine animation through c# scripts.
It may help you...
//Kaan Yamanyar,Levent Seckin
Shader "Sprites/ShinyDefault"
{
Properties
{
[PerRendererData] _MainTex("Sprite Texture", 2D) = "white" {}
_Color("Tint", Color) = (1,1,1,1)
_ShineLocation("ShineLocation", Range(0,1)) = 0
_ShineWidth("ShineWidth", Range(0,1)) = 0
[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
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile _ 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;
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;
float _AlphaSplitEnabled;
float _ShineLocation;
float _ShineWidth;
fixed4 SampleSpriteTexture(float2 uv)
{
fixed4 color = tex2D(_MainTex, uv);
#if UNITY_TEXTURE_ALPHASPLIT_ALLOWED
if (_AlphaSplitEnabled)
color.a = tex2D(_AlphaTex, uv).r;
#endif //UNITY_TEXTURE_ALPHASPLIT_ALLOWED
float lowLevel = _ShineLocation - _ShineWidth;
float highLevel = _ShineLocation + _ShineWidth;
float currentDistanceProjection = (uv.x + uv.y) / 2;
if (currentDistanceProjection > lowLevel && currentDistanceProjection < highLevel) {
float whitePower = 1- (abs(currentDistanceProjection - _ShineLocation ) / _ShineWidth);
color.rgb += color.a * whitePower;
}
return color;
}
fixed4 frag(v2f IN) : SV_Target
{
fixed4 c = SampleSpriteTexture(IN.texcoord) * IN.color;
c.rgb *= c.a;
return c;
}
ENDCG
}
}
}
Just noticed, it worked in most cases, but for some reason it doesn't work on Android 6.0, $$anonymous$$arshmallow. It gets all glitchy. Anyone has any idea why?
I'm Fairly new to Unity and I would like to know how I would go about to use this shader?
Answer by firestoke · Aug 31, 2016 at 09:04 AM
Based on Kaan Yy's Answer. I have wrote a utils function to make it working more convenient. Here it is:
public static void shineObject (GameObject obj, float width, float duration)
{
var mono = obj.GetComponent<MonoBehaviour>();
if( mono != null) {
// change material
Material mat = Resources.Load ("Materials/ShineMaterial", typeof(Material)) as Material;
var render = obj.GetComponent<Renderer> ();
if (render != null) {
render.material = mat;
} else {
var img = obj.GetComponent<Image> ();
if (img != null) {
img.material = mat;
} else {
Debug.LogWarning ("cannot get the render or image compoent!");
}
}
mat.SetFloat("_ShineWidth", width);
// start a coroutine
mono.StopAllCoroutines ();
mono.StartCoroutine (shineRoutine (mat, duration));
} else {
Debug.LogWarning ("cannot find MonoBehaviour component!");
}
}
static IEnumerator shineRoutine (Material mat, float duration)
{
if( mat != null ) {
float location = 0f;
float interval = 0.04f;
float offsetVal = interval / duration;
while(true) {
yield return new WaitForSeconds (interval);
mat.SetFloat("_ShineLocation", location);
location += offsetVal;
if (location > 1f) {
location = 0f;
}
}
} else {
Debug.LogWarning ("there is no material parameter!");
}
}
It works both on a UI Image or a Sprite game object. But the game object must have a "MonoBehaviour" component to use the StartCoroutine function.
The result:
I thinks this is not working anymore with Unity 2017.3.1.
Do you know how to fix it for those versions and upper?
Thanks!
Answer by tanoshimi · Mar 25, 2015 at 05:05 PM
You need to use an emissive shader, and supply a suitable emission map: http://docs.unity3d.com/Manual/StandardShaderMaterialParameters.html
Answer by mhbitaraf · Dec 11, 2018 at 07:58 AM
I changed firestoke code into this and it's working for me perfectly, and as an absolute amateur I have to say that I am very grateful for the main Shader code and of course firestoke script. I think if you try and work on the code a bit, you can personalize it to fit your needs. here is the code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class ShineMaterialScript : MonoBehaviour
{
public float width;
public float duration;
public float m_Delay;
//delay is the time between each shine;
void Start ()
{
Material mat = Resources.Load("Materials/Environment/Shiny", typeof(Material)) as Material;
// either you have to have this exact address in your resource folder or change it to where ever
// you saved your shiny material, remember that the "Shiny" last bit here is just an example I used for
// the material name, you have to use the name which you have given your material with shiny shader on it.
// Take note that you have to add a "Resourse" folder in your assets folder in order for the script to work.
Renderer renderer = gameObject.GetComponent<Renderer>();
if (renderer != null)
{
renderer.material = mat;
}
else
{
Image img = gameObject.GetComponent<Image>();
if (img != null)
{
img.material = mat;
}
else
{
Debug.LogWarning("Cannot get the Renderer or Image component!");
}
}
mat.SetFloat("_ShineWith", width);
StopAllCoroutines();
StartCoroutine(shineRoutine(mat, duration, m_Delay));
}
static IEnumerator shineRoutine(Material mat, float duration, float m_Delay)
{
if (mat != null)
{
float location = 0f;
float interval = 0.04f;
float offsetVal = interval / duration;
while (true)
{
yield return new WaitForSeconds(interval);
mat.SetFloat("_ShineLocation", location);
location += offsetVal;
if (location > 1f)
{
yield return new WaitForSeconds(m_Delay);
location = 0f;
}
}
}
else
{
Debug.LogWarning("There is no Material parameter!");
}
}
}