Shader "Bansonic/Sprite Glow" { Properties { [PerRendererData] _MainTex ("Sprite Texture", 2D) = "white" {} [HideInInspector] _Color ("Tint", Color) = (1,1,1,1) [HideInInspector] PixelSnap ("Pixel snap", Float) = 0 [HideInInspector] _RendererColor ("RendererColor", Color) = (1,1,1,1) [HideInInspector] _AlphaTex ("External Alpha", 2D) = "white" {} [HideInInspector] _EnableExternalAlpha ("Enable External Alpha", Float) = 0 [HDR]_GlowColor ("Glow Color", Color) = (1,1,1,1) _Threshold ("Glow Threshold", Range(0, 4)) = 0.9 _Intensity ("Glow Intensity", Range(0, 8)) = 1.5 _GlowRadius ("Glow Radius", Range(0, 32)) = 6 } SubShader { Tags { "Queue" = "Transparent" "RenderType" = "Transparent" "RenderPipeline" = "UniversalPipeline" "CanUseSpriteAtlas" = "True" } Blend SrcAlpha OneMinusSrcAlpha, One OneMinusSrcAlpha Cull Off ZWrite Off Pass { Tags { "LightMode" = "Universal2D" } HLSLPROGRAM #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl" #include "Packages/com.unity.render-pipelines.universal/Shaders/2D/Include/Core2D.hlsl" #pragma vertex SpriteVertex #pragma fragment SpriteFragment #pragma target 2.0 #pragma multi_compile_instancing #pragma multi_compile _ SKINNED_SPRITE struct Attributes { float3 positionOS : POSITION; float4 color : COLOR; float2 uv : TEXCOORD0; UNITY_SKINNED_VERTEX_INPUTS UNITY_VERTEX_INPUT_INSTANCE_ID }; struct Varyings { float4 positionCS : SV_POSITION; half4 color : COLOR; float2 uv : TEXCOORD0; UNITY_VERTEX_OUTPUT_STEREO }; TEXTURE2D(_MainTex); SAMPLER(sampler_MainTex); float4 _MainTex_TexelSize; CBUFFER_START(UnityPerMaterial) half4 _Color; half4 _GlowColor; half _Threshold; half _Intensity; half _GlowRadius; CBUFFER_END Varyings SpriteVertex(Attributes input) { Varyings output = (Varyings)0; UNITY_SETUP_INSTANCE_ID(input); UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output); UNITY_SKINNED_VERTEX_COMPUTE(input); SetUpSpriteInstanceProperties(); input.positionOS = UnityFlipSprite(input.positionOS, unity_SpriteProps.xy); output.positionCS = TransformObjectToHClip(input.positionOS); output.uv = input.uv; output.color = input.color * _Color * unity_SpriteColor; return output; } half GetLuminance(half3 color) { return dot(color, half3(0.2126h, 0.7152h, 0.0722h)); } half SampleGlowMask(float2 uv, half4 tint) { half4 tex = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, uv) * tint; half luminance = GetLuminance(tex.rgb); half mask = smoothstep(_Threshold - 0.18h, _Threshold + 0.18h, luminance); return mask * tex.a; } half ComputeGlow(float2 uv, half4 tint) { float2 texel = _MainTex_TexelSize.xy * max(_GlowRadius, 0.001h) * 1.5; const half w0 = 0.180h; const half w1 = 0.150h; const half w2 = 0.120h; const half w3 = 0.090h; const half w4 = 0.060h; half sum = SampleGlowMask(uv, tint) * w0; sum += SampleGlowMask(uv + texel * float2( 0.65, 0.00), tint) * w1; sum += SampleGlowMask(uv + texel * float2(-0.65, 0.00), tint) * w1; sum += SampleGlowMask(uv + texel * float2( 0.00, 0.65), tint) * w1; sum += SampleGlowMask(uv + texel * float2( 0.00, -0.65), tint) * w1; sum += SampleGlowMask(uv + texel * float2( 0.50, 0.50), tint) * w2; sum += SampleGlowMask(uv + texel * float2(-0.50, 0.50), tint) * w2; sum += SampleGlowMask(uv + texel * float2( 0.50, -0.50), tint) * w2; sum += SampleGlowMask(uv + texel * float2(-0.50, -0.50), tint) * w2; sum += SampleGlowMask(uv + texel * float2( 1.35, 0.00), tint) * w3; sum += SampleGlowMask(uv + texel * float2(-1.35, 0.00), tint) * w3; sum += SampleGlowMask(uv + texel * float2( 0.00, 1.35), tint) * w3; sum += SampleGlowMask(uv + texel * float2( 0.00, -1.35), tint) * w3; sum += SampleGlowMask(uv + texel * float2( 1.00, 1.00), tint) * w4; sum += SampleGlowMask(uv + texel * float2(-1.00, 1.00), tint) * w4; sum += SampleGlowMask(uv + texel * float2( 1.00, -1.00), tint) * w4; sum += SampleGlowMask(uv + texel * float2(-1.00, -1.00), tint) * w4; return sum; } half4 SpriteFragment(Varyings input) : SV_Target { half4 baseSample = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, input.uv) * input.color; half glowStrength = ComputeGlow(input.uv, input.color) * _Intensity * 1.75h; half3 glow = _GlowColor.rgb * glowStrength * _GlowColor.a; half4 color = baseSample; color.rgb += glow; color.a = saturate(baseSample.a + glowStrength * 0.55h); return color; } ENDHLSL } Pass { Tags { "LightMode" = "UniversalForward" } HLSLPROGRAM #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl" #include "Packages/com.unity.render-pipelines.universal/Shaders/2D/Include/Core2D.hlsl" #pragma vertex SpriteVertex #pragma fragment SpriteFragment #pragma target 2.0 #pragma multi_compile_instancing #pragma multi_compile _ SKINNED_SPRITE struct Attributes { float3 positionOS : POSITION; float4 color : COLOR; float2 uv : TEXCOORD0; UNITY_SKINNED_VERTEX_INPUTS UNITY_VERTEX_INPUT_INSTANCE_ID }; struct Varyings { float4 positionCS : SV_POSITION; half4 color : COLOR; float2 uv : TEXCOORD0; UNITY_VERTEX_OUTPUT_STEREO }; TEXTURE2D(_MainTex); SAMPLER(sampler_MainTex); float4 _MainTex_TexelSize; CBUFFER_START(UnityPerMaterial) half4 _Color; half4 _GlowColor; half _Threshold; half _Intensity; half _GlowRadius; CBUFFER_END Varyings SpriteVertex(Attributes input) { Varyings output = (Varyings)0; UNITY_SETUP_INSTANCE_ID(input); UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output); UNITY_SKINNED_VERTEX_COMPUTE(input); SetUpSpriteInstanceProperties(); input.positionOS = UnityFlipSprite(input.positionOS, unity_SpriteProps.xy); output.positionCS = TransformObjectToHClip(input.positionOS); output.uv = input.uv; output.color = input.color * _Color * unity_SpriteColor; return output; } half GetLuminance(half3 color) { return dot(color, half3(0.2126h, 0.7152h, 0.0722h)); } half SampleGlowMask(float2 uv, half4 tint) { half4 tex = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, uv) * tint; half luminance = GetLuminance(tex.rgb); half mask = smoothstep(_Threshold - 0.18h, _Threshold + 0.18h, luminance); return mask * tex.a; } half ComputeGlow(float2 uv, half4 tint) { float2 texel = _MainTex_TexelSize.xy * max(_GlowRadius, 0.001h) * 1.5; const half w0 = 0.180h; const half w1 = 0.150h; const half w2 = 0.120h; const half w3 = 0.090h; const half w4 = 0.060h; half sum = SampleGlowMask(uv, tint) * w0; sum += SampleGlowMask(uv + texel * float2( 0.65, 0.00), tint) * w1; sum += SampleGlowMask(uv + texel * float2(-0.65, 0.00), tint) * w1; sum += SampleGlowMask(uv + texel * float2( 0.00, 0.65), tint) * w1; sum += SampleGlowMask(uv + texel * float2( 0.00, -0.65), tint) * w1; sum += SampleGlowMask(uv + texel * float2( 0.50, 0.50), tint) * w2; sum += SampleGlowMask(uv + texel * float2(-0.50, 0.50), tint) * w2; sum += SampleGlowMask(uv + texel * float2( 0.50, -0.50), tint) * w2; sum += SampleGlowMask(uv + texel * float2(-0.50, -0.50), tint) * w2; sum += SampleGlowMask(uv + texel * float2( 1.35, 0.00), tint) * w3; sum += SampleGlowMask(uv + texel * float2(-1.35, 0.00), tint) * w3; sum += SampleGlowMask(uv + texel * float2( 0.00, 1.35), tint) * w3; sum += SampleGlowMask(uv + texel * float2( 0.00, -1.35), tint) * w3; sum += SampleGlowMask(uv + texel * float2( 1.00, 1.00), tint) * w4; sum += SampleGlowMask(uv + texel * float2(-1.00, 1.00), tint) * w4; sum += SampleGlowMask(uv + texel * float2( 1.00, -1.00), tint) * w4; sum += SampleGlowMask(uv + texel * float2(-1.00, -1.00), tint) * w4; return sum; } half4 SpriteFragment(Varyings input) : SV_Target { half4 baseSample = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, input.uv) * input.color; half glowStrength = ComputeGlow(input.uv, input.color) * _Intensity * 1.75h; half3 glow = _GlowColor.rgb * glowStrength * _GlowColor.a; half4 color = baseSample; color.rgb += glow; color.a = saturate(baseSample.a + glowStrength * 0.55h); return color; } ENDHLSL } } FallBack "Universal Render Pipeline/2D/Sprite-Unlit-Default" }