阶段性完成
This commit is contained in:
65
Assets/Shaders/UI/Contour Flow.mat
Normal file
65
Assets/Shaders/UI/Contour Flow.mat
Normal file
@@ -0,0 +1,65 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!21 &2100000
|
||||
Material:
|
||||
serializedVersion: 8
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_Name: Contour Flow
|
||||
m_Shader: {fileID: 4800000, guid: caa72d45b56d4aca8bd51d79b8d99135, type: 3}
|
||||
m_Parent: {fileID: 0}
|
||||
m_ModifiedSerializedProperties: 0
|
||||
m_ValidKeywords: []
|
||||
m_InvalidKeywords: []
|
||||
m_LightmapFlags: 4
|
||||
m_EnableInstancingVariants: 0
|
||||
m_DoubleSidedGI: 0
|
||||
m_CustomRenderQueue: -1
|
||||
stringTagMap: {}
|
||||
disabledShaderPasses: []
|
||||
m_LockedProperties:
|
||||
m_SavedProperties:
|
||||
serializedVersion: 3
|
||||
m_TexEnvs:
|
||||
- _MainTex:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
m_Ints: []
|
||||
m_Floats:
|
||||
- _BottomGlowPower: 8
|
||||
- _BottomGlowStrength: 1
|
||||
- _BreathSpeed: 4
|
||||
- _ColorMask: 15
|
||||
- _EchoDistance: 0.02
|
||||
- _EchoStrength: 2
|
||||
- _FlowScale: 4
|
||||
- _FlowSpeed: 0.18
|
||||
- _FlowStrength: 0.03
|
||||
- _LineBoost: 0.38
|
||||
- _LineSoftness: 0.14
|
||||
- _LineThreshold: 0
|
||||
- _PulseIntensity: 3
|
||||
- _PulseSpeed: 2
|
||||
- _PulseWidth: 0.02
|
||||
- _RippleFrequency: 32
|
||||
- _RippleRadius: 0.9
|
||||
- _RippleSpeed: 0.7
|
||||
- _RippleStrength: 0.003
|
||||
- _Stencil: 0
|
||||
- _StencilComp: 8
|
||||
- _StencilOp: 0
|
||||
- _StencilReadMask: 255
|
||||
- _StencilWriteMask: 255
|
||||
- _UseClipRect: 0
|
||||
- _UseUIAlphaClip: 0
|
||||
m_Colors:
|
||||
- _AccentColor: {r: 0.6399999, g: 0.37999994, b: 1, a: 1}
|
||||
- _BottomGlowColor: {r: 0.04, g: 0.19999996, b: 1, a: 1}
|
||||
- _Color: {r: 1, g: 1, b: 1, a: 1}
|
||||
- _LineColor: {r: 0.35999998, g: 0.58, b: 1, a: 1}
|
||||
- _RippleCenter: {r: 0.38, g: 0.48, b: 0, a: 0}
|
||||
m_BuildTextureStacks: []
|
||||
m_AllowLocking: 1
|
||||
8
Assets/Shaders/UI/Contour Flow.mat.meta
Normal file
8
Assets/Shaders/UI/Contour Flow.mat.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3722087dd8cab124386a1b764bef2017
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 2100000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
306
Assets/Shaders/UI/UI_ContourFlow.shader
Normal file
306
Assets/Shaders/UI/UI_ContourFlow.shader
Normal file
@@ -0,0 +1,306 @@
|
||||
Shader "Ichni/UI/Contour Flow"
|
||||
{
|
||||
Properties
|
||||
{
|
||||
[PerRendererData] _MainTex ("Sprite Texture", 2D) = "white" {}
|
||||
_Color ("Tint", Color) = (1, 1, 1, 1)
|
||||
|
||||
[Header(Organic Motion)]
|
||||
_FlowScale ("Flow Scale", Range(0.5, 12)) = 4.0
|
||||
_FlowSpeed ("Flow Speed", Range(-2, 2)) = 0.18
|
||||
_FlowStrength ("Flow Strength", Range(0, 0.03)) = 0.004
|
||||
_RippleCenter ("Ripple Center", Vector) = (0.38, 0.48, 0, 0)
|
||||
_RippleRadius ("Ripple Radius", Range(0.05, 1.5)) = 0.9
|
||||
_RippleFrequency ("Ripple Frequency", Range(1, 80)) = 32
|
||||
_RippleSpeed ("Ripple Speed", Range(-10, 10)) = 0.7
|
||||
_RippleStrength ("Ripple Strength", Range(0, 0.03)) = 0.003
|
||||
|
||||
[Header(Contour Energy)]
|
||||
_LineColor ("Line Color", Color) = (0.36, 0.58, 1, 1)
|
||||
_AccentColor ("Pulse Accent", Color) = (0.64, 0.38, 1, 1)
|
||||
_LineThreshold ("Line Threshold", Range(0, 1)) = 0.17
|
||||
_LineSoftness ("Line Softness", Range(0.001, 0.5)) = 0.14
|
||||
_LineBoost ("Line Boost", Range(0, 2)) = 0.38
|
||||
_PulseSpeed ("Pulse Speed", Range(-2, 2)) = 0.08
|
||||
_PulseWidth ("Pulse Width", Range(0.02, 0.48)) = 0.14
|
||||
_PulseIntensity ("Pulse Intensity", Range(0, 3)) = 0.9
|
||||
_BreathSpeed ("Breath Speed", Range(0, 4)) = 0.55
|
||||
_EchoDistance ("Colored Echo Distance", Range(0, 0.02)) = 0.002
|
||||
_EchoStrength ("Colored Echo Strength", Range(0, 2)) = 0.22
|
||||
|
||||
[Header(Bottom Energy)]
|
||||
_BottomGlowColor ("Bottom Glow Color", Color) = (0.04, 0.2, 1, 1)
|
||||
_BottomGlowStrength ("Bottom Glow Strength", Range(0, 1)) = 0.14
|
||||
_BottomGlowPower ("Bottom Glow Falloff", Range(0.5, 8)) = 3.2
|
||||
|
||||
[Header(UI)]
|
||||
_StencilComp ("Stencil Comparison", Float) = 8
|
||||
_Stencil ("Stencil ID", Float) = 0
|
||||
_StencilOp ("Stencil Operation", Float) = 0
|
||||
_StencilWriteMask ("Stencil Write Mask", Float) = 255
|
||||
_StencilReadMask ("Stencil Read Mask", Float) = 255
|
||||
_ColorMask ("Color Mask", Float) = 15
|
||||
[Toggle(UNITY_UI_CLIP_RECT)] _UseClipRect ("Use UI Clip Rect", Float) = 0
|
||||
[Toggle(UNITY_UI_ALPHACLIP)] _UseUIAlphaClip ("Use UI Alpha Clip", Float) = 0
|
||||
}
|
||||
|
||||
SubShader
|
||||
{
|
||||
Tags
|
||||
{
|
||||
"Queue" = "Transparent"
|
||||
"IgnoreProjector" = "True"
|
||||
"RenderType" = "Transparent"
|
||||
"PreviewType" = "Plane"
|
||||
"CanUseSpriteAtlas" = "False"
|
||||
}
|
||||
|
||||
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]
|
||||
|
||||
Pass
|
||||
{
|
||||
Name "Contour Flow UI"
|
||||
|
||||
CGPROGRAM
|
||||
#pragma target 3.0
|
||||
#pragma vertex vert
|
||||
#pragma fragment frag
|
||||
#pragma multi_compile_local _ UNITY_UI_CLIP_RECT
|
||||
#pragma multi_compile_local _ UNITY_UI_ALPHACLIP
|
||||
|
||||
#include "UnityCG.cginc"
|
||||
#include "UnityUI.cginc"
|
||||
|
||||
struct appdata_t
|
||||
{
|
||||
float4 vertex : POSITION;
|
||||
fixed4 color : COLOR;
|
||||
float2 texcoord : TEXCOORD0;
|
||||
UNITY_VERTEX_INPUT_INSTANCE_ID
|
||||
};
|
||||
|
||||
struct v2f
|
||||
{
|
||||
float4 vertex : SV_POSITION;
|
||||
fixed4 color : COLOR;
|
||||
float4 texcoord : TEXCOORD0;
|
||||
float4 worldPosition : TEXCOORD1;
|
||||
half4 mask : TEXCOORD2;
|
||||
UNITY_VERTEX_OUTPUT_STEREO
|
||||
};
|
||||
|
||||
sampler2D _MainTex;
|
||||
float4 _MainTex_ST;
|
||||
float4 _MainTex_TexelSize;
|
||||
fixed4 _Color;
|
||||
fixed4 _TextureSampleAdd;
|
||||
float4 _ClipRect;
|
||||
float _UIMaskSoftnessX;
|
||||
float _UIMaskSoftnessY;
|
||||
|
||||
float _FlowScale;
|
||||
float _FlowSpeed;
|
||||
float _FlowStrength;
|
||||
float4 _RippleCenter;
|
||||
float _RippleRadius;
|
||||
float _RippleFrequency;
|
||||
float _RippleSpeed;
|
||||
float _RippleStrength;
|
||||
|
||||
fixed4 _LineColor;
|
||||
fixed4 _AccentColor;
|
||||
float _LineThreshold;
|
||||
float _LineSoftness;
|
||||
float _LineBoost;
|
||||
float _PulseSpeed;
|
||||
float _PulseWidth;
|
||||
float _PulseIntensity;
|
||||
float _BreathSpeed;
|
||||
float _EchoDistance;
|
||||
float _EchoStrength;
|
||||
|
||||
fixed4 _BottomGlowColor;
|
||||
float _BottomGlowStrength;
|
||||
float _BottomGlowPower;
|
||||
|
||||
v2f vert(appdata_t v)
|
||||
{
|
||||
v2f o;
|
||||
UNITY_SETUP_INSTANCE_ID(v);
|
||||
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
|
||||
|
||||
o.worldPosition = v.vertex;
|
||||
o.vertex = UnityObjectToClipPos(o.worldPosition);
|
||||
o.texcoord.xy = TRANSFORM_TEX(v.texcoord, _MainTex);
|
||||
o.texcoord.zw = v.texcoord;
|
||||
o.color = v.color * _Color;
|
||||
|
||||
float2 pixelSize = o.vertex.w;
|
||||
pixelSize /= abs(mul((float2x2)UNITY_MATRIX_P, _ScreenParams.xy));
|
||||
|
||||
float4 clampedRect = clamp(_ClipRect, -2e10, 2e10);
|
||||
o.mask = half4(
|
||||
v.vertex.xy * 2 - clampedRect.xy - clampedRect.zw,
|
||||
0.25 / (0.25 * half2(_UIMaskSoftnessX, _UIMaskSoftnessY) + abs(pixelSize.xy))
|
||||
);
|
||||
|
||||
return o;
|
||||
}
|
||||
|
||||
half PerceivedLuminance(half3 color)
|
||||
{
|
||||
#ifndef UNITY_COLORSPACE_GAMMA
|
||||
color = LinearToGammaSpace(color);
|
||||
#endif
|
||||
|
||||
return dot(color, half3(0.2126, 0.7152, 0.0722));
|
||||
}
|
||||
|
||||
float2 BuildAnimatedUV(float2 uv, out float2 flowDirection, out float flowSignal)
|
||||
{
|
||||
float time = _Time.y;
|
||||
float aspect = max(_MainTex_TexelSize.z / max(_MainTex_TexelSize.w, 1.0), 0.001);
|
||||
|
||||
float2 aspectPosition = uv - 0.5;
|
||||
aspectPosition.x *= aspect;
|
||||
|
||||
float flowTime = time * _FlowSpeed;
|
||||
float flowX =
|
||||
sin(aspectPosition.y * _FlowScale + flowTime) +
|
||||
0.45 * sin((aspectPosition.x + aspectPosition.y) * (_FlowScale * 0.73) - flowTime * 0.61);
|
||||
float flowY =
|
||||
cos(aspectPosition.x * (_FlowScale * 0.89) - flowTime * 0.83) +
|
||||
0.45 * sin((aspectPosition.x - aspectPosition.y) * (_FlowScale * 0.57) + flowTime * 0.47);
|
||||
|
||||
float2 flow = float2(flowX, flowY) / 1.45;
|
||||
float2 flowUV = flow;
|
||||
flowUV.x /= aspect;
|
||||
|
||||
float2 rippleDelta = uv - _RippleCenter.xy;
|
||||
rippleDelta.x *= aspect;
|
||||
float rippleDistance = max(length(rippleDelta), 0.0001);
|
||||
float2 rippleDirection = rippleDelta / rippleDistance;
|
||||
float rippleEnvelope = 1.0 - smoothstep(_RippleRadius * 0.2, _RippleRadius, rippleDistance);
|
||||
float rippleWave = sin(rippleDistance * _RippleFrequency - time * _RippleSpeed);
|
||||
float2 rippleUV = rippleDirection;
|
||||
rippleUV.x /= aspect;
|
||||
|
||||
float2 animatedUV =
|
||||
uv +
|
||||
flowUV * _FlowStrength +
|
||||
rippleUV * (rippleWave * rippleEnvelope * _RippleStrength);
|
||||
|
||||
flowDirection = normalize(flowUV + rippleUV * (rippleWave * rippleEnvelope) + float2(0.001, 0.001));
|
||||
flowSignal = (flowX + flowY + rippleWave * rippleEnvelope) * 0.3333;
|
||||
|
||||
float2 halfTexel = _MainTex_TexelSize.xy * 0.5;
|
||||
return clamp(animatedUV, halfTexel, 1.0 - halfTexel);
|
||||
}
|
||||
|
||||
fixed4 frag(v2f i) : SV_Target
|
||||
{
|
||||
float2 flowDirection;
|
||||
float flowSignal;
|
||||
float2 animatedUV = BuildAnimatedUV(i.texcoord.xy, flowDirection, flowSignal);
|
||||
|
||||
half4 source = tex2D(_MainTex, animatedUV) + _TextureSampleAdd;
|
||||
half sourceLuminance = PerceivedLuminance(source.rgb);
|
||||
half echoDifference = 0;
|
||||
|
||||
UNITY_BRANCH
|
||||
if (_EchoStrength > 0.0001 && _EchoDistance > 0.000001)
|
||||
{
|
||||
float2 halfTexel = _MainTex_TexelSize.xy * 0.5;
|
||||
float2 echoUV = clamp(
|
||||
animatedUV - flowDirection * _EchoDistance,
|
||||
halfTexel,
|
||||
1.0 - halfTexel
|
||||
);
|
||||
half echoLuminance = PerceivedLuminance(tex2D(_MainTex, echoUV).rgb);
|
||||
echoDifference = saturate(abs(echoLuminance - sourceLuminance) * 5.0);
|
||||
}
|
||||
|
||||
half lineMask = smoothstep(
|
||||
_LineThreshold,
|
||||
_LineThreshold + max(_LineSoftness, 0.001),
|
||||
sourceLuminance
|
||||
);
|
||||
|
||||
float pulsePhase = frac(
|
||||
animatedUV.y * 0.78 +
|
||||
animatedUV.x * 0.22 +
|
||||
flowSignal * 0.035 -
|
||||
_Time.y * _PulseSpeed
|
||||
);
|
||||
float pulseDistance = abs(pulsePhase - 0.5);
|
||||
float pulseFeather = max(fwidth(pulsePhase) * 1.5, 0.006);
|
||||
half pulse = 1.0 - smoothstep(
|
||||
_PulseWidth,
|
||||
_PulseWidth + pulseFeather,
|
||||
pulseDistance
|
||||
);
|
||||
|
||||
half breath = 0.8 + 0.2 * sin(
|
||||
_Time.y * _BreathSpeed +
|
||||
sourceLuminance * 12.0 +
|
||||
flowSignal
|
||||
);
|
||||
half lineEnergy =
|
||||
lineMask *
|
||||
breath *
|
||||
(0.35 + pulse * _PulseIntensity) *
|
||||
_LineBoost;
|
||||
|
||||
half3 movingLineColor = lerp(
|
||||
_LineColor.rgb * _LineColor.a,
|
||||
_AccentColor.rgb * _AccentColor.a,
|
||||
pulse
|
||||
);
|
||||
|
||||
half echoEnergy = echoDifference * (0.35 + pulse * 0.65) * _EchoStrength;
|
||||
|
||||
half bottomGlow = pow(saturate(1.0 - i.texcoord.w), _BottomGlowPower);
|
||||
bottomGlow *= _BottomGlowStrength *
|
||||
(0.9 + 0.1 * cos(_Time.y * _BreathSpeed * 0.6));
|
||||
|
||||
half3 enhancedColor =
|
||||
source.rgb +
|
||||
movingLineColor * lineEnergy +
|
||||
_AccentColor.rgb * (_AccentColor.a * echoEnergy) +
|
||||
_BottomGlowColor.rgb * (_BottomGlowColor.a * bottomGlow);
|
||||
|
||||
fixed4 color;
|
||||
color.rgb = enhancedColor * i.color.rgb;
|
||||
color.a = source.a * i.color.a;
|
||||
|
||||
#ifdef UNITY_UI_CLIP_RECT
|
||||
half2 clipMask = saturate(
|
||||
(_ClipRect.zw - _ClipRect.xy - abs(i.mask.xy)) * i.mask.zw
|
||||
);
|
||||
color.a *= clipMask.x * clipMask.y;
|
||||
#endif
|
||||
|
||||
#ifdef UNITY_UI_ALPHACLIP
|
||||
clip(color.a - 0.001);
|
||||
#endif
|
||||
|
||||
return color;
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
}
|
||||
}
|
||||
9
Assets/Shaders/UI/UI_ContourFlow.shader.meta
Normal file
9
Assets/Shaders/UI/UI_ContourFlow.shader.meta
Normal file
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: caa72d45b56d4aca8bd51d79b8d99135
|
||||
ShaderImporter:
|
||||
externalObjects: {}
|
||||
defaultTextures: []
|
||||
nonModifiableTextures: []
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
63
Assets/Shaders/UI/UI_Expanding Contours.mat
Normal file
63
Assets/Shaders/UI/UI_Expanding Contours.mat
Normal file
@@ -0,0 +1,63 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!21 &2100000
|
||||
Material:
|
||||
serializedVersion: 8
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_Name: UI_Expanding Contours
|
||||
m_Shader: {fileID: 4800000, guid: abcd49c27bc748dc98d692443877ab00, type: 3}
|
||||
m_Parent: {fileID: 0}
|
||||
m_ModifiedSerializedProperties: 0
|
||||
m_ValidKeywords: []
|
||||
m_InvalidKeywords: []
|
||||
m_LightmapFlags: 4
|
||||
m_EnableInstancingVariants: 0
|
||||
m_DoubleSidedGI: 0
|
||||
m_CustomRenderQueue: -1
|
||||
stringTagMap: {}
|
||||
disabledShaderPasses: []
|
||||
m_LockedProperties:
|
||||
m_SavedProperties:
|
||||
serializedVersion: 3
|
||||
m_TexEnvs:
|
||||
- _MainTex:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
m_Ints: []
|
||||
m_Floats:
|
||||
- _CenterMargin: 0
|
||||
- _ColorMask: 15
|
||||
- _ContourSpacing: 0.075
|
||||
- _EdgeSoftness: 0.5
|
||||
- _EmitterCount: 6
|
||||
- _ExpansionCurve: 0.3
|
||||
- _FadeDuration: 0.25
|
||||
- _FusionStrength: 0.1
|
||||
- _Irregularity: 0.45
|
||||
- _LineWidth: 0.0005
|
||||
- _MaxRadius: 0.75
|
||||
- _MorphAmount: 1
|
||||
- _Opacity: 0.1
|
||||
- _RandomSeed: 0
|
||||
- _ShapeDetail: 1
|
||||
- _ShapeVariation: 1
|
||||
- _SpawnRate: 0.05
|
||||
- _Stencil: 0
|
||||
- _StencilComp: 8
|
||||
- _StencilOp: 0
|
||||
- _StencilReadMask: 255
|
||||
- _StencilWriteMask: 255
|
||||
- _TopologyRelease: 1
|
||||
- _TrailFade: 0.5
|
||||
- _TrailLength: 0.5
|
||||
- _UseClipRect: 0
|
||||
- _UseUIAlphaClip: 0
|
||||
m_Colors:
|
||||
- _Color: {r: 1, g: 1, b: 1, a: 1}
|
||||
- _LineColor: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_BuildTextureStacks: []
|
||||
m_AllowLocking: 1
|
||||
8
Assets/Shaders/UI/UI_Expanding Contours.mat.meta
Normal file
8
Assets/Shaders/UI/UI_Expanding Contours.mat.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 983ae72c51d95034eaf1e7800b0115fe
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 2100000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
459
Assets/Shaders/UI/UI_ExpandingContours.shader
Normal file
459
Assets/Shaders/UI/UI_ExpandingContours.shader
Normal file
@@ -0,0 +1,459 @@
|
||||
Shader "Ichni/UI/Expanding Contours"
|
||||
{
|
||||
Properties
|
||||
{
|
||||
[PerRendererData] _MainTex ("Sprite Texture", 2D) = "white" {}
|
||||
_Color ("Graphic Tint", Color) = (1, 1, 1, 1)
|
||||
|
||||
[Header(Line)]
|
||||
_LineColor ("Line Color", Color) = (1, 1, 1, 1)
|
||||
_Opacity ("Opacity", Range(0, 1)) = 0.5
|
||||
_LineWidth ("Line Width", Range(0.0005, 0.02)) = 0.0005
|
||||
_EdgeSoftness ("Edge Softness", Range(0.5, 4)) = 0.5
|
||||
_ContourSpacing ("Contour Spacing", Range(0.01, 0.2)) = 0.1
|
||||
_TrailLength ("Contour Trail Length", Range(0.02, 1.5)) = 0.5
|
||||
_TrailFade ("Inner Line Fade", Range(0, 1)) = 1
|
||||
|
||||
[Header(Emission)]
|
||||
_EmitterCount ("Simultaneous Emitters", Range(1, 6)) = 4
|
||||
_SpawnRate ("Event Cycles Per Second", Range(0.02, 1)) = 0.05
|
||||
_MaxRadius ("Maximum Radius", Range(0.1, 2)) = 0.5
|
||||
_ExpansionCurve ("Expansion Curve", Range(0.3, 3)) = 0.85
|
||||
_FadeDuration ("Lifetime Fade", Range(0.01, 0.45)) = 0.16
|
||||
_CenterMargin ("Random Center Margin", Range(0, 0.45)) = 0
|
||||
_RandomSeed ("Random Seed", Float) = 0
|
||||
|
||||
[Header(Shape)]
|
||||
_Irregularity ("Shape Irregularity", Range(0, 0.45)) = 0.45
|
||||
_ShapeDetail ("Shape Detail", Range(0, 1)) = 1
|
||||
_MorphAmount ("Shape Morph Amount", Range(0, 1)) = 1
|
||||
_ShapeVariation ("Per Shape Variation", Range(0, 1)) = 1
|
||||
_FusionStrength ("Intersection Fusion", Range(0, 0.2)) = 0.04
|
||||
_TopologyRelease ("Topology Release", Range(0, 2)) = 1
|
||||
|
||||
[Header(UI)]
|
||||
_StencilComp ("Stencil Comparison", Float) = 8
|
||||
_Stencil ("Stencil ID", Float) = 0
|
||||
_StencilOp ("Stencil Operation", Float) = 0
|
||||
_StencilWriteMask ("Stencil Write Mask", Float) = 255
|
||||
_StencilReadMask ("Stencil Read Mask", Float) = 255
|
||||
_ColorMask ("Color Mask", Float) = 15
|
||||
[Toggle(UNITY_UI_CLIP_RECT)] _UseClipRect ("Use UI Clip Rect", Float) = 0
|
||||
[Toggle(UNITY_UI_ALPHACLIP)] _UseUIAlphaClip ("Use UI Alpha Clip", Float) = 0
|
||||
}
|
||||
|
||||
SubShader
|
||||
{
|
||||
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]
|
||||
|
||||
Pass
|
||||
{
|
||||
Name "Expanding Contours UI"
|
||||
|
||||
CGPROGRAM
|
||||
#pragma target 3.0
|
||||
#pragma vertex vert
|
||||
#pragma fragment frag
|
||||
#pragma multi_compile_local _ UNITY_UI_CLIP_RECT
|
||||
#pragma multi_compile_local _ UNITY_UI_ALPHACLIP
|
||||
|
||||
#include "UnityCG.cginc"
|
||||
#include "UnityUI.cginc"
|
||||
|
||||
#define MAX_EMITTERS 6
|
||||
struct appdata_t
|
||||
{
|
||||
float4 vertex : POSITION;
|
||||
fixed4 color : COLOR;
|
||||
float2 texcoord : TEXCOORD0;
|
||||
UNITY_VERTEX_INPUT_INSTANCE_ID
|
||||
};
|
||||
|
||||
struct v2f
|
||||
{
|
||||
float4 vertex : SV_POSITION;
|
||||
fixed4 color : COLOR;
|
||||
float2 uv : TEXCOORD0;
|
||||
float4 worldPosition : TEXCOORD1;
|
||||
half4 mask : TEXCOORD2;
|
||||
UNITY_VERTEX_OUTPUT_STEREO
|
||||
};
|
||||
|
||||
fixed4 _Color;
|
||||
fixed4 _LineColor;
|
||||
float _Opacity;
|
||||
float _LineWidth;
|
||||
float _EdgeSoftness;
|
||||
float _ContourSpacing;
|
||||
float _TrailLength;
|
||||
float _TrailFade;
|
||||
|
||||
float _EmitterCount;
|
||||
float _SpawnRate;
|
||||
float _MaxRadius;
|
||||
float _ExpansionCurve;
|
||||
float _FadeDuration;
|
||||
float _CenterMargin;
|
||||
float _RandomSeed;
|
||||
|
||||
float _Irregularity;
|
||||
float _ShapeDetail;
|
||||
float _MorphAmount;
|
||||
float _ShapeVariation;
|
||||
float _FusionStrength;
|
||||
float _TopologyRelease;
|
||||
|
||||
float4 _ClipRect;
|
||||
float _UIMaskSoftnessX;
|
||||
float _UIMaskSoftnessY;
|
||||
|
||||
v2f vert(appdata_t v)
|
||||
{
|
||||
v2f o;
|
||||
UNITY_SETUP_INSTANCE_ID(v);
|
||||
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
|
||||
|
||||
o.worldPosition = v.vertex;
|
||||
o.vertex = UnityObjectToClipPos(o.worldPosition);
|
||||
o.uv = v.texcoord;
|
||||
o.color = v.color * _Color;
|
||||
|
||||
float2 pixelSize = o.vertex.w;
|
||||
pixelSize /= abs(mul((float2x2)UNITY_MATRIX_P, _ScreenParams.xy));
|
||||
|
||||
float4 clampedRect = clamp(_ClipRect, -2e10, 2e10);
|
||||
o.mask = half4(
|
||||
v.vertex.xy * 2 - clampedRect.xy - clampedRect.zw,
|
||||
0.25 / (0.25 * half2(_UIMaskSoftnessX, _UIMaskSoftnessY) + abs(pixelSize.xy))
|
||||
);
|
||||
|
||||
return o;
|
||||
}
|
||||
|
||||
float Hash11(float value)
|
||||
{
|
||||
value = frac(value * 0.1031);
|
||||
value *= value + 33.33;
|
||||
value *= value + value;
|
||||
return frac(value);
|
||||
}
|
||||
|
||||
float2 Hash21(float value)
|
||||
{
|
||||
float3 value3 = frac(
|
||||
float3(value, value, value) *
|
||||
float3(0.1031, 0.1030, 0.0973)
|
||||
);
|
||||
value3 += dot(value3, value3.yzx + 33.33);
|
||||
return frac((value3.xx + value3.yz) * value3.zy);
|
||||
}
|
||||
|
||||
float2 GetRandomDirection(float seed)
|
||||
{
|
||||
float2 direction = Hash21(seed) * 2.0 - 1.0;
|
||||
return direction * rsqrt(max(dot(direction, direction), 0.0001));
|
||||
}
|
||||
|
||||
float2 NormalizeSafe(float2 direction)
|
||||
{
|
||||
return direction * rsqrt(max(dot(direction, direction), 0.0001));
|
||||
}
|
||||
|
||||
float2 ComplexMultiply(float2 a, float2 b)
|
||||
{
|
||||
return float2(
|
||||
a.x * b.x - a.y * b.y,
|
||||
a.y * b.x + a.x * b.y
|
||||
);
|
||||
}
|
||||
|
||||
float GetRectAspect(float2 uv)
|
||||
{
|
||||
float uGradient = max(length(float2(ddx(uv.x), ddy(uv.x))), 0.000001);
|
||||
float vGradient = max(length(float2(ddx(uv.y), ddy(uv.y))), 0.000001);
|
||||
return clamp(vGradient / uGradient, 0.1, 10.0);
|
||||
}
|
||||
|
||||
float GetIrregularDistance(
|
||||
float2 uv,
|
||||
float2 center,
|
||||
float aspect,
|
||||
float eventSeed,
|
||||
float life
|
||||
)
|
||||
{
|
||||
float2 delta = uv - center;
|
||||
delta.x *= aspect;
|
||||
|
||||
float2 shapeAxis = GetRandomDirection(eventSeed + 17.23);
|
||||
float2 perpendicularAxis = float2(-shapeAxis.y, shapeAxis.x);
|
||||
float axisStretch = lerp(
|
||||
1.0,
|
||||
lerp(0.72, 1.28, Hash11(eventSeed + 21.91)),
|
||||
_ShapeVariation
|
||||
);
|
||||
float parallelDistance = dot(delta, shapeAxis) / axisStretch;
|
||||
float perpendicularDistance = dot(delta, perpendicularAxis) * axisStretch;
|
||||
delta =
|
||||
shapeAxis * parallelDistance +
|
||||
perpendicularAxis * perpendicularDistance;
|
||||
|
||||
float radialDistance = max(length(delta), 0.000001);
|
||||
float2 direction = delta / radialDistance;
|
||||
|
||||
// Complex powers provide closed angular harmonics without
|
||||
// texture noise, atan2, or per-pixel trigonometry.
|
||||
float2 harmonic2 = ComplexMultiply(direction, direction);
|
||||
float2 harmonic3 = ComplexMultiply(harmonic2, direction);
|
||||
float2 harmonic5 = ComplexMultiply(harmonic3, harmonic2);
|
||||
float2 harmonic7 = ComplexMultiply(harmonic5, harmonic2);
|
||||
|
||||
float morph = smoothstep(0.0, 1.0, life) * _MorphAmount;
|
||||
float2 phaseA = NormalizeSafe(lerp(
|
||||
GetRandomDirection(eventSeed + 2.31),
|
||||
GetRandomDirection(eventSeed + 102.31),
|
||||
morph
|
||||
));
|
||||
float2 phaseB = NormalizeSafe(lerp(
|
||||
GetRandomDirection(eventSeed + 7.17),
|
||||
GetRandomDirection(eventSeed + 107.17),
|
||||
morph
|
||||
));
|
||||
float2 phaseC = NormalizeSafe(lerp(
|
||||
GetRandomDirection(eventSeed + 13.73),
|
||||
GetRandomDirection(eventSeed + 113.73),
|
||||
morph
|
||||
));
|
||||
|
||||
float broadShape =
|
||||
0.58 * dot(harmonic2, phaseA) +
|
||||
0.29 * dot(harmonic3, phaseB);
|
||||
float fineShape =
|
||||
0.09 * dot(harmonic5, phaseB) +
|
||||
0.04 * dot(harmonic7, phaseC);
|
||||
float detailVariation = lerp(
|
||||
1.0,
|
||||
lerp(0.6, 1.4, Hash11(eventSeed + 29.37)),
|
||||
_ShapeVariation
|
||||
);
|
||||
float irregularityVariation = lerp(
|
||||
1.0,
|
||||
lerp(0.65, 1.35, Hash11(eventSeed + 37.61)),
|
||||
_ShapeVariation
|
||||
);
|
||||
float shape =
|
||||
broadShape +
|
||||
fineShape * _ShapeDetail * detailVariation;
|
||||
return radialDistance *
|
||||
(1.0 + shape * _Irregularity * irregularityVariation);
|
||||
}
|
||||
|
||||
float2 GetEmitterField(float2 uv, float aspect, float emitterIndex, float activeEmitters)
|
||||
{
|
||||
float stagger = emitterIndex / activeEmitters;
|
||||
float timeline = _Time.y * _SpawnRate + stagger;
|
||||
float cycle = floor(timeline);
|
||||
float life = frac(timeline);
|
||||
|
||||
// R2 low-discrepancy ordering keeps both consecutive events and
|
||||
// simultaneously active centers distributed across the UI.
|
||||
float sequenceIndex =
|
||||
cycle * activeEmitters +
|
||||
(activeEmitters - 1.0 - emitterIndex);
|
||||
float eventSeed =
|
||||
sequenceIndex * 17.17 +
|
||||
_RandomSeed * 101.13;
|
||||
|
||||
float2 sequenceOffset = Hash21(_RandomSeed * 43.17 + 0.71);
|
||||
float2 randomCenter = frac(
|
||||
sequenceOffset +
|
||||
sequenceIndex * float2(0.754877666, 0.569840296)
|
||||
);
|
||||
float centerRange = max(1.0 - _CenterMargin * 2.0, 0.001);
|
||||
float2 center = _CenterMargin + randomCenter * centerRange;
|
||||
|
||||
float irregularDistance = GetIrregularDistance(
|
||||
uv,
|
||||
center,
|
||||
aspect,
|
||||
eventSeed,
|
||||
life
|
||||
);
|
||||
|
||||
float radiusVariation = lerp(
|
||||
1.0,
|
||||
lerp(0.85, 1.15, Hash11(eventSeed + 41.93)),
|
||||
_ShapeVariation
|
||||
);
|
||||
float expansion = pow(saturate(life), _ExpansionCurve);
|
||||
float currentRadius = _MaxRadius * radiusVariation * expansion;
|
||||
|
||||
float fadeDuration = max(_FadeDuration, 0.01);
|
||||
half fadeIn = smoothstep(0.0, fadeDuration, life);
|
||||
half fadeOut = 1.0 - smoothstep(1.0 - fadeDuration, 1.0, life);
|
||||
half lifeFade = fadeIn * fadeOut;
|
||||
|
||||
// Alpha fading alone leaves the full SDF in the smooth union
|
||||
// until the emitter is removed, which makes connected contours
|
||||
// snap closed. Erode the field continuously during fade-out so
|
||||
// its topology is already released before the final removal.
|
||||
float retirement = 1.0 - fadeOut;
|
||||
float releaseDistance =
|
||||
currentRadius +
|
||||
_TrailLength +
|
||||
_ContourSpacing +
|
||||
_FusionStrength;
|
||||
float releaseOffset =
|
||||
retirement *
|
||||
retirement *
|
||||
releaseDistance *
|
||||
_TopologyRelease;
|
||||
float releasedDistance =
|
||||
irregularDistance -
|
||||
currentRadius +
|
||||
releaseOffset;
|
||||
|
||||
return float2(releasedDistance, lifeFade);
|
||||
}
|
||||
|
||||
fixed4 frag(v2f i) : SV_Target
|
||||
{
|
||||
float aspect = GetRectAspect(i.uv);
|
||||
float activeEmitters = clamp(floor(_EmitterCount + 0.5), 1.0, MAX_EMITTERS);
|
||||
float unionDistance = 100000.0;
|
||||
half unionFade = 0;
|
||||
half hasEmitter = 0;
|
||||
|
||||
[unroll]
|
||||
for (int emitter = 0; emitter < MAX_EMITTERS; emitter++)
|
||||
{
|
||||
UNITY_BRANCH
|
||||
if ((float)emitter < activeEmitters)
|
||||
{
|
||||
float2 emitterField = GetEmitterField(
|
||||
i.uv,
|
||||
aspect,
|
||||
(float)emitter,
|
||||
activeEmitters
|
||||
);
|
||||
|
||||
UNITY_BRANCH
|
||||
if (emitterField.y > 0.001)
|
||||
{
|
||||
if (hasEmitter < 0.5)
|
||||
{
|
||||
unionDistance = emitterField.x;
|
||||
unionFade = emitterField.y;
|
||||
hasEmitter = 1;
|
||||
}
|
||||
else if (_FusionStrength > 0.00001)
|
||||
{
|
||||
float blend = saturate(
|
||||
0.5 +
|
||||
0.5 * (emitterField.x - unionDistance) /
|
||||
_FusionStrength
|
||||
);
|
||||
unionDistance =
|
||||
lerp(emitterField.x, unionDistance, blend) -
|
||||
_FusionStrength * blend * (1.0 - blend);
|
||||
unionFade = lerp(emitterField.y, unionFade, blend);
|
||||
}
|
||||
else if (emitterField.x < unionDistance)
|
||||
{
|
||||
unionDistance = emitterField.x;
|
||||
unionFade = emitterField.y;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
float contourDepth = -unionDistance;
|
||||
float spacing = max(_ContourSpacing, 0.0001);
|
||||
float ringCoordinate = contourDepth / spacing;
|
||||
float ringDistance =
|
||||
abs(frac(ringCoordinate + 0.5) - 0.5) *
|
||||
spacing;
|
||||
float antialiasing = max(
|
||||
fwidth(unionDistance) * _EdgeSoftness,
|
||||
0.00001
|
||||
);
|
||||
half lineAlpha = 1.0 - smoothstep(
|
||||
_LineWidth,
|
||||
_LineWidth + antialiasing,
|
||||
ringDistance
|
||||
);
|
||||
|
||||
half outerMask = smoothstep(
|
||||
-antialiasing,
|
||||
antialiasing,
|
||||
contourDepth
|
||||
);
|
||||
half innerMask = 1.0 - smoothstep(
|
||||
_TrailLength - antialiasing,
|
||||
_TrailLength + antialiasing,
|
||||
contourDepth
|
||||
);
|
||||
half trailPosition = 1.0 - saturate(
|
||||
contourDepth / max(_TrailLength, 0.0001)
|
||||
);
|
||||
half trailOpacity = lerp(
|
||||
1.0 - _TrailFade,
|
||||
1.0,
|
||||
trailPosition
|
||||
);
|
||||
half contourAlpha =
|
||||
lineAlpha *
|
||||
outerMask *
|
||||
innerMask *
|
||||
trailOpacity *
|
||||
unionFade *
|
||||
hasEmitter;
|
||||
|
||||
fixed4 color;
|
||||
color.rgb = _LineColor.rgb * i.color.rgb;
|
||||
color.a =
|
||||
saturate(contourAlpha) *
|
||||
_LineColor.a *
|
||||
_Opacity *
|
||||
i.color.a;
|
||||
|
||||
#ifdef UNITY_UI_CLIP_RECT
|
||||
half2 clipMask = saturate(
|
||||
(_ClipRect.zw - _ClipRect.xy - abs(i.mask.xy)) * i.mask.zw
|
||||
);
|
||||
color.a *= clipMask.x * clipMask.y;
|
||||
#endif
|
||||
|
||||
#ifdef UNITY_UI_ALPHACLIP
|
||||
clip(color.a - 0.001);
|
||||
#endif
|
||||
|
||||
return color;
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
}
|
||||
}
|
||||
9
Assets/Shaders/UI/UI_ExpandingContours.shader.meta
Normal file
9
Assets/Shaders/UI/UI_ExpandingContours.shader.meta
Normal file
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: abcd49c27bc748dc98d692443877ab00
|
||||
ShaderImporter:
|
||||
externalObjects: {}
|
||||
defaultTextures: []
|
||||
nonModifiableTextures: []
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user