Files
Bombaleila/Assets/ThunderWire Studio/UHFPS/Content/Shaders/Heartbeat/UIHeartbeat.shader
2026-03-03 05:27:03 +05:00

261 lines
9.8 KiB
GLSL

// Unity built-in shader source. Copyright (c) 2016 Unity Technologies. MIT license (see license.txt)
// Modified version of: https://www.shadertoy.com/view/4dfBWn
Shader "UHFPS/UIHeartbeat"
{
Properties
{
[PerRendererData] _MainTex("Sprite Texture", 2D) = "white" {}
_LineColor("Line Color", Color) = (0.0, 1.0, 0.7, 1.5)
_DefaultPulse("Default Pulse", Float) = 0.4
_PulseMultiplier("Pulse Multiplier", Float) = 1
_PulseFade("Pulse Fade", Float) = 0.25
_PulseWidth("Pulse Width", Float) = 1
_PulseRate("Pulse Rate", Float) = 1.3
_LineThickness("Line Thickness", Float) = 10
_GridThickness("Grid Thickness", Float) = 0.01
[Toggle(USE_BACKGROUND)] _UseBackground("Use Background", Float) = 0
_Color("Background Color", Color) = (1,1,1,1)
[Toggle(USE_GRID)] _UseGrid("Use Grid", Float) = 0
_GridColor("Grid Color", Color) = (1.0, 0.0, 0.0, 1.0)
_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
_GraphResolution("Graph Resolution", Float) = 512
_ColorMask("Color Mask", Float) = 15
_GridOffset("Grid Offset", Vector) = (0,0,0,0)
_GridTiling("Grid Tiling", Vector) = (1,1,0,0)
_GraphOffset("Graph Offset", Vector) = (0,0,0,0)
_GraphTiling("Graph Tiling", Vector) = (1,1,1,1)
[Toggle(UNITY_UI_ALPHACLIP)] _UseUIAlphaClip("Use 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 "Default"
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma target 2.0
#include "UnityCG.cginc"
#include "UnityUI.cginc"
#pragma multi_compile_local _ UNITY_UI_CLIP_RECT
#pragma multi_compile_local _ UNITY_UI_ALPHACLIP
#pragma shader_feature ZERO_PULSE
#pragma shader_feature USE_BACKGROUND
#pragma shader_feature USE_GRID
#define AA_FALLOFF 1.2 // AA falloff in pixels, must be > 0, affects all drawing
#define FUNC_SAMPLE_STEP 0.05 // function sample step size in pixels
#define SCOPE_RATE 0.5 // default oscilloscope refresh rate
struct appdata_t
{
float4 vertex : POSITION;
float4 color : COLOR;
float2 texcoord : TEXCOORD0;
UNITY_VERTEX_INPUT_INSTANCE_ID
};
struct v2f
{
float4 vertex : SV_POSITION;
fixed4 color : COLOR;
float2 texcoord : TEXCOORD0;
float4 worldPosition : TEXCOORD1;
UNITY_VERTEX_OUTPUT_STEREO
};
sampler2D _MainTex;
fixed4 _Color;
fixed4 _LineColor;
fixed4 _GridColor;
float _DefaultPulse;
float _PulseMultiplier;
float _PulseFade;
float _PulseWidth;
float _PulseRate;
float _LineThickness;
float _GridThickness;
fixed4 _TextureSampleAdd;
float4 _ClipRect;
float4 _MainTex_ST;
float _GraphResolution;
float4 _GridOffset;
float4 _GridTiling;
float4 _GraphOffset;
float4 _GraphTiling;
float pp;
v2f vert(appdata_t v)
{
v2f OUT;
UNITY_SETUP_INSTANCE_ID(v);
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(OUT);
OUT.worldPosition = v.vertex;
OUT.vertex = UnityObjectToClipPos(OUT.worldPosition);
OUT.texcoord = TRANSFORM_TEX(v.texcoord, _MainTex);
OUT.texcoord = OUT.texcoord;
#ifdef USE_BACKGROUND
OUT.color = v.color * _Color;
#else
_Color.a = 0;
OUT.color = v.color * _Color;
#endif
return OUT;
}
float sinc(float x)
{
return (x == 0.0) ? 1.0 : sin(x) / x;
}
float triIsolate(float x)
{
return abs(-1.0 + frac(clamp(x, -0.5, 0.5)) * 2.0);
}
float aaStep(float a, float b, float x)
{
x = clamp(x, a, b);
return (x - a) / (b - a);
}
// heartbeat wave function
float heartbeat(float x)
{
float prebeat = -sinc((x - 0.4) * 40.0) * 0.6 * triIsolate((x - 0.4) * 1.0);
float mainbeat = (sinc((x - 0.5) * 60.0)) * 1.2 * triIsolate((x - 0.5) * 0.7);
float postbeat = sinc((x - 0.5) * 15.0) * 0.5 * triIsolate((x - 0.85) * 0.6);
return (prebeat + mainbeat + postbeat) * triIsolate((x - 0.625) * 0.8); // width 1.25
}
float drawCircle(float2 uv, float2 center, float radius) {
float r = length(uv-center);
float c = 1.0 - aaStep(0.0, radius + pp * AA_FALLOFF, r);
return c * c;
}
float func(float x)
{
#ifdef ZERO_PULSE
return 0;
#else
return 0.5 * heartbeat(fmod((x * _PulseWidth), _PulseRate));
#endif
}
float drawGrid(float2 uv, float stepSize) {
float hlw = _GridThickness * pp * 0.5;
float mul = 1.0 / stepSize;
float2 gf = abs(float2(-0.5,-0.5) + frac((uv + float2(stepSize, stepSize) * 0.5) * mul));
return 1.0 - aaStep(hlw * mul, (hlw + pp * AA_FALLOFF) * mul, min(gf.x, gf.y));
}
float drawFunc(float2 uv) {
float hlw = _LineThickness * pp * 0.5;
float left = uv.x - hlw - pp * AA_FALLOFF;
float right = uv.x + hlw + pp * AA_FALLOFF;
float closest = 100000.0;
for (float x = left; x <= right; x += pp * FUNC_SAMPLE_STEP) {
float2 diff = float2(x, func(x)) - uv;
float dSqr = dot(diff, diff);
closest = min(dSqr, closest);
}
float c = 1.0 - aaStep(0.0, hlw + pp * AA_FALLOFF, sqrt(closest));
return c * c * c;
}
fixed4 frag(v2f IN) : SV_Target
{
half4 color = (tex2D(_MainTex, IN.texcoord) + _TextureSampleAdd) * IN.color;
float graphRange = 0.4 + pow(1.2, _GraphOffset.z * _GraphOffset.z * _GraphOffset.z);
pp = graphRange / _GraphResolution;
// grid
#ifdef USE_GRID
float gridValue = drawGrid((IN.texcoord * _GridTiling) + _GridOffset, 0.1);
color = lerp(color, _GridColor, gridValue);
color.a = 1;
#endif
float rate = SCOPE_RATE * _DefaultPulse * _PulseMultiplier;
float pulse = frac(_Time.y * rate) * _GraphTiling.x;
float2 lineXY = _GraphOffset + IN.texcoord * _GraphTiling;
float fade = pulse - lineXY.x;
if (fade < 0.0) fade += _GraphTiling.x;
fade *= max(0.1, _PulseFade);
fade = clamp(fade / rate * max(1, _DefaultPulse * _PulseMultiplier), 0.0, 1.0);
fade = 1.0 - fade;
fade = fade * fade * fade;
fade *= step(0, lineXY.x) * step(lineXY.x, _GraphTiling.x);
float graphValue = drawFunc(lineXY);
color = lerp(color, _LineColor, graphValue * fade);
float circleValue = drawCircle(lineXY, float2(pulse, func(pulse)), _LineThickness * pp);
color = lerp(color, _LineColor, circleValue);
#ifdef UNITY_UI_CLIP_RECT
color.a *= UnityGet2DClipping(IN.worldPosition.xy, _ClipRect);
#endif
#ifdef UNITY_UI_ALPHACLIP
clip(color.a - 0.001);
#endif
return color;
}
ENDCG
}
}
}