Welcome back!! Here i am gonna create an "Outline shader". Before moving on how to achieve that using unity shaders, let me define what is an "Outline shader". This shader will give you an outline border, of any desired thickness and color for any object. Outline for any object has many uses. Lets suppose you wanna highlight selected object with an outline border or you wanna highlight a collectible object in the scene for your game.
Now there are many ways of achieving this result and its your choice how you do this.
Here for this blog, i am gonna do this using Normals.
I will split my shader into 2 passes
First pass: i will apply normal texture on to the object
Second pass: i will stretch the vertices of the object along the normal, apply some color and disable "ZWrite" so that only the borders get highlighted and rest is masked out.
Here is the shader code:
// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)' Shader "ShaderLearning/Outline" { Properties { _Color("Texture Color", Color) = (1,1,1,1) _Texture("Basic Texture", 2D) = "white" {} //Outline shader properties _OutlineStrength("OutLine Strength", float) = 0.1 _OutlineColor("Outline Color", Color) = (1,1,1,1) _turnOnOutline("Turn on Outline", int) = 1 } Subshader { //Pass for outline Pass { ZWrite off CGPROGRAM #pragma vertex vert #pragma fragment frag uniform half4 _OutlineColor; //Outline color uniform float _OutlineStrength; //Thinkness of the outline uniform int _turnOnOutline; //used in in C# script to turn on/off the outline shader property struct vertexInput { float4 vertex: POSITION; float4 normal: NORMAL; }; struct vertexOutput { float4 pos : SV_POSITION; }; vertexOutput vert(vertexInput v) { vertexOutput o; v.vertex += v.normal * _OutlineStrength * _turnOnOutline; o.pos = UnityObjectToClipPos(v.vertex); return o; } half4 frag(vertexOutput i) : COLOR { return _OutlineColor.rgba; } ENDCG } //Pass for the texture Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag uniform sampler2D _Texture; uniform half4 _Color; struct vertexInput { float4 vertex: POSITION; float4 texcoorda: TEXCOORD0; }; struct vertexOutput { float4 pos : SV_POSITION; float4 texcoorda: TEXCOORD0; }; vertexOutput vert(vertexInput v) { vertexOutput o; o.pos = UnityObjectToClipPos(v.vertex); o.texcoorda.xy = v.texcoorda; return o; } half4 frag(vertexOutput i) : COLOR { return tex2D(_Texture,i.texcoorda) * _Color.rgba; } ENDCG } } }
In the above code there are 2 passes, one for normal texture and one for the outline border.
For giving this code a little more life, i have created a C# script- to give the outline effect only if we hover over that object. Basically i used this outline shader for highlight selected object.
C# script which is attached to each object:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
public class Hover : MonoBehaviour
{
private void OnMouseEnter()
{
GetComponent<Renderer>().material.SetInt("_turnOnOutline", 1);
}
private void OnMouseExit()
{
GetComponent<Renderer>().material.SetInt("_turnOnOutline", 0);
}
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
}
}
Final Result:
Comments