Making an internal glow shader

Today I was playing around with shaders and I decided to make a shader I may use for a project I have yet to get around to. The project is a desktop clone of slither.io which is a massive multiplayer game where everyone is a snake and  their goal is to eat as many dots as possible, the dots make them bigger and when they die they release the dots they ate. When someone’s head runs into another’s body, they die. The reason I want to make this is because my class decided to make a network game together, currently the server is runnign with all of the logic working, the students are just required to create the clients.

I decided to make mine in Unity, and in doing so, I wanted to use the shader I’m making for the boost ability in the game. The boost will essentially just increase the speed of the player, but I need to let the players know that other players are boosting. The goal for the visual aesthetic is to have a variant of a velvet shader so that when the player is boosting, their snake isn’t a single solid colour. For those that do not know, a velvet shader is something that is brighter on surfaces that are facing away from the viewer, this is because of the small hairs on velvet which reflect light better when viewed from a side:

screen1.jpg


After a little playing around, I made a prototype of the shader. Using an image effect shader I was able to use a dot product of the normal against a vector facing forward and blend the colours together:

Capture.PNG

The code of which is:

Shader:

Shader "Hidden/Glow"
{
 Properties
 {
 _MainTex ("Texture", 2D) = "white" {}
 _glowRange("Glow Factor", Range(0,0.9999)) = 0.8
 _glowColour("Glow Colour", Color) = (0,0,1,1)
 }
 SubShader
 {
 // No culling or depth
 Cull Off ZWrite Off ZTest Always

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

 struct appdata
 {
 float4 vertex : POSITION;
 float2 uv : TEXCOORD0;
 };

 struct v2f
 {
 float2 uv : TEXCOORD0;
 float4 vertex : SV_POSITION;
 };

 v2f vert (appdata v)
 {
 v2f o;
 o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
 o.uv = v.uv;
 return o;
 }
 
 sampler2D _MainTex;

 sampler2D _CameraDepthNormalsTexture;

 float _glowRange;
 float4 _glowColour;


 fixed4 frag (v2f i) : SV_Target
 {
 fixed4 col = tex2D(_MainTex, i.uv);
 // just invert the colors
 float depthValue;
 float3 normalValues;

 float2 switchedY = float2(i.uv.x, 1-i.uv.y);

 DecodeDepthNormal(tex2D(_CameraDepthNormalsTexture, switchedY), depthValue, normalValues);

 float dotProduct = dot(float3(0,0,1), normalValues);

 if (dotProduct < _glowRange)
 {
 float4 dotNormalised = dotProduct / _glowRange;
 col = col * (dotNormalised) + (1 - dotNormalised) * _glowColour;
 }

 return col;
 }
 ENDCG
 }
 }
}

C# script attached to the Camera:

using UnityEngine;
using System.Collections;

[ExecuteInEditMode]
public class GlowEffect : MonoBehaviour {

 public Material mat;

 void Awake()
 {
 mat = new Material(Shader.Find("Hidden/Glow"));

 GetComponent<Camera>().depthTextureMode = DepthTextureMode.DepthNormals;
 }
 
 void OnRenderImage(RenderTexture source, RenderTexture destination)
 {
 Graphics.Blit(source, destination, mat);
 }
}
Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s