261 lines
9.8 KiB
GLSL
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
|
|
}
|
|
}
|
|
} |