🎯 Recommended Samples
Balanced sample collections from various categories for you to explore
Unity Shader Samples
Unity HLSL shader examples including surface shaders, vertex/fragment shaders, and post-processing effects
💻 Basic Unity Shaders glsl
🟢 simple
⭐⭐
Introduction to Unity shader programming with surface shaders and basic effects
⏱️ 25 min
🏷️ unity, shader, hlsl, graphics
Prerequisites:
Shader programming basics, Unity Editor
// Unity Basic Shaders - HLSL/Cg
// 1. Basic Diffuse Shader
Shader "Custom/BasicDiffuse"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
_Color ("Color", Color) = (1,1,1,1)
}
SubShader
{
Tags { "RenderType"="Opaque" }
CGPROGRAM
#pragma surface surf Lambert
sampler2D _MainTex;
fixed4 _Color;
struct Input
{
float2 uv_MainTex;
};
void surf (Input IN, inout SurfaceOutput o)
{
fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
o.Albedo = c.rgb;
o.Alpha = c.a;
}
ENDCG
}
Fallback "Diffuse"
}
// 2. Lambert Lighting with Custom Properties
Shader "Custom/CustomLambert"
{
Properties
{
_MainTex ("Base (RGB)", 2D) = "white" {}
_Color ("Color", Color) = (1,1,1,1)
_Emission ("Emission", Color) = (0,0,0,1)
_Glossiness ("Glossiness", Range(0,1)) = 0.5
_Metallic ("Metallic", Range(0,1)) = 0.0
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 200
CGPROGRAM
#pragma surface surf Standard fullforwardshadows
#pragma target 3.0
sampler2D _MainTex;
fixed4 _Color;
half _Glossiness;
half _Metallic;
fixed4 _Emission;
struct Input
{
float2 uv_MainTex;
};
void surf (Input IN, inout SurfaceOutputStandard o)
{
fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
o.Albedo = c.rgb;
o.Normal = fixed3(0,0,1);
o.Metallic = _Metallic;
o.Smoothness = _Glossiness;
o.Emission = _Emission.rgb;
o.Alpha = c.a;
}
ENDCG
}
Fallback "Standard"
}
// 3. Transparent Shader with Alpha
Shader "Custom/Transparent"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
_Color ("Color", Color) = (1,1,1,1)
_Alpha ("Alpha", Range(0,1)) = 1.0
}
SubShader
{
Tags {
"Queue"="Transparent"
"RenderType"="Transparent"
}
LOD 100
Blend SrcAlpha OneMinusSrcAlpha
ZWrite Off
Cull Off
CGPROGRAM
#pragma surface surf Lambert alpha:fade
sampler2D _MainTex;
fixed4 _Color;
float _Alpha;
struct Input
{
float2 uv_MainTex;
};
void surf (Input IN, inout SurfaceOutput o)
{
fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
o.Albedo = c.rgb;
o.Alpha = c.a * _Alpha;
}
ENDCG
}
}
// 4. Rim Lighting Shader
Shader "Custom/RimLighting"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
_Color ("Color", Color) = (1,1,1,1)
_RimColor ("Rim Color", Color) = (0,0.5,1,1)
_RimPower ("Rim Power", Range(0,8)) = 3.0
}
SubShader
{
Tags { "RenderType"="Opaque" }
CGPROGRAM
#pragma surface surf Lambert
sampler2D _MainTex;
fixed4 _Color;
fixed4 _RimColor;
float _RimPower;
struct Input
{
float2 uv_MainTex;
float3 viewDir;
};
void surf (Input IN, inout SurfaceOutput o)
{
fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
o.Albedo = c.rgb;
// Rim lighting
half rim = 1.0 - saturate(dot (normalize(IN.viewDir), o.Normal));
o.Emission = _RimColor.rgb * pow (rim, _RimPower);
o.Alpha = c.a;
}
ENDCG
}
Fallback "Diffuse"
}
// 5. Toon/Cel Shading Shader
Shader "Custom/ToonShader"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
_Color ("Color", Color) = (1,1,1,1)
_Ramp ("Toon Ramp", 2D) = "gray" {}
_OutlineColor ("Outline Color", Color) = (0,0,0,1)
_Outline ("Outline Width", Range(0,0.1)) = 0.02
}
SubShader
{
Tags { "RenderType"="Opaque" }
UsePass "Toon/OUTLINE"
CGPROGRAM
#pragma surface surf Toon
sampler2D _MainTex;
sampler2D _Ramp;
fixed4 _Color;
struct Input
{
float2 uv_MainTex;
};
inline fixed4 LightingToon (SurfaceOutput s, half3 lightDir, half3 viewDir, half atten)
{
half d = dot (s.Normal, lightDir) * 0.5 + 0.5;
fixed3 ramp = tex2D (_Ramp, fixed2(d,d)).rgb;
fixed4 c;
c.rgb = s.Albedo * _LightColor0.rgb * ramp * atten;
c.a = s.Alpha;
return c;
}
void surf (Input IN, inout SurfaceOutput o)
{
fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
o.Albedo = c.rgb;
o.Alpha = c.a;
}
ENDCG
}
Fallback "Diffuse"
}
// 6. Scrolling Texture Shader
Shader "Custom/ScrollingTexture"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
_Color ("Color", Color) = (1,1,1,1)
_ScrollX ("Scroll X Speed", float) = 0.1
_ScrollY ("Scroll Y Speed", float) = 0.0
}
SubShader
{
Tags { "RenderType"="Opaque" }
CGPROGRAM
#pragma surface surf Lambert
sampler2D _MainTex;
fixed4 _Color;
float _ScrollX;
float _ScrollY;
struct Input
{
float2 uv_MainTex;
};
void surf (Input IN, inout SurfaceOutput o)
{
float2 scrolledUV = IN.uv_MainTex;
scrolledUV.x += _Time * _ScrollX;
scrolledUV.y += _Time * _ScrollY;
fixed4 c = tex2D (_MainTex, scrolledUV) * _Color;
o.Albedo = c.rgb;
o.Alpha = c.a;
}
ENDCG
}
Fallback "Diffuse"
}
// 7. Dissolve Shader
Shader "Custom/Dissolve"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
_Color ("Color", Color) = (1,1,1,1)
_DissolveTex ("Dissolve Texture", 2D) = "white" {}
_DissolveAmount ("Dissolve Amount", Range(0,1)) = 0.0
_EdgeColor ("Edge Color", Color) = (1,0,0,1)
_EdgeWidth ("Edge Width", Range(0,0.1)) = 0.01
}
SubShader
{
Tags { "RenderType"="Opaque" }
CGPROGRAM
#pragma surface surf Lambert
sampler2D _MainTex;
sampler2D _DissolveTex;
fixed4 _Color;
float _DissolveAmount;
fixed4 _EdgeColor;
float _EdgeWidth;
struct Input
{
float2 uv_MainTex;
float2 uv_DissolveTex;
};
void surf (Input IN, inout SurfaceOutput o)
{
float dissolve = tex2D (_DissolveTex, IN.uv_DissolveTex).r;
fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
if (dissolve < _DissolveAmount)
{
clip (-1);
}
// Edge effect
if (dissolve < _DissolveAmount + _EdgeWidth)
{
c = _EdgeColor;
}
o.Albedo = c.rgb;
o.Alpha = c.a;
}
ENDCG
}
Fallback "Diffuse"
}
// 8. Glass/Refraction Shader
Shader "Custom/Glass"
{
Properties
{
_MainTex ("Main Texture", 2D) = "white" {}
_BumpMap ("Normal Map", 2D) = "bump" {}
_Color ("Color", Color) = (1,1,1,1)
_RefractAmount ("Refraction Amount", Range(0,1)) = 0.5
_Glossiness ("Glossiness", Range(0,1)) = 0.8
}
SubShader
{
Tags {
"Queue"="Transparent"
"RenderType"="Opaque"
}
GrabPass {}
CGPROGRAM
#pragma surface surf Standard alpha
#pragma target 3.0
sampler2D _MainTex;
sampler2D _BumpMap;
sampler2D _GrabTexture;
fixed4 _Color;
float _RefractAmount;
half _Glossiness;
struct Input
{
float2 uv_MainTex;
float2 uv_BumpMap;
float4 screenPos;
};
void surf (Input IN, inout SurfaceOutputStandard o)
{
fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
// Refraction
float3 normal = UnpackNormal(tex2D (_BumpMap, IN.uv_BumpMap));
float2 offset = normal.xy * _RefractAmount;
IN.screenPos.xy += offset;
half3 grabColor = tex2Dproj(_GrabTexture, IN.screenPos).rgb;
o.Albedo = c.rgb;
o.Emission = grabColor * _RefractAmount;
o.Smoothness = _Glossiness;
o.Normal = normal;
o.Alpha = c.a * 0.8;
}
ENDCG
}
Fallback "Transparent/Cutout/VertexLit"
}
// 9. Vertex/Fragment Shader - Basic Unlit
Shader "Custom/BasicUnlit"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
_Color ("Color", Color) = (1,1,1,1)
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 100
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;
};
sampler2D _MainTex;
float4 _MainTex_ST;
fixed4 _Color;
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
return o;
}
fixed4 frag (v2f i) : SV_Target
{
fixed4 col = tex2D(_MainTex, i.uv) * _Color;
return col;
}
ENDCG
}
}
}
// 10. Vertex Color Shader
Shader "Custom/VertexColor"
{
SubShader
{
Tags { "RenderType"="Opaque" }
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
fixed4 color : COLOR;
};
struct v2f
{
float4 vertex : SV_POSITION;
fixed4 color : COLOR;
};
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.color = v.color;
return o;
}
fixed4 frag (v2f i) : SV_Target
{
return i.color;
}
ENDCG
}
}
}
💻 Advanced Unity Shaders glsl
🟡 intermediate
⭐⭐⭐⭐
Complex shader effects including parallax mapping, tessellation, and advanced lighting models
⏱️ 35 min
🏷️ unity, shader, advanced, parallax, tessellation
Prerequisites:
Advanced shader programming, Mathematics, Graphics pipeline
// Advanced Unity Shaders - HLSL/Cg
// 1. Parallax Occlusion Mapping Shader
Shader "Custom/ParallaxOcclusion"
{
Properties
{
_MainTex ("Albedo (RGB)", 2D) = "white" {}
_BumpMap ("Normal Map", 2D) = "bump" {}
_ParallaxMap ("Height Map", 2D) = "black" {}
_Parallax ("Height Scale", Range(0.005, 0.08)) = 0.02
_ParallaxMaxSteps ("Max Steps", Range(1, 50)) = 20
_ParallaxRefractionSteps ("Refraction Steps", Range(1, 20)) = 10
_Color ("Color", Color) = (1,1,1,1)
_Metallic ("Metallic", Range(0,1)) = 0.0
_Glossiness ("Glossiness", Range(0,1)) = 0.5
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 300
CGPROGRAM
#pragma surface surf Standard fullforwardshadows
#pragma target 3.0
#pragma shader_feature _PARALLAX_MAP
sampler2D _MainTex;
sampler2D _BumpMap;
sampler2D _ParallaxMap;
fixed4 _Color;
half _Metallic;
half _Glossiness;
float _Parallax;
int _ParallaxMaxSteps;
int _ParallaxRefractionSteps;
struct Input
{
float2 uv_MainTex;
float2 uv_BumpMap;
float2 uv_ParallaxMap;
float3 viewDir;
};
#if defined(_PARALLAX_MAP)
float2 ParallaxOffset(float2 uv, float3 viewDir)
{
float h = tex2D(_ParallaxMap, uv).r;
float height = h * _Parallax;
float2 offset = viewDir.xy / (viewDir.z + 0.42);
return uv - offset * height;
}
float2 RaymarchParallax(float2 uv, float3 viewDir)
{
float2 offset = 0;
float stepSize = 1.0 / _ParallaxMaxSteps;
for(int i = 0; i < _ParallaxMaxSteps; i++)
{
float h = tex2D(_ParallaxMap, uv + offset).r;
float height = h * _Parallax;
if(height > (float)i / _ParallaxMaxSteps)
{
offset -= viewDir.xy / viewDir.z * stepSize * _Parallax;
}
else
{
break;
}
}
return uv + offset;
}
#endif
void surf (Input IN, inout SurfaceOutputStandard o)
{
#if defined(_PARALLAX_MAP)
float2 uv = RaymarchParallax(IN.uv_ParallaxMap, IN.viewDir);
#else
float2 uv = IN.uv_MainTex;
#endif
fixed4 c = tex2D (_MainTex, uv) * _Color;
o.Albedo = c.rgb;
o.Normal = UnpackNormal(tex2D (_BumpMap, uv));
o.Metallic = _Metallic;
o.Smoothness = _Glossiness;
o.Alpha = c.a;
}
ENDCG
}
Fallback "Standard"
}
// 2. Tessellation Shader
Shader "Custom/Tessellation"
{
Properties
{
_MainTex ("Albedo (RGB)", 2D) = "white" {}
_Color ("Color", Color) = (1,1,1,1)
_Tessellation ("Tessellation", Range(1,32)) = 4
_MinDistance ("Min Distance", Range(1,20)) = 10
_MaxDistance ("Max Distance", Range(20,100)) = 50
_EdgeLength ("Edge Length", Range(2,50)) = 15
}
SubShader
{
Tags { "RenderType"="Opaque" }
CGPROGRAM
#pragma surface surf Standard fullforwardshadows vertex:disp tessellate:tessEdge nolightmap
#pragma hull hull_shader
#pragma domain domain_shader
#pragma target 4.6
sampler2D _MainTex;
fixed4 _Color;
float _Tessellation;
float _MinDistance;
float _MaxDistance;
float _EdgeLength;
struct appdata
{
float4 vertex : POSITION;
float3 normal : NORMAL;
float2 uv : TEXCOORD0;
};
struct v2f
{
float4 vertex : SV_POSITION;
float3 normal : NORMAL;
float2 uv : TEXCOORD0;
};
float4 disp (appdata v)
{
return v.vertex;
}
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.normal = v.normal;
o.uv = v.uv;
return o;
}
#ifdef UNITY_CAN_COMPILE_TESSELLATION
struct TessellationFactors
{
float edge[3] : SV_TessFactor;
float inside : SV_InsideTessFactor;
};
struct HS_CONSTANT_OUTPUT
{
float edges[3] : SV_TessFactor;
float inside : SV_InsideTessFactor;
};
HS_CONSTANT_OUTPUT hsConstant (InputPatch<appdata,3> v)
{
HS_CONSTANT_OUTPUT o;
float4 p0 = UnityObjectToViewPos(v[0].vertex);
float4 p1 = UnityObjectToViewPos(v[1].vertex);
float4 p2 = UnityObjectToViewPos(v[2].vertex);
float d0 = length(p0.xyz);
float d1 = length(p1.xyz);
float d2 = length(p2.xyz);
float minDist = min(min(d0, d1), d2);
float maxDist = max(max(d0, d1), d2);
float dist = saturate((minDist - _MinDistance) / (_MaxDistance - _MinDistance));
float factor = lerp(_Tessellation, 1, dist);
o.edges[0] = factor;
o.edges[1] = factor;
o.edges[2] = factor;
o.inside = factor;
return o;
}
[domain("tri")]
[partitioning("fractional_odd")]
[outputtopology("triangle_cw")]
[outputcontrolpoints(3)]
[patchconstantfunc("hsConstant")]
TessellationFactors hs (InputPatch<appdata,3> i, uint patchID : SV_PrimitiveID)
{
TessellationFactors o;
o.edge[0] = 4;
o.edge[1] = 4;
o.edge[2] = 4;
o.inside = 4;
return o;
}
struct HS_OUTPUT
{
float4 vertex : SV_POSITION;
float3 normal : NORMAL;
float2 uv : TEXCOORD0;
};
[domain("tri")]
DS_OUTPUT ds (TessellationFactors factors, OutputPatch<HS_OUTPUT,3> patch, float3 bary : SV_DomainLocation)
{
DS_OUTPUT o;
float3 vertex =
patch[0].vertex * bary.x +
patch[1].vertex * bary.y +
patch[2].vertex * bary.z;
float3 normal =
patch[0].normal * bary.x +
patch[1].normal * bary.y +
patch[2].normal * bary.z;
float2 uv =
patch[0].uv * bary.x +
patch[1].uv * bary.y +
patch[2].uv * bary.z;
o.vertex = vertex;
o.normal = normal;
o.uv = uv;
return o;
}
#endif
void surf (Input IN, inout SurfaceOutputStandard o)
{
fixed4 c = tex2D (_MainTex, IN.uv) * _Color;
o.Albedo = c.rgb;
o.Alpha = c.a;
}
ENDCG
}
Fallback "Standard"
}
// 3. Fur Shader
Shader "Custom/Fur"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
_Color ("Color", Color) = (1,1,1,1)
_FurLength ("Fur Length", Range(0.1, 1)) = 0.5
_FurDensity ("Fur Density", Range(0.01, 1)) = 0.3
_FurTiling ("Fur Tiling", float) = 1.0
_FurGravity ("Gravity Force", Range(0,1)) = 0.5
_FurColor ("Fur Color", Color) = (1,1,1,1)
_Layers ("Layer Count", Range(1, 100)) = 20
}
SubShader
{
Tags { "RenderType"="TransparentCutout" }
LOD 200
Cull Off
CGPROGRAM
#pragma surface surf Lambert vertex:vert alpha:fade
#pragma shader_feature _FURSHADER_ON
sampler2D _MainTex;
fixed4 _Color;
float _FurLength;
float _FurDensity;
float _FurTiling;
float _FurGravity;
fixed4 _FurColor;
int _Layers;
struct Input
{
float2 uv_MainTex;
float furLayer;
};
void vert(inout appdata_full v, out Input o)
{
UNITY_INITIALIZE_OUTPUT(Input);
o.uv_MainTex = v.texcoord;
o.furLayer = v.color.r; // Pass layer from vertex color
}
void surf (Input IN, inout SurfaceOutput o)
{
float2 uv = IN.uv_MainTex * _FurTiling + float2(IN.furLayer * 0.2, IN.furLayer * 0.3);
float4 fur = tex2D(_MainTex, uv);
// Alpha based on fur density and layer
float alpha = fur.r;
alpha = smoothstep(_FurDensity * (1.0 - IN.furLayer), 1.0, alpha);
// Fur color variation
fixed4 furColor = lerp(_Color, _FurColor, IN.furLayer * 0.5);
o.Albedo = furColor.rgb;
o.Alpha = alpha * (1.0 - IN.furLayer);
}
ENDCG
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma shader_feature _FURSHADER_ON
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
float3 normal : NORMAL;
fixed4 color : COLOR;
};
struct v2f
{
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
fixed4 color : COLOR;
};
sampler2D _MainTex;
float _FurLength;
float _FurGravity;
int _Layers;
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = v.uv;
o.color = v.color;
return o;
}
fixed4 frag (v2f i) : SV_Target
{
float fur = tex2D(_MainTex, i.uv).r;
float alpha = smoothstep(0.5, 1.0, fur);
return fixed4(1, 1, 1, alpha);
}
ENDCG
}
}
}
// 4. Holographic Shader
Shader "Custom/Holographic"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
_Color ("Color", Color) = (1,1,1,1)
_ScanLineSize ("Scan Line Size", Range(0.1, 10)) = 2.0
_ScanLineSpeed ("Scan Line Speed", Range(-10, 10)) = 2.0
_FlickerIntensity ("Flicker Intensity", Range(0, 1)) = 0.1
_FlickerSpeed ("Flicker Speed", Range(1, 100)) = 50.0
_GlowIntensity ("Glow Intensity", Range(0, 5)) = 2.0
}
SubShader
{
Tags {
"Queue"="Transparent"
"RenderType"="Transparent"
}
LOD 200
Cull Off
CGPROGRAM
#pragma surface surf Lambert alpha:fade
#pragma shader_feature _HOLOGRAM_SHADER_ON
sampler2D _MainTex;
fixed4 _Color;
float _ScanLineSize;
float _ScanLineSpeed;
float _FlickerIntensity;
float _FlickerSpeed;
float _GlowIntensity;
struct Input
{
float2 uv_MainTex;
float3 worldPos;
};
void surf (Input IN, inout SurfaceOutput o)
{
// Base texture
fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
// Scan lines
float scanline = sin(IN.worldPos.y * _ScanLineSize + _Time.y * _ScanLineSpeed) * 0.5 + 0.5;
scanline = pow(scanline, 2.0);
// Flicker effect
float flicker = sin(_Time.y * _FlickerSpeed) * 0.5 + 0.5;
flicker = lerp(1.0, flicker, _FlickerIntensity);
// Edge glow
float edge = 1.0 - saturate(dot(IN.worldPos - _WorldSpaceCameraPos, IN.worldPos - _WorldSpaceCameraPos));
// Combine effects
c.rgb = c.rgb * scanline * flicker + c.rgb * _GlowIntensity * edge;
o.Albedo = c.rgb;
o.Alpha = c.a * scanline * flicker;
o.Emission = c.rgb * _GlowIntensity * edge;
}
ENDCG
}
Fallback "Transparent/VertexLit"
}
// 5. Particle Shader with Soft Particles
Shader "Custom/SoftParticles"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
_Color ("Color", Color) = (1,1,1,1)
_InvFade ("Soft Particles Factor", Range(0.01,3.0)) = 1.0
_Softness ("Softness", Range(0,1)) = 0.5
}
SubShader
{
Tags {
"Queue"="Transparent"
"IgnoreProjector"="True"
"RenderType"="Transparent"
"PreviewType"="Plane"
}
Blend SrcAlpha OneMinusSrcAlpha
ColorMask RGB
Cull Off Lighting Off ZWrite Off
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile_particles
#include "UnityCG.cginc"
sampler2D _MainTex;
fixed4 _Color;
float _InvFade;
float _Softness;
struct appdata
{
float4 vertex : POSITION;
float3 normal : NORMAL;
fixed4 color : COLOR;
float2 uv : TEXCOORD0;
};
struct v2f
{
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
fixed4 color : COLOR;
#ifdef SOFTPARTICLES_ON
float4 projPos : TEXCOORD2;
#endif
};
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = v.uv;
o.color = v.color;
#ifdef SOFTPARTICLES_ON
o.projPos = ComputeScreenPos(o.vertex);
COMPUTE_EYEDEPTH(o.projPos);
#endif
return o;
}
fixed4 frag (v2f i) : SV_Target
{
#ifdef SOFTPARTICLES_ON
float sceneZ = LinearEyeDepth(SAMPLE_DEPTH_TEXTURE_PROJ(_CameraDepthTexture, i.projPos));
float partZ = i.projPos.z;
float fade = saturate(_InvFade * (sceneZ - partZ));
fade = pow(fade, 1.0 + _Softness);
i.color.a *= fade;
#endif
fixed4 c = tex2D(_MainTex, i.uv) * i.color * _Color;
return c;
}
ENDCG
}
}
}
💻 Post-Processing Shaders glsl
🔴 complex
⭐⭐⭐⭐
Screen-space effects including bloom, depth of field, motion blur, and screen transitions
⏱️ 45 min
🏷️ unity, shader, post processing, screen effects
Prerequisites:
Expert shader programming, Render pipeline, Graphics math
// Unity Post-Processing Shaders
// 1. Bloom Effect Shader
Shader "Hidden/PostProcessing/Bloom"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
_Threshold ("Bloom Threshold", Range(0, 1)) = 0.5
_Intensity ("Bloom Intensity", Range(0, 10)) = 1.0
_BlurSize ("Blur Size", Range(1, 10)) = 3.0
_Tint ("Bloom Tint", Color) = (1,1,1,1)
}
SubShader
{
Cull Off ZWrite Off ZTest Always
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
sampler2D _MainTex;
float4 _MainTex_TexelSize;
float _Threshold;
float _Intensity;
int _BlurSize;
fixed4 _Tint;
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float4 vertex : SV_POSITION;
float2 uv : TEXCOORD0;
};
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = v.uv;
return o;
}
fixed4 frag (v2f i) : SV_Target
{
fixed4 original = tex2D(_MainTex, i.uv);
// Apply threshold
fixed luminance = dot(original.rgb, fixed3(0.2126, 0.7152, 0.0722);
fixed4 bloom = luminance > _Threshold ? original : fixed4(0,0,0,1);
// Apply intensity and tint
bloom *= _Intensity * _Tint;
return bloom;
}
ENDCG
}
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
sampler2D _MainTex;
float4 _MainTex_TexelSize;
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float4 vertex : SV_POSITION;
float2 uv : TEXCOORD0;
};
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = v.uv;
return o;
}
fixed4 frag (v2f i) : SV_Target
{
float2 texelSize = _MainTex_TexelSize.xy;
float2 offset = texelSize * 2.0;
fixed4 color = tex2D(_MainTex, i.uv);
// Box blur
for(int x = -2; x <= 2; x++)
{
for(int y = -2; y <= 2; y++)
{
float2 offset = float2(x, y) * texelSize;
color += tex2D(_MainTex, i.uv + offset);
}
}
color /= 25.0; // Normalize by the number of samples
return color;
}
ENDCG
}
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
sampler2D _MainTex;
sampler2D _BloomTex;
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float4 vertex : SV_POSITION;
float2 uv : TEXCOORD0;
};
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = v.uv;
return o;
}
fixed4 frag (v2f i) : SV_Target
{
fixed4 original = tex2D(_MainTex, i.uv);
fixed4 bloom = tex2D(_BloomTex, i.uv);
return original + bloom;
}
ENDCG
}
}
}
// 2. Depth of Field Shader
Shader "Hidden/PostProcessing/DepthOfField"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
_FocalDepth ("Focal Depth", Range(0, 1)) = 0.5
_FocalRange ("Focal Range", Range(0, 1)) = 0.1
_MaxBlurSize ("Max Blur Size", Range(0, 10)) = 5.0
_Aperture ("Aperture", Range(0.1, 10)) = 2.8
}
SubShader
{
Cull Off ZWrite Off ZTest Always
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
sampler2D _MainTex;
sampler2D _CameraDepthTexture;
float4 _MainTex_TexelSize;
float _FocalDepth;
float _FocalRange;
float _MaxBlurSize;
float _Aperture;
float4 _ProjectionParams;
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float4 vertex : SV_POSITION;
float2 uv : TEXCOORD0;
float2 uvDepth : TEXCOORD1;
};
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = v.uv;
o.uvDepth = ComputeScreenPos(o.vertex).xy / ComputeScreenPos(o.vertex).w;
return o;
}
float LinearEyeDepth(float z)
{
return -Linear01Depth(z) * _ProjectionParams.z;
}
fixed4 frag (v2f i) : SV_Target
{
// Get scene depth
float depth = SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, i.uvDepth);
float sceneDepth = LinearEyeDepth(depth);
float focalPlane = _FocalDepth * _ProjectionParams.z;
// Calculate circle of confusion
float coc = abs(sceneDepth - focalPlane) / _FocalRange * _Aperture;
coc = saturate(coc);
// Apply blur based on CoC
float blurSize = coc * _MaxBlurSize;
fixed4 color = tex2D(_MainTex, i.uv);
if(blurSize > 1.0)
{
// Box blur
float2 texelSize = _MainTex_TexelSize.xy;
int blurRadius = (int)blurSize;
fixed4 blurredColor = fixed4(0,0,0,0);
int sampleCount = 0;
for(int x = -blurRadius; x <= blurRadius; x++)
{
for(int y = -blurRadius; y <= blurRadius; y++)
{
if(x*x + y*y <= blurRadius * blurRadius)
{
float2 offset = float2(x, y) * texelSize;
blurredColor += tex2D(_MainTex, i.uv + offset);
sampleCount++;
}
}
}
blurredColor /= sampleCount;
// Blend based on CoC
color = lerp(color, blurredColor, coc);
}
return color;
}
ENDCG
}
}
}
// 3. Motion Blur Shader
Shader "Hidden/PostProcessing/MotionBlur"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
_VelocityScale ("Velocity Scale", Range(0, 2)) = 1.0
_MaxVelocity ("Max Velocity", Range(0, 10)) = 5.0
_NumSamples ("Number of Samples", Range(4, 32)) = 16
}
SubShader
{
Cull Off ZWrite Off ZTest Always
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
sampler2D _MainTex;
sampler2D _VelocityTex;
float2 _MainTex_TexelSize;
float _VelocityScale;
float _MaxVelocity;
int _NumSamples;
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float4 vertex : SV_POSITION;
float2 uv : TEXCOORD0;
};
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = v.uv;
return o;
}
fixed4 frag (v2f i) : SV_Target
{
// Get velocity vector
float2 velocity = tex2D(_VelocityTex, i.uv).rg * 2.0 - 1.0;
velocity *= _VelocityScale;
// Limit velocity
float velocityLength = length(velocity);
if(velocityLength > _MaxVelocity)
{
velocity = normalize(velocity) * _MaxVelocity;
}
// Motion blur
float2 texelSize = _MainTex_TexelSize.xy;
fixed4 blurredColor = fixed4(0,0,0,0);
float totalWeight = 0.0;
for(int j = 0; j < _NumSamples; j++)
{
float t = (float)j / (_NumSamples - 1) - 0.5;
float2 sampleUV = i.uv + velocity * texelSize * t;
// Weight based on distance from center
float weight = 1.0 - abs(t);
blurredColor += tex2D(_MainTex, sampleUV) * weight;
totalWeight += weight;
}
blurredColor /= totalWeight;
return blurredColor;
}
ENDCG
}
}
}
// 4. Screen Transition Shader
Shader "Hidden/PostProcessing/ScreenTransition"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
_TransitionTex ("Transition Texture", 2D) = "white" {}
_NextTex ("Next Texture", 2D) = "white" {}
_Progress ("Transition Progress", Range(0, 1)) = 0.0
_TransitionType ("Transition Type", Range(0, 4)) = 0
_EdgeWidth ("Edge Width", Range(0, 0.5)) = 0.1
_EdgeSoftness ("Edge Softness", Range(0, 0.5)) = 0.05
}
SubShader
{
Cull Off ZWrite Off ZTest Always
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
sampler2D _MainTex;
sampler2D _TransitionTex;
sampler2D _NextTex;
float _Progress;
int _TransitionType;
float _EdgeWidth;
float _EdgeSoftness;
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float4 vertex : SV_POSITION;
float2 uv : TEXCOORD0;
};
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = v.uv;
return o;
}
float FadeTransition(float progress)
{
return progress;
}
float WipeTransition(float2 uv, float progress)
{
return progress > uv.x ? 1.0 : 0.0;
}
float CircleTransition(float2 uv, float progress)
{
float2 center = float2(0.5, 0.5);
float distance = length(uv - center);
return distance > (1.0 - progress) ? 1.0 : 0.0;
}
float DiagonalWipeTransition(float2 uv, float progress)
{
float2 diagonal = float2(1.0, 1.0);
float diagonalPos = dot(uv, normalize(diagonal));
return diagonalPos > progress ? 1.0 : 0.0;
}
float RandomTransition(float2 uv, float progress)
{
float noise = tex2D(_TransitionTex, uv).r;
return noise > progress ? 1.0 : 0.0;
}
fixed4 frag (v2f i) : SV_Target
{
float transitionValue = 0.0;
switch(_TransitionType)
{
case 0: // Fade
transitionValue = FadeTransition(_Progress);
break;
case 1: // Wipe
transitionValue = WipeTransition(i.uv, _Progress);
break;
case 2: // Circle
transitionValue = CircleTransition(i.uv, _Progress);
break;
case 3: // Diagonal Wipe
transitionValue = DiagonalWipeTransition(i.uv, _Progress);
break;
case 4: // Random Noise
transitionValue = RandomTransition(i.uv, _Progress);
break;
}
// Edge smoothing
float edge = smoothstep(_Progress - _EdgeSoftness, _Progress + _EdgeSoftness, transitionValue);
edge = smoothstep(_Progress - _EdgeWidth - _EdgeSoftness,
_Progress - _EdgeWidth + _EdgeSoftness, edge);
fixed4 currentColor = tex2D(_MainTex, i.uv);
fixed4 nextColor = tex2D(_NextTex, i.uv);
// Blend between scenes
fixed4 finalColor = lerp(nextColor, currentColor, edge);
return finalColor;
}
ENDCG
}
}
}
// 5. Vignette Effect Shader
Shader "Hidden/PostProcessing/Vignette"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
_VignetteIntensity ("Vignette Intensity", Range(0, 2)) = 1.0
_VignetteRadius ("Vignette Radius", Range(0, 2)) = 0.8
_VignetteSmoothness ("Vignette Smoothness", Range(0, 1)) = 0.1
_VignetteColor ("Vignette Color", Color) = (0,0,0,1)
}
SubShader
{
Cull Off ZWrite Off ZTest Always
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
sampler2D _MainTex;
float _VignetteIntensity;
float _VignetteRadius;
float _VignetteSmoothness;
fixed4 _VignetteColor;
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float4 vertex : SV_POSITION;
float2 uv : TEXCOORD0;
};
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = v.uv;
return o;
}
fixed4 frag (v2f i) : SV_Target
{
fixed4 originalColor = tex2D(_MainTex, i.uv);
// Calculate vignette
float2 center = float2(0.5, 0.5);
float dist = distance(i.uv, center);
float vignette = 1.0 - smoothstep(_VignetteRadius, _VignetteRadius + _VignetteSmoothness, dist);
vignette = saturate(vignette * _VignetteIntensity);
// Apply vignette
fixed3 vignetteColor = lerp(_VignetteColor.rgb, originalColor.rgb, vignette);
return fixed4(vignetteColor, originalColor.a);
}
ENDCG
}
}
}