-->



Shader "UI/RadialLine"
{
Properties
{
[HideInInspector] _MainTex("-",2D)="white"{}
[KeywordEnum(Rough, Sharp)] _Line("Line", Int) = 0
_Color("Color", Color) = (0,0,0,1)
[Space(10)]
_NoiseScale("NoiseScale", Range(100, 1000)) = 500
_PatternSeed("PatternSeed", Range(10, 100)) = 1
[Space(10)]
_Edge1("Edge1", Range(0, 1)) = 0.5
_Edge2("Edge2", Range(0, 1)) = 1
[Space(10)]
[Toggle] _IsAutoAnim("IsAutoAnim", float) = 0
_AutoAnimSpeed("AutoAnimSpeed", Range(1, 20)) = 10
}
SubShader
{
Tags
{
"RenderPipeline" = "UniversalPipeline"
"Queue" = "Transparent"
}
Cull Off
ZWrite Off
Blend SrcAlpha OneMinusSrcAlpha
Pass
{
HLSLPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile _LINE_ROUGH _LINE_SHARP
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
struct Attributes
{
float4 positionOS : POSITION;
half2 uv : TEXCOORD0;
};
struct Varyings
{
float4 positionCS : POSITION;
half2 uv : TEXCOORD0;
};
sampler2D _MainTex;
//SRP Batcherを適用、動的に変更される数値はこの中に定義
CBUFFER_START(UnityPerMaterial)
half4 _Color;
half _NoiseScale;
half _PatternSeed;
half _Edge1;
half _Edge2;
half _IsAutoAnim;
half _AutoAnimSpeed;
CBUFFER_END
//radianの最大値、degreeで言うと360度のこと
static const float PI2 = 3.14159 * 2;
Varyings vert(Attributes input)
{
Varyings output;
output.positionCS = TransformObjectToHClip(input.positionOS.xyz);
output.uv = input.uv;
return output;
}
//あらゆる範囲の2次元変数を0~1の範囲の1次元変数に変換する
half random(half2 uv)
{
return frac(sin(dot(uv, float2(12.9898, 78.233)))*43758.5453);
}
//引数に渡された対象座標の角度を0~1の範囲に圧縮して返す。
//反時計周りに徐々に値が大きくなる。
half2 getUvAngle(half2 uv)
{
//uv座標を、画面中央を原点として(0,0)>(1,1)から(-1,-1)>(1,1)の範囲に修正する
half2 fixUv = uv * 2 - 1;
//修正したuv座標の角度をradian値で取得
half angle = atan2(fixUv.y, fixUv.x);
//0~PI*2の値を0~1の範囲に圧縮
return angle / PI2;
}
//半時計周りにグラデーションする0~1の値を、バラバラの、かつある程度はまとまった集中線に変換する
half getRadialLine(half angle)
{
//_NoiseScaleを大きくするほど、集中線が細かくなる。
//これは_NoiseScaleで値を大きくすると、floorで切り捨てられる要素が少なくなり
//angleの細かい値まで漏れなく後のrandom関数に反映されるため。
//random関数は、どんな巨大な値も0~1の範囲に収めるため、与える値の大きさは問題ではなく
//どこからどこまでのangle値を同値として扱うかが重要になる
half2 lineSeed = floor(half2(angle, angle) * _NoiseScale);
half lineVal = random(lineSeed); ;
//sin関数はあらゆる値を規則的な-1~1の範囲の波形に変換する。
//ここでは集中線の出現パターンを変える効果に使っている。
//_IsAutoAnimがtrueの時は、Unity再生時に自動でアニメーションを実行し、
//_IsAutoAnimがfalseの時は、_PatternSeedを操作することで集中線の見た目が変化する
lineVal = (_IsAutoAnim * sin(lineVal * _Time.w * _AutoAnimSpeed)) +
((1 - _IsAutoAnim) * sin(lineVal * _PatternSeed));
return lineVal;
}
//引数のuv座標を参照し、中心から外側に向けて0から1に遷移していく値を返す
half getCenterCircle(half2 uv)
{
//uv座標を、画面中央を原点として(0,0)>(1,1)から(-1,-1)>(1,1)の範囲に修正する
half2 fixUv = uv * 2 - 1;
#ifdef _LINE_ROUGH
//ランダム関数を使ってちょっと線をザラザラにする
half2 i = random(uv) * 0.5 + 0.7;
return length(fixUv) * i;
#else
return length(fixUv);
#endif
}
half4 frag (Varyings input) : SV_Target
{
half4 col = tex2D(_MainTex, input.uv);
//以下の処理は全てalpha値を算出するための処理
half angle = getUvAngle(input.uv);
half lineVal = getRadialLine(angle);
half circle = getCenterCircle(input.uv);
//中心まで届く集中線と、中心に近いほど0に近づく円を掛け算して、
//中心付近は空になる集中線を作る
half resultLine = saturate(lineVal * circle);
//smoothstepで濃い所はより濃く、薄い所はより薄くする
half smoothAlpha = smoothstep(_Edge1, _Edge2, resultLine);
col = _Color;
col.a = smoothAlpha;
return col;
}
ENDHLSL
}
}
}






//あらゆる範囲の2次元変数を0~1の範囲の1次元変数に変換する
fixed random(fixed2 uv)
{
return frac(sin(dot(uv, float2(12.9898, 78.233)))*43758.5453);
}
fixed2 lineSeed = floor(fixed2(angle, angle) * _NoiseScale);
fixed lineVal = random(lineSeed); ;
