-->


Shader "UI/Barrel"
{
Properties
{
[HideInInspector]_MainTex("-",2D)="white"{}
[KeywordEnum(All, Vertical, Horizontal)] _Direction("Direction", Int) = 0
_DistortionRange ("DistortionRange", Range(0.0, 10.0)) = 10
_EasePow ("EasePow", Range(0, 10)) = 9
}
SubShader
{
Tags
{
"Queue" = "Transparent"
"RenderType"="Transparent"
}
Cull Off
ZWrite Off
Blend SrcAlpha OneMinusSrcAlpha
GrabPass{}
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
sampler2D _GrabTexture;
#pragma multi_compile _DIRECTION_ALL _DIRECTION_VERTICAL _DIRECTION_HORIZONTAL
fixed _DistortionRange;
fixed _EasePow;
struct appdata
{
fixed4 vertex : POSITION;
fixed4 uv : TEXCOORD0;
};
struct v2f
{
fixed4 vertex : SV_POSITION;
fixed2 uv : TEXCOORD0;
};
v2f vert(appdata i)
{
v2f o;
o.vertex = UnityObjectToClipPos(i.vertex);
o.uv = ComputeGrabScreenPos(o.vertex);
return o;
}
fixed2 getIsUnderHalf(v2f i)
{
//x軸が0.5より小さければ1を代入
fixed isUnderHalfX = step(i.uv.x, 0.5);
//y軸が0.5より小さければ1を代入
fixed isUnderHalfY = step(i.uv.y, 0.5);
return fixed2(isUnderHalfX, isUnderHalfY);
}
fixed2 getFarFromSafe(v2f i)
{
fixed fixRange = _DistortionRange * 0.1;
fixed safeRange = 1 - fixRange;
fixed farFromSafeX = abs(0.5 - i.uv.x) - (safeRange / 2);
fixed farFromSafeY = abs(0.5 - i.uv.y) - (safeRange / 2);
return fixed2(farFromSafeX, farFromSafeY);
}
fixed2 getFarFromCenter(v2f i)
{
fixed farFromCenterX = abs(0.5 - i.uv.x);
fixed farFromCenterY = abs(0.5 - i.uv.y);
return fixed2(farFromCenterX, farFromCenterY);
}
fixed getFixEase()
{
fixed easePowMax = 10;
return (easePowMax + 0.5) - _EasePow;
}
fixed2 getMainDist(fixed2 farFromSafe)
{
//InQuadのEaseでfarFromSafeが大きい程指数関数的に座標がずれるようにする
fixed quadX = farFromSafe.x * (farFromSafe.x - 2);
fixed quadY = farFromSafe.y * (farFromSafe.y - 2);
//指数関数の伸びが強すぎるのでfixEaseで抑える
//_EasePowのrangeが0~10なのでfixEaseの振れ幅は10.1~0.1
fixed fixEase = getFixEase();
fixed mainDistX = pow(quadX * quadX, 2) / fixEase;
fixed mainDistY = pow(quadY * quadY, 2) / fixEase;
return fixed2(mainDistX, mainDistY);
}
fixed2 getSubDist(fixed2 farFromCenter, fixed2 mainDist)
{
fixed subDistX = farFromCenter.x * mainDist.y;
fixed subDistY = farFromCenter.y * mainDist.x;
return fixed2(subDistX, subDistY);
}
fixed2 getMainReduce(fixed2 isUnderHalf, fixed2 mainDist)
{
fixed mainReduceX = (isUnderHalf.x * -1 * mainDist.x) + ((1 - isUnderHalf.x) * (mainDist.x));
fixed mainReduceY = (isUnderHalf.y * -1 * mainDist.y) + ((1 - isUnderHalf.y) * (mainDist.y));
return fixed2(mainReduceX, mainReduceY);
}
fixed2 getSubReduce(fixed2 isUnderHalf, fixed2 subDist)
{
fixed subReduceX = (isUnderHalf.x * -1 * subDist.x) + ((1 - isUnderHalf.x) * (subDist.x));
fixed subReduceY = (isUnderHalf.y * -1 * subDist.y) + ((1 - isUnderHalf.y) * (subDist.y));
return fixed2(subReduceX, subReduceY);
}
fixed2 getUseDist(fixed2 farFromSafe)
{
//x軸が歪み対象エリア内かどうか
fixed useDistX = step(0, farFromSafe.x);
//y軸が歪み対象エリア内かどうか
fixed useDistY = step(0, farFromSafe.y);
return fixed2(useDistX, useDistY);
}
fixed4 frag(v2f i) : SV_Target
{
//対象のy軸とx軸座標が中心点を超えてるかどうかを習得
fixed2 isUnderHalf = getIsUnderHalf(i);
//非歪みエリアから外側にx軸、y軸がどれだけ離れてるかを取得
fixed2 farFromSafe = getFarFromSafe(i);
//中心からx軸、y軸がどれだけ離れてるかを取得
fixed2 farFromCenter = getFarFromCenter(i);
//メインの歪みの基本値を取得
fixed2 mainDist = getMainDist(farFromSafe);
//サブの歪みの基本値を取得
fixed2 subDist = getSubDist(farFromCenter, mainDist);
//メインの座標の減退値を取得
fixed2 mainReduce = getMainReduce(isUnderHalf, mainDist);
//サブの座標の減退値を取得
fixed2 subReduce = getSubReduce(isUnderHalf, subDist);
//対象のx軸、y軸が歪み対象エリア内かどうか
fixed2 useDist = getUseDist(farFromSafe);
#ifdef _DIRECTION_ALL
i.uv.x = i.uv.x + useDist.x * mainReduce.x + useDist.y * subReduce.x;
i.uv.y = i.uv.y + useDist.y * mainReduce.y + useDist.x * subReduce.y;
#elif _DIRECTION_VERTICAL
i.uv.x = i.uv.x + useDist.y * subReduce.x * 2;
i.uv.y = i.uv.y + useDist.y * mainReduce.y;
#else
i.uv.x = i.uv.x + useDist.x * mainReduce.x;
i.uv.y = i.uv.y + useDist.x * subReduce.y * 2;
#endif
fixed fixEase = getFixEase();
fixed isUnderOne = step(fixEase, 1);
fixed magni = 1 + (1 / fixEase);
fixed shift = (1 - 1 / magni) / 2;
fixed4 col = tex2D(_GrabTexture, i.uv * (1 / magni) + shift);
return col;
}
ENDCG
}
}
}