Outline Highlight Shader for Unity URP
A URP outline shader for Unity 6 that adds a constant-width, optionally pulsing outline to any mesh as an extra material, for selection, hover and pickup highlights.
Also called: selection outline, hover highlight, object outline, interactable highlight.
Effects URP, Unity 6000.0+ beginner MIT licensed
Use it for: Highlighting what the player is looking at, a selected unit, an interactable door or a pickup, without changing the object's own material.
The preview is a WebGL copy of the shader's maths with one fixed light, so it shows no shadows, Bloom or textures.
What it does
- Works on top of any material: add it as an extra material slot on the renderer
- Width in screen pixels, so the line is equally thick near and far
- HDR colour for a glow with Bloom, and alpha for softer lines
- Optional pulse in width and opacity
- Drawn after opaque objects, so only the part outside the silhouette shows
How it works
The shader draws the mesh a second time with front faces culled, so only its inside shows. In clip space it pushes each vertex outwards along the screen direction of its normal by a fixed number of pixels, scaled by the vertex's depth so the width stays constant on screen.
Because it renders with the transparent objects, the object itself has already written depth. The pushed-out back faces are hidden behind the object everywhere except around its edges, which leaves a clean outline.
Setup
- Save the file as OutlineHighlight.shader under Assets and create a material that uses Scripts For Unity > Outline Highlight.
- Select the object's Mesh Renderer, increase the Materials list by one and drop the outline material into the new slot.
- To switch it on and off from code, add and remove the material from
renderer.sharedMaterials, or keep it and set _OutlineWidth to 0. - For a glow, set an HDR colour with intensity above 1 and enable Bloom.
Common mistakes
- The outline breaks at corners: hard-edged meshes like cubes have split normals, so the pushed faces separate. Use a mesh with smoothed normals for the outline.
- It does not show through walls: the outline is depth tested, like the object. Showing it through walls needs a separate stencil or render-objects setup.
- Only part of a multi-material mesh is outlined: an extra material slot draws the last submesh only. On meshes with several submeshes, put the outline on a duplicate renderer instead.
Questions
- How do I show the outline only when the player looks at an object?
- Keep the outline material out of the renderer's materials until it is needed, then add it: copy
renderer.sharedMaterialsinto a list, append the outline material, and assign the array back. Remove it the same way when the player looks away. - Does it work on animated characters?
- Yes. It uses the mesh's skinned positions and normals like any other material, so it follows a Skinned Mesh Renderer.
- How is it different from Edge Outline?
- Outline Highlight outlines only the objects you give it, in their own colour. Edge Outline is a full-screen effect that outlines everything the camera sees.
Source
OutlineHighlight.shader · 89 lines · ShaderLab and HLSL for the Universal Render Pipeline 17 (Unity 6)
// Outline Highlight: an add-on material that draws a constant-width outline
// around any mesh, whatever its main material. Add it as an extra material
// slot on the renderer (or from code) to highlight a selection, a hovered
// object or a pickup. URP 17 (Unity 6). Scripts For Unity, MIT licensed.
Shader "Scripts For Unity/Outline Highlight"
{
Properties
{
[HDR] _OutlineColor ("Outline Color", Color) = (1, 0.75, 0.2, 1)
_OutlineWidth ("Width (pixels)", Range(0, 12)) = 3
_PulseSpeed ("Pulse Speed", Range(0, 6)) = 0
_PulseAmount ("Pulse Amount", Range(0, 1)) = 0.5
}
SubShader
{
// Drawn with the transparent objects, after every opaque surface has
// written depth, so only the part outside the silhouette shows
Tags
{
"RenderType" = "Transparent"
"Queue" = "Transparent"
"RenderPipeline" = "UniversalPipeline"
"IgnoreProjector" = "True"
}
Pass
{
Name "Outline"
Tags { "LightMode" = "SRPDefaultUnlit" }
Cull Front
ZWrite Off
ZTest LEqual
Blend SrcAlpha OneMinusSrcAlpha
HLSLPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
CBUFFER_START(UnityPerMaterial)
half4 _OutlineColor;
float _OutlineWidth;
float _PulseSpeed;
float _PulseAmount;
CBUFFER_END
struct Attributes
{
float4 positionOS : POSITION;
float3 normalOS : NORMAL;
};
struct Varyings
{
float4 positionCS : SV_POSITION;
};
float SfuPulse()
{
return (sin(_Time.y * _PulseSpeed * TWO_PI) * 0.5 + 0.5) * _PulseAmount * step(0.0001, _PulseSpeed);
}
Varyings vert(Attributes input)
{
Varyings output;
float4 positionCS = TransformObjectToHClip(input.positionOS.xyz);
float3 normalWS = TransformObjectToWorldNormal(input.normalOS);
float2 normalCS = TransformWorldToHClipDir(normalWS).xy;
float2 direction = normalize(normalCS + float2(0.00001, 0.00001));
// Push out by a fixed number of screen pixels at any distance
float width = _OutlineWidth * (1.0 + SfuPulse());
positionCS.xy += direction * width * 2.0 / _ScreenParams.xy * positionCS.w;
output.positionCS = positionCS;
return output;
}
half4 frag(Varyings input) : SV_Target
{
return half4(_OutlineColor.rgb, _OutlineColor.a * (1.0 - SfuPulse() * 0.5));
}
ENDHLSL
}
}
FallBack Off
}
More shaders
- Dissolve ShaderA URP dissolve shader for Unity 6 that burns a mesh away along procedural noise with a glowing HDR edge. No noise texture needed, and its shadow dissolves with it.
- Hologram ShaderA URP hologram shader for Unity 6: additive fresnel glow, scrolling world-space scanlines and random flicker, for sci-fi displays, ghosts and selection previews.
- Toon Lit Shader with OutlineA URP toon shader for Unity 6: two-band cel shading that receives shadows, a hard specular highlight, a rim light and an inverted-hull outline, in one .shader file.
- Stylized Water ShaderA URP stylized water shader for Unity 6: rolling vertex waves, a deep-to-horizon colour ramp, crest foam, a sun glint and optional shore foam from the depth texture.