// const
// 定数

// UNITY_PI
// UnityCG.cgincで定義されているUNITY_PIを利用できる。UNITY_TWO_PIというものもある。
// static float UNITY_PI = 3.141592653589793238;
// static float HALF_PI = 1.57079632679;
// static float HALF_PI = UNITY_PI / 2;
// static float TWO_PI = 6.28318530718;
// static float TWO_PI = 2 * UNITY_PI; // これはUNITY_TWO_PIが使える
// 0.01745329251 // pi / 180

// Golden Ratio
static float PHI = 1.618033988749894848;

static float GOLDEN = UNITY_PI * (3.0-sqrt(5.0));

// 0.4545.. // 1/2.2, RECIPROCAL_GAMMA, 輝度=電圧出力率^1/2.2
static float GAMMA_CORRECTION = 0.45454545;

// bit smaller than 1.0
float cos0067() { return cos(0.067); } // 0.997756339504

// bit larger than 0.0
float cos1569() { return cos(1.569); } // 0.00179632582884


// matrices
// 行列

// 2D rotation matrix
// to use mul(rot2DM(_Time.y), p)
float2x2 rot2DM(float angle)
{
	float c = cos(angle);
	float s = sin(angle);
	return float2x2(c, s, -s, c);
}

// scale matrix
float2x2 scale2DM(float2 scale){
    return float2x2(scale.x, 0, 0, scale.y);
}

// YUV to RGB matrix
float3x3 YUV2RGBM = float3x3(1.0, 0.0, 1.13983,
 1.0, -0.39465, -0.58060,
 1.0, 2.03211, 0.0);

// RGB to YUV matrix
float3x3 RGB2YUVM = float3x3(0.2126, 0.7152, 0.0722,
 -0.09991, -0.33609, 0.43600,
 0.615, -0.5586, -0.05639);


// basic func
// 関数
// to include perlin noise and snoise, https://github.com/keijiro/NoiseShader/blob/master/Assets/HLSL/ClassicNoise2D.hlsl
// https://github.com/keijiro/NoiseShader/blob/master/Assets/HLSL/ClassicNoise3D.hlsl
// also see [Noise]
// GLSL Noise Algorithms
// https://gist.github.com/patriciogonzalezvivo/670c22f3966e662d2f83

// note: HLSL has no mod() function, so prepare handmade.
// fmod works same as %. under zero, fmod differs from mod.

float mod(float x, float y)
{
	return x - y * floor(x / y);
}

float2 mod(float2 x, float2 y)
{
	return x - y * floor(x / y);
}

float3 mod(float3 x, float3 y)
{
	return x - y * floor(x / y);
}

float4 mod(float4 x, float4 y)
{
	return x - y * floor(x / y);
}

// 1D random numbers
float Rand(float n)
{
	return frac(sin(n));
}

// 2D random numbers
float2 Rand2(float2 p)
{
	return frac(float2(sin(p.x * 1.32 + p.y * 54.077), cos(p.x * 91.32 + p.y * 9.077)));
}

// 1D noise
float Noise1(float p)
{
	float fl = floor(p);
	float fc = frac(p);
	return lerp(Rand(fl), Rand(fl + 1.0), fc);
}

// 2D noise
float Noise2(float2 p) {
	return frac(sin(dot(p.xy, float2(12.9898, 78.233))) * 43758.5453);
}

// Taylor approximation of inverse square root
// https://math.stackexchange.com/questions/2585826/taylor-approximation-of-inverse-square-root
float4 taylorInvSqrt(float4 r)
{
	return 1.79284291400159 - 0.85373472095314 * r;
}

// Hash
float hash1(float n)
{
	return frac(sin(n)*43758.5453123);
}

float3 hash3(float n)
{
	return frac(sin(n + float3(0.0, 13.1, 31.3))*158.5453123);
}

// mod 289
float3 mod289(float3 x) {
	return x - floor(x * (1 / 289)) * 289;
}

float4 mod289(float4 x) {
	return x - floor(x * (1 / 289)) * 289;
}

// smooth min

// exponential smooth, k=32
float sminEx(float a, float b, float k)
{
	float res = exp2(-k * a) + exp2(-k * b);
	return -log2(res) / k;
}

// polynomial smooth, k=0.1
float sminPoly(float a, float b, float k)
{
	float h = clamp(0.5 + 0.5 * (b - a) / k, 0.0, 1.0);
	return lerp(b, a, h) - k * h * (1.0 - h);
}

// power smooth, k=8
float sminPow(float a, float b, float k)
{
	a = pow(a, k);
	b = pow(b, k);
	return pow((a * b) / (a + b), 1.0 / k);
}

// 2D cross product
// note: HLSL cross is 3D method
// https://docs.microsoft.com/en-us/windows/desktop/direct3dhlsl/dx-graphics-hlsl-cross
float cross2(float2 v1, float2 v2) {
    return v1.x * v2.y - v1.y * v2.x;
}

// 3D pow
// wrong?? pow(float3, float) works.
// note: HLSL pow is 1D method
// https://docs.microsoft.com/en-us/windows/desktop/direct3dhlsl/dx-graphics-hlsl-pow
float3 pow3(float3 i, float p)
{
	return float3(pow(i.x, p), pow(i.y, p), pow(i.z, p));
}

// maxcomp
float maxcomp(float2 v)
{
	return max(v.x, v.y);
}
float maxcomp(float3 v)
{
	return max(max(v.x, v.y), v.z);
}


// transform
// 移動・回転・拡大縮小

// Translate
float2 translate()
{
	return float2(cos(_Time.y), sin(_Time.y));
}

// Rotate
float2 rot(float2 p, float a)
{	
	return float2(p.x * cos(a) - p.y * sin(a), p.x * sin(a) + p.y * cos(a));
}

float3 rotate(float3 p, float3 v, float a) 
{
	float4 q = float4(sin(a / 2.) * v, cos(a / 2.)); // quaternion
	return cross(cross(p, q.xyz) - q.w * p, q.xyz) * 2. + p;
}

// Zoom
float2 zoom(float2 p, float2 z)
{
	return float2(p * z); // float2(p.x*z.x, p.y*z.y) or mul(float2x2(z.x,0,0,z.y), p)
}


// time after time
// 時間

// time multiplier
float sinTimer()
{
	return sin(_Time.y);
}

// 0 to 1 sine curve
// sin(x) * 0.5 + 0.5;
float sinHalfTimer()
{
	return sin(_Time.y) * 0.5 + 0.5;
}


// draw simple colours
// 色

// Gray
fixed4 Gray(float c) {
	return fixed4(c.xxx, 1);
}

// Red
fixed4 Red(float c) {
	return fixed4(c, 0, 0, 1);
}

// alters RGB
fixed4 Colorful(float c) {
	return fixed4(c * sinTimer(), -c * sinTimer(), c * sinTimer(), 1);
}


// figures
// 形

// draw round
// to call
// float _Rad;
// float c = Round2(i.uv, _Rad);
// return Gray(c);
float Round2(float2 p, float rad)
{
	float2 st = p - 0.5;
	return step(distance(st, 0), rad);
}

// to call
// return Gray(HaloRing((2*i.uv-1), 0.8 , 3.));
float HaloRing(float2 p, float r, float s)
{
	return 1.2-(length(1.-length(abs(p*s))))-r;
}

float dSphere(float3 p, float s)
{
	return length(p) - s;
}


// draw line
// to call
// float c = step(Liner2(i.uv, a, b, 0.01), 0.0001);
// return Gray(c);
float Liner2(float2 p, float2 a, float2 b, float r)
{
	float2 pa = p - a;
	float2 ba = b - a;
	float h = clamp(dot(pa, ba) / dot(ba, ba), 0., 1.);
	return length(pa - ba * h ) - r;
}

// Rectangle
// to call
// return Gray(dRectangle(i.uv, 0.3), 1);
float dRectangle(float2 p, float size) {
	float2 st = p - 0.5;
	return step(max(abs(st.x), abs(st.y)), size);
}

// Box
float dBox(float2 p, float2 b) {
	return max(abs(p.x) - b.x, abs(p.y) - b.y);
}

// Torus
float dTorus(float3 p, float2 t)
{
	return length(float2(length(p.xz) - t.x, p.y)) - t.y;
}

// Ellipsoid
// to call
// return scgColorful2(Ellipsoid((i.uv), float2(0.4, 0.6), float2(0.2, 0.1)));
float Ellipsoid(float2 p, float2 c, float2 r)
{
	return (length((p - c) / r) - 1.0) * min(r.x, r.y);
}

// Ellipsoid(3D)
// to call
// return Colorful2(Ellipsoid3(float3(i.uv, abs(sin(_Time.z))), float3(0.4, 0.6, 0.3), float3(0.2, 0.1, 0.1)));
float Ellipsoid3(float3 p, float3 c, float3 r)
{
	return (length((p - c) / r) - 1.0) * min(min(r.x, r.y), r.z);
}

// Triangle
// to call
// return float4(Triangle(i.uv).xxx, 1);
float Triangle(float2 p){

	float2 st = p - 1.;
	st = rot(st, UNITY_PI / 6.);

	// Number of sides of your shape
	int N = 3;

	// Angle and radius from the current pixel
	float a = atan2(st.y, st.x) + UNITY_PI;
	float r = 2. * UNITY_PI / float(N);

	// Shaping function that modulate the distance
	float d = cos(floor(0.5 + a / r) * r - a) * length(st);
	return 1.0 - smoothstep(0.4, 0.41, d);
}

// Rotating Triangle
// to call
// return Colorful3(RotateTriangle(2 * (i.uv)));
float RotateTriangle(float2 p){

	float2 st = p - 1;
	st = rot(st, UNITY_PI / 6 + sin(_Time.y));

	// Number of sides of your shape
	int N = 3;

	// Angle and radius from the current pixel
	float a = atan2(st.y, st.x) + UNITY_PI;
	float r = 2 * UNITY_PI / float(N);

	// Shaping function that modulate the distance
	float d = cos(floor(0.5 + a / r) * r - a) * length(st);
	return 1.0 - smoothstep(0.4, 0.41, d);
}

float dPolygon(float2 p, int vs) {
	float r = UNITY_TWO_PI / float(vs);
	float2 st = p - 0.5;
	float a = atan2(st.x, st.y) + UNITY_PI;
	return cos(floor(0.5+a/r)*r-a)*length(st);
}