Skip to content

Instantly share code, notes, and snippets.

@JohannesMP
Created October 3, 2018 13:22
Show Gist options
  • Save JohannesMP/8d0f531b815dfad07823d44bc12b8112 to your computer and use it in GitHub Desktop.
Save JohannesMP/8d0f531b815dfad07823d44bc12b8112 to your computer and use it in GitHub Desktop.
UIBlur_WIP
static const float MAX_RADIUS = 128;
static const float ITER_STEP = 2;
#include "UnityCG.cginc"
#include "UnityUI.cginc"
struct appdata_t
{
float4 vertex : POSITION;
float2 texcoord: TEXCOORD0;
float4 color : COLOR;
};
struct v2f
{
float4 vertex : POSITION;
float4 uvgrab : TEXCOORD0;
float4 worldpos : TEXCOORD1;
float2 uvmain : TEXCOORD2;
float4 color : COLOR;
};
sampler2D _MainTex;
float4 _MainTex_ST;
v2f vert(appdata_t v)
{
v2f OUT;
UNITY_SETUP_INSTANCE_ID(v);
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(OUT);
OUT.worldpos = v.vertex;
OUT.vertex = UnityObjectToClipPos(v.vertex);
#if UNITY_UV_STARTS_AT_TOP
float scale = -1.0;
#else
float scale = 1.0;
#endif
OUT.uvgrab.xy = (float2(OUT.vertex.x, OUT.vertex.y*scale) + OUT.vertex.w) * 0.5;
OUT.uvgrab.zw = OUT.vertex.zw;
OUT.uvmain = TRANSFORM_TEX(v.texcoord, _MainTex);
OUT.color = v.color;
return OUT;
}
sampler2D _GrabTexture;
float4 _GrabTexture_TexelSize;
float _Radius;
float _Visibility;
float4 _ClipRect;
half4 layerBlend(half4 back, half4 front)
{
half a0 = front.a;
half a1 = back.a;
half a01 = (1 - a0)*a1 + a0;
return half4(
((1 - a0)*a1*back.r + a0*front.r) / a01,
((1 - a0)*a1*back.g + a0*front.g) / a01,
((1 - a0)*a1*back.b + a0*front.b) / a01,
a01);
}
half4 GrabPixel(sampler2D tex, float4 uv)
{
half4 pixel = tex2Dproj(tex, UNITY_PROJ_COORD(uv));
return half4(pixel.rgb, 1);
}
half4 GrabPixelXY(sampler2D tex, float4 uv, float4 size, half kernelx, half kernely)
{
half4 pixel = tex2Dproj(
tex,
UNITY_PROJ_COORD(
float4(
uv.x + size.x * kernelx,
uv.y + size.y * kernely,
uv.z,
uv.w)
)
);
return half4(pixel.rgb, 1);
}
half4 GetBlurInDir(v2f IN, half4 pixel, half dirx, half diry)
{
#if IS_BLUR_ALPHA_MASKED
float visibility = clamp(_Visibility, 0, 1)*pixel.a;
#else
float visibility = clamp(_Visibility, 0, 1);
#endif
float radius = clamp(_Radius, 0, MAX_RADIUS);
visibility *= UnityGet2DClipping(IN.worldpos.xy, _ClipRect);
half4 base = GrabPixel(_GrabTexture, IN.uvgrab);
float4 sum = base;
half steps = 1;
for (half range = ITER_STEP; range <= radius; range += ITER_STEP)
{
sum += GrabPixelXY(_GrabTexture, IN.uvgrab, _GrabTexture_TexelSize, range*dirx, range*diry);
sum += GrabPixelXY(_GrabTexture, IN.uvgrab, _GrabTexture_TexelSize, -range*dirx, -range*diry);
steps += 2;
}
return base * (1 - visibility) + (sum / steps)*visibility;
}
Shader "Custom/UIBlur_WIP"
{
Properties
{
[Toggle(IS_BLUR_ALPHA_MASKED)] _IsAlphaMasked("Image Alpha Masks Blur", Float) = 1
[Toggle(IS_SPRITE_VISIBLE)] _IsSpriteVisible("Show Image", Float) = 1
// Internally enforced by MAX_RADIUS
_Radius("Blur Radius", Range(0, 128)) = 1
_Visibility("Blur Visibility", Range(0, 1)) = 1
// see Stencil in UI/Default
[HideInInspector][PerRendererData] _MainTex ("Sprite Texture", 2D) = "white" {}
[HideInInspector]_StencilComp ("Stencil Comparison", Float) = 8
[HideInInspector]_Stencil ("Stencil ID", Float) = 0
[HideInInspector]_StencilOp ("Stencil Operation", Float) = 0
[HideInInspector]_StencilWriteMask ("Stencil Write Mask", Float) = 255
[HideInInspector]_StencilReadMask ("Stencil Read Mask", Float) = 255
[HideInInspector]_ColorMask ("Color Mask", Float) = 15
[HideInInspector]_UseUIAlphaClip ("Use Alpha Clip", Float) = 0
}
Category
{
Tags
{
"Queue" = "Transparent"
"IgnoreProjector" = "True"
"RenderType" = "Transparent"
"PreviewType" = "Plane"
"CanUseSpriteAtlas" = "True"
}
Stencil
{
Ref [_Stencil]
Comp [_StencilComp]
Pass [_StencilOp]
ReadMask [_StencilReadMask]
WriteMask [_StencilWriteMask]
}
Cull Off
Lighting Off
ZWrite Off
ZTest [unity_GUIZTestMode]
Blend SrcAlpha OneMinusSrcAlpha
ColorMask [_ColorMask]
SubShader
{
GrabPass
{
Tags{ "LightMode" = "Always" }
}
Pass
{
Tags{ "LightMode" = "Always" }
NAME "_BLURY"
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma fragmentoption ARB_precision_hint_fastest
#pragma multi_compile __ IS_BLUR_ALPHA_MASKED
#pragma multi_compile __ IS_SPRITE_VISIBLE
#pragma multi_compile __ UNITY_UI_ALPHACLIP
#include "BlurPass_Shared.cginc"
half4 frag(v2f IN) : COLOR
{
half4 pixel_raw = tex2D(_MainTex, IN.uvmain);
return GetBlurInDir(IN, pixel_raw, 0, 1);
}
ENDCG
}
GrabPass
{
Tags{ "LightMode" = "Always" }
}
Pass
{
Tags{ "LightMode" = "Always" }
NAME "_BLURX"
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma fragmentoption ARB_precision_hint_fastest
#pragma multi_compile __ IS_BLUR_ALPHA_MASKED
#pragma multi_compile __ IS_SPRITE_VISIBLE
#pragma multi_compile __ UNITY_UI_ALPHACLIP
#include "BlurPass_Shared.cginc"
half4 frag(v2f IN) : COLOR
{
half4 pixel_raw = tex2D(_MainTex, IN.uvmain);
#if IS_SPRITE_VISIBLE
return layerBlend(
// Layer 0 : The blurred background
GetBlurInDir(IN, pixel_raw, 1, 0),
// Layer 1 : The sprite itself
pixel_raw * IN.color
);
#else
return GetBlurInDir(IN, pixel_raw, 1, 0);
#endif
}
ENDCG
}
}
}
Fallback "UI/Default"
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment