[Unity] ShaderTutorial2D


# 対象
Shaderやってみたいけど,どう勉強すればよいか分からない人

# 導入
とりあえず動かしてみる

1. Create -> Shader -> ImageEffectShader選択
2. ダブルクリックで開き，一行目を`Shader "ShaderTutorial/Tutorial1"`にする．
3. Materialを作成し，ShaderをShaderTutorial -> Tutorial1にする．
4. C#スクリプトを作成，後述するスクリプトを記入
5. スクリプトをMainCameraにアタッチ
6. Materialがない!ってエラーが出るので，materialをアタッチ
7. 終了

手順2
![Create.png](https://qiita-image-store.s3.amazonaws.com/0/113504/518d9c9e-477d-3fe3-ad2a-cc8ddcca404c.png "Create.png")

手順3
![MaterialShader.png](https://qiita-image-store.s3.amazonaws.com/0/113504/493f2d71-ca5d-efbf-b5f4-0bcb391337e9.png "MaterialShader.png")

手順4

```Tutorial1.cs
using UnityEngine;
using System.Collections;

[ExecuteInEditMode]
public class Tutorial1 : MonoBehaviour {

	public Material mat;

	void OnRenderImage(RenderTexture src, RenderTexture dest){
		Graphics.Blit (src, dest, mat);
	}
}
```

結果

色が反転します．

![ネガ.png](https://qiita-image-store.s3.amazonaws.com/0/113504/58a9dea6-da41-9365-a808-33a8a312d3a3.png "ネガ.png")


以下のチュートリアルはShaderToyの
https://www.shadertoy.com/view/Md23DV

この投稿をUnityで実装したものになります．
> 数値に関しては，float, half, fixedの3種類がありますが，
このチュートリアルではfixedとfloatのみを使用しています．

# Github
https://github.com/teach310/ShaderTutorial2D




# Tutorial1

![Tutorial1.png](https://qiita-image-store.s3.amazonaws.com/0/113504/c806ad92-967a-6072-49b7-bdeb15067b14.png "Tutorial1.png")


```Tutorial1.shader
Shader "ShaderTutorial/Tutorial1"
{
	SubShader
	{
		// No culling or depth
		Cull Off ZWrite Off ZTest Always

		Pass
		{
			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag
			
			#include "UnityCG.cginc"

			struct appdata
			{
				float4 vertex : POSITION;
				float2 uv : TEXCOORD0;
			};

			struct v2f
			{
				float2 uv : TEXCOORD0;
				float4 vertex : SV_POSITION;
			};

			v2f vert (appdata v)
			{
				v2f o;
				o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
				o.uv = v.uv;
				return o;
			}


			fixed4 frag (v2f i) : SV_Target
			{
				return fixed4(1.0, 1.0, 0.0, 1.0);
			}
			ENDCG
		}
	}
}

```

fragの中身に注目してください.

`fixed4(1.0, 1.0, 0.0, 1.0)`が黄色を示しています．
パラメータはそれぞれ(Red, Green, Blue, Alpha(透明度))を示しています．

値は0~1.0です．

> ## Point
fragの中で色をreturnすることで絵が出る

# Tutorial2

![result_tutorial2.png](https://qiita-image-store.s3.amazonaws.com/0/113504/84a9971a-439c-c8f3-5015-6484710e09d3.png "result_tutorial2.png")

ここからはフラグメントシェーダのみスクリプトを示します．

```Tutorial2.shader
fixed4 frag (v2f i) : SV_Target
{
	fixed3 color = fixed3(0.0, 1.0, 1.0);
	fixed alpha = 1.0;

	fixed4 pixel = fixed4(color, alpha);
	return pixel;
}
```

> ## Point
fixed3型のcolorとfixed型のalphaを合体してfixed4型にできる．


# Tutorial3

![result_tutorial3.png](https://qiita-image-store.s3.amazonaws.com/0/113504/d2bf0b37-2240-54ce-1ca9-9814ff99a7cb.png "result_tutorial3.png")

```Tutorial3.shader
fixed4 frag (v2f i) : SV_Target
{
	fixed redAmount = 0.6;
	fixed greenAmount = 0.2;
	fixed blueAmount = 0.9;

	fixed3 color = fixed3(0.0, 0.0, 0.0);
	color.x = redAmount;
	color.y = greenAmount;
	color.z = blueAmount;

	fixed alpha = 1.0;
	fixed4 pixel = fixed4(color, alpha);
	return pixel;
}
```
> ## Point
fixed3の3要素には，color.xのように，xyzでアクセスできる．

# Tutorial4

![result_tutorial4.png](https://qiita-image-store.s3.amazonaws.com/0/113504/b279e7fe-1bd6-29c7-c32c-de5b3321ea47.png "result_tutorial4.png")



```Tutorial4.shader
fixed4 frag (v2f i) : SV_Target
{
	fixed3 color1 = fixed3(0.886, 0.576, 0.898);
	fixed3 color2 = fixed3(0.537, 0.741, 0.408);
	fixed3 pixel;

	if(i.uv.x > 0.5){
		pixel = color2;
	} else {
		pixel = color1;
	}

	return fixed4(pixel, 1.0);
}
```

> ## Point
引数であるiを使うことにより，現在処理しているピクセルのuv座標をi.uvで取得することができる．
今回はi.uv.x > 0.5すなわち，画面を横に分断するように色を分けた．
uv座標のx軸は画面の左から一番右端へ0~1.0である．

# Tutorial5

![result_Tutorial5.png](https://qiita-image-store.s3.amazonaws.com/0/113504/369ac26e-0c06-ae15-7fbb-538466d0ac98.png "result_Tutorial5.png")

```Tutorial5.shader
fixed4 frag (v2f i) : SV_Target
{
	fixed3 color1 = fixed3(0.886, 0.576, 0.898);
	fixed3 color2 = fixed3(0.537, 0.741, 0.408);
	fixed3 pixel;

	float dis = 50;

	if(i.uv.x * _ScreenParams.x > dis){
		pixel = color2;
	} else {
		pixel = color1;
	}

	return fixed4(pixel, 1.0);
}
```

> ## Point
uv座標に，スクリーンの解像度(_ScreenParams)を掛け算することで，現在処理しているピクセルの位置を取得できる．

# Tutorial6 線の引き方
![result_tutorial6.png](https://qiita-image-store.s3.amazonaws.com/0/113504/ca0123df-c167-f64a-0423-d16c4e642d24.png "result_tutorial6.png")


```Tutorial6.shader
// HORIZONTAL AND VERTICAL LINES
fixed4 frag (v2f i) : SV_Target
{
	fixed3 backgroundColor = fixed3(1.0, 1.0, 1.0);
	fixed3 color1 = fixed3(0.216, 0.471, 0.698); // blue
	fixed3 color2 = fixed3(1.00, 0.329, 0.298); // red
	fixed3 color3 = fixed3(0.867, 0.910, 0.247); // yellow

	fixed3 pixel = backgroundColor;

	// line1
	float leftCoord = 0.54;
	float rightCoord = 0.55;
	if(i.uv.x < rightCoord && i.uv.x > leftCoord) pixel = color1;

	// line2
	float lineCoordinate = 0.4;
	float lineThickness = 0.003;
	if(abs(i.uv.x - lineCoordinate) < lineThickness ) pixel = color2;

	// line3
	if(abs(i.uv.y - 0.6) < 0.01) pixel = color3;

	return fixed4(pixel, 1.0);
}
```

> ## Point
線の引き方には2種類あり，一つ目は線の端の座標を示す方法(line1)．二つ目は線の中心の座標と厚さを示す方法である(line2,3)
後者の場合には`if(abs(i.uv.x - lineCoordinate) < lineThickness )`で表せる．

# もし上下が反転していたら
```glsl
v2f vert(appdata v)
{
	v2f o;
	o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
	o.uv = v.uv;
	o.uv.y = 1-o.uv.y; //この行を加える．
	return o;
}
```

# Tutorial7  座標の視覚化

![result_tutorial7.png](https://qiita-image-store.s3.amazonaws.com/0/113504/0478a1b4-08aa-01ae-56df-92b375067471.png "result_tutorial7.png")


```Tutorial7.shader
// VISUALISING THE COORDINATE SYSTEM
fixed4 frag (v2f i) : SV_Target
{
	fixed3 backgroundColor = fixed3(1.0, 1.0, 1.0);
	fixed3 axesColor = fixed3(0.0, 0.0, 1.0);
	fixed3 gridColor = fixed3(0.5, 0.5, 0.5);

	fixed3 pixel = backgroundColor;

	const float tickWidth = 0.1;
	for(float lc=0.0; lc< 1.0; lc+=tickWidth){
		if(abs(i.uv.x - lc) < 0.002) pixel = gridColor;
		if(abs(i.uv.y - lc) < 0.002) pixel = gridColor;
	}

	// Draw the axes
	if(abs(i.uv.x)<0.005) pixel = axesColor;
	if(abs(i.uv.y)<0.006) pixel = axesColor;

	return fixed4(pixel, 1.0);
}
```

> ## Point
for文で線を引く座標を変えることで，等間隔に線を引くことができる．

# Tutorial8 座標　軸中心

![result_tutorial8.png](https://qiita-image-store.s3.amazonaws.com/0/113504/06b94e07-ab11-1f84-8dc9-3784d694b21d.png "result_tutorial8.png")


fragの外にも記入したため，全文

```Tutorial8.shader
Shader "ShaderTutorial/Tutorial8"
{
	SubShader
	{
		// No culling or depth
		Cull Off ZWrite Off ZTest Always

		// 追加
		CGINCLUDE
		float mod(float  a, float  b) { return a-b*floor(a/b); } 
		ENDCG


		Pass
		{
			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag
			
			#include "UnityCG.cginc"

			struct appdata
			{
				float4 vertex : POSITION;
				float2 uv : TEXCOORD0;
			};

			struct v2f
			{
				float2 uv : TEXCOORD0;
				float4 vertex : SV_POSITION;
			};

			v2f vert (appdata v)
			{
				v2f o;
				o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
				o.uv = v.uv;
				return o;
			}

			// MOVING THE COORDINATE CENTER TO THE CENTER OF THE FRAME
			fixed4 frag (v2f i) : SV_Target
			{
				fixed2 r = 2.0 * fixed2(i.uv.x - 0.5, i.uv.y - 0.5);
				fixed3 backgroundColor = fixed3(1.0, 1.0, 1.0);
				fixed3 axesColor = fixed3(0.0, 0.0, 1.0);
				fixed3 gridColor = fixed3(0.5, 0.5, 0.5);

				fixed3 pixel = backgroundColor;

				const float tickWidth = 0.1;
				if( mod(r.x, tickWidth) < 0.008 ) pixel = gridColor;
				if( mod(r.y, tickWidth) < 0.008 ) pixel = gridColor;

				// Draw the axes
				if(abs(r.x)<0.006) pixel = axesColor;
				if(abs(r.y)<0.007) pixel = axesColor;

				return fixed4(pixel, 1.0);
			}


			ENDCG
		}
	}
}
```

> ## Point
自前の関数をPassの外側に，CGINCLUDE ~ ENDCG の間に記述している．
このmod関数はaをbで割った余りを返す関数である．
これを使うことで，
if(r.xをtickWidthで割った余り < 0.008) グリッドの色にする．
とすることができている．

また，i.uv.xが0~1の値をとるのに対し，-0.5したものを2倍することによって
r，画面の領域を-1 ~ 1で表すことができる．

# Tutorial9 縦横比にあわせる
![result_tutorial9.png](https://qiita-image-store.s3.amazonaws.com/0/113504/530687a9-96a3-f1fd-0654-f72732861dd1.png "result_tutorial9.png")

```Tutorial9.shader
// MAKING THE ASPECT RATIO OF THE COORDINATE SYSTEM 1.0
fixed4 frag (v2f i) : SV_Target
{
	float2 r = 2.0 * (i.uv - 0.5);
	float aspectRatio = _ScreenParams.x / _ScreenParams.y;
	r.x *= aspectRatio;

	fixed3 backgroundColor = fixed3(1.0, 1.0, 1.0);
	fixed3 axesColor = fixed3(0.0, 0.0, 1.0);
	fixed3 gridColor = fixed3(0.5, 0.5, 0.5);

	fixed3 pixel = backgroundColor;

	const float tickWidth = 0.2;
	if( mod(r.x, tickWidth) < 0.008 ) pixel = gridColor;
	if( mod(r.y, tickWidth) < 0.008 ) pixel = gridColor;

	// Draw the axes
	if(abs(r.x)<0.006) pixel = axesColor;
	if(abs(r.y)<0.007) pixel = axesColor;

	return fixed4(pixel, 1.0);
}
```

> ## Point
r.xに_ScreenParamsから求めたaspectRatioを掛け算することで，縦横の目盛りが同じ長さになる．

# Tutorial10 DISK
![result_tutorial10.PNG](https://qiita-image-store.s3.amazonaws.com/0/113504/1d9f10fe-7402-87d2-a7f3-e108dba2acc7.png "result_tutorial10.PNG")

```Tutorial10.shader
// Draw Disks
fixed4 frag (v2f i) : SV_Target
{
	float2 r = 2.0 * (i.uv - 0.5);
	float aspectRatio = _ScreenParams.x / _ScreenParams.y;
	r.x *= aspectRatio;

	fixed3 backgroundColor = fixed3(1.0, 1.0, 1.0);
	fixed3 col1 = fixed3(0.216, 0.471, 0.698); // blue
	fixed3 col2 = fixed3(1.00, 0.329, 0.298); // red
	fixed3 col3 = fixed3(0.867, 0.910, 0.247); // yellow

	fixed3 pixel = backgroundColor;
	
	//Disk1 blue
	float radius = 0.8;
	if(r.x*r.x + r.y*r.y < radius*radius){
		pixel = col1;
	}
	
	//Disk2 red
	if(length(r) < 0.3){
		pixel = col3;
	}
	
	//Disk3 yellow
	float2 center = fixed2(0.9, -0.4);
	float2 d = r - center;
	if( length(d) < 0.6){
		pixel = col2;
	}

	return fixed4(pixel, 1.0);
}
```

> ## Point
Disk1では，2点間の距離求める公式を2乗することで，半径0.8以内を塗るという処理を行っている．
Disk2では，ベクトルの距離を求めるlength関数を用いることで，短く書いている．
Disk3では，移動させたい分だけ引き算することによって円の中心位置を移動している．
例：　
```math
y = (x-3)^2
```
だと，線がx軸正の方向に3移動する．


# Tutorial11 Functionを作る

![result_tutorial11.PNG](https://qiita-image-store.s3.amazonaws.com/0/113504/eb6cb3d0-31be-e884-baf1-2d6875741976.png "result_tutorial11.PNG")

```Tutorial11.shader
Shader "ShaderTutorial/Tutorial11"
{
	SubShader
	{
		// No culling or depth
		Cull Off ZWrite Off ZTest Always

		// 追加
		CGINCLUDE
		fixed3 disk(fixed2 r, fixed2 center, fixed radius, fixed3 color, fixed3 pixel){
			fixed3 col = pixel;
			if(length(r - center) < radius){
				col = color;
			}
			return col;
		}
		ENDCG


		Pass
		{
			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag
			
			#include "UnityCG.cginc"

			struct appdata
			{
				float4 vertex : POSITION;
				float2 uv : TEXCOORD0;
			};

			struct v2f
			{
				float2 uv : TEXCOORD0;
				float4 vertex : SV_POSITION;
			};

			v2f vert (appdata v)
			{
				v2f o;
				o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
				o.uv = v.uv;
				o.uv.y = 1-o.uv.y;
				return o;
			}

			// Functions
			fixed4 frag (v2f i) : SV_Target
			{
				float2 r = 2.0 * (i.uv - 0.5);
				float aspectRatio = _ScreenParams.x / _ScreenParams.y;
				r.x *= aspectRatio;

				fixed3 backgroundColor = fixed3(0.3, 0.3, 0.3);
				fixed3 col1 = fixed3(0.216, 0.471, 0.698); // blue
				fixed3 col2 = fixed3(1.00, 0.329, 0.298); // red
				fixed3 col3 = fixed3(0.867, 0.910, 0.247); // yellow

				fixed3 pixel = backgroundColor;
				
				pixel = disk(r, fixed2(0.1, 0.3), 0.5, col3, pixel);
				pixel = disk(r, fixed2(-0.8, -0.6), 1.5, col1, pixel);
				pixel = disk(r, fixed2(0.8, 0.0), 0.15, col2, pixel);


				return fixed4(pixel, 1.0);
			}


			ENDCG
		}
	}
}
```

> ## Point
関数はCGINCLUDE ~ ENDCG内に記述．
return文が使える．


# Tutorial12 STEP

![result_tutorial12.PNG](https://qiita-image-store.s3.amazonaws.com/0/113504/fbc6a499-86b3-aacc-3019-cdb600ea1664.png "result_tutorial12.PNG")

```Tutorial12.shader
// BUILT-IN FUNCTION: STEP
fixed4 frag (v2f i) : SV_Target
{
	float2 r = 2.0 * (i.uv - 0.5);
	float aspectRatio = _ScreenParams.x / _ScreenParams.y;
	r.x *= aspectRatio;

	fixed3 backgroundColor = fixed3(0.0, 0.0, 0.0); // black
	fixed3 col1 = fixed3(0.216, 0.471, 0.698); // blue
	fixed3 col2 = fixed3(1.00, 0.329, 0.298); // red
	fixed3 col3 = fixed3(0.867, 0.910, 0.247); // yellow

	fixed3 pixel = backgroundColor;
	
	float edge, variable, ret;

	// divide the screen into five parts horizontally
	// for different examples
	if(r.x < -0.6 * aspectRatio){ // part1
		variable = r.y;
		edge = 0.2;
		if( variable > edge ){
			ret = 1.0;
		}else{
			ret = 0.0;
		}
	}
	else if(r.x < -0.2 * aspectRatio){ //part2
		variable = r.y;
		edge = -0.2;
		// part1と同じこと
		ret = step(edge, variable); 
	}
	else if(r.x < 0.2 * aspectRatio){
		// 1.0 - step(a,b) で反転
		ret = 1.0 - step(0.5, r.y); 
	}
	else if(r.x < 0.6 * aspectRatio){
		// r.yが-0.4以上でretは0.3 + 0.5 = 0.8
		ret = 0.3 + 0.5 * step(-0.4, r.y);  
	}
	else{
		// stepを二つ使うことでgapを生み出すことができる
		ret = step(-0.3, r.y) * (1.0 - step(0.2, r.y)); 
	}

	pixel = fixed3 (ret, ret, ret);
	return fixed4(pixel, 1.0);
}
```

> ## Point
|名前|説明|
|:--|:--|
|step(a,b)|bがaをより大きければ1, そうでなければ0|

# Tutorial13

![result_tutorial13.png](https://qiita-image-store.s3.amazonaws.com/0/113504/e262df80-9da0-a707-2882-1babea68178a.png "result_tutorial13.png")


```Tutorial13.shader
Shader "ShaderTutorial/Tutorial13"
{
	SubShader
	{
		// No culling or depth
		Cull Off ZWrite Off ZTest Always

		// 追加
		CGINCLUDE
		#define PI 3.14159
		ENDCG


		Pass
		{
			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag
			
			#include "UnityCG.cginc"

			struct appdata
			{
				float4 vertex : POSITION;
				float2 uv : TEXCOORD0;
			};

			struct v2f
			{
				float2 uv : TEXCOORD0;
				float4 vertex : SV_POSITION;
			};

			v2f vert (appdata v)
			{
				v2f o;
				o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
				o.uv = v.uv;
				o.uv.y = 1-o.uv.y;
				return o;
			}

			// BUILT-IN FUNCTION: CLAMP
			fixed4 frag (v2f i) : SV_Target
			{
				float2 r = 2.0 * (i.uv - 0.5);
				float aspectRatio = _ScreenParams.x / _ScreenParams.y;
				r.x *= aspectRatio;

				fixed3 backgroundColor = fixed3(0.0, 0.0, 0.0); // black
				fixed3 col1 = fixed3(0.216, 0.471, 0.698); // blue
				fixed3 col2 = fixed3(1.00, 0.329, 0.298); // red
				fixed3 col3 = fixed3(0.867, 0.910, 0.247); // yellow

				fixed3 pixel = backgroundColor;
				
				float edge, variable, ret;

				// divide the screen into four parts horizontally
				// for different examples
				if(i.uv.x < 0.25){ // part1
					ret = i.uv.y;
				}
				else if(i.uv.x < 0.5){ // part2
					float minVal = 0.3;
					float maxVal = 0.6;
					variable = i.uv.y;
					if (variable < minVal){
						ret = minVal;
					}
					if( variable > minVal && variable < maxVal){
						ret = variable;
					}
					if( variable > maxVal ){
						ret = maxVal;
					}
				}
				else if(i.uv.x < 0.75){ // part3
					float minVal = 0.6;
					float maxVal = 0.8;
					variable = i.uv.y;
					ret = clamp(variable, minVal, maxVal);
				}
				else { // part4
					float y = cos(5.0 * 2.0 * PI *i.uv.y);
					y = (y+1.0)*0.5; // map [-1,1] to [0,1]
					ret = clamp(y, 0.2, 0.8);
				}

				pixel = fixed3 (ret, ret, ret);
				return fixed4(pixel, 1.0);
			}


			ENDCG
		}
	}
}
```

> ## Point
|名前|説明|
|:--|:--|
|float Clamp(float a,float min,float max)|aがminよりも小さければmin, aがmaxよりも大きければmax, それ以外であればaを返す|

# Tutorial14 smoothstep

![result_tutorial14.png](https://qiita-image-store.s3.amazonaws.com/0/113504/e87f15a5-4324-1477-bfdc-0f4de98ab4ee.png "result_tutorial14.png")


```Tutorial14.shader
// BUILT-IN FUNCTION: SMOOTHSTEP
fixed4 frag (v2f i) : SV_Target
{
	fixed3 backgroundColor = fixed3(0.0, 0.0, 0.0); // black
	fixed3 col1 = fixed3(0.216, 0.471, 0.698); // blue
	fixed3 col2 = fixed3(1.00, 0.329, 0.298); // red
	fixed3 col3 = fixed3(0.867, 0.910, 0.247); // yellow

	fixed3 pixel = backgroundColor;
	
	float edge, variable, ret;

	// divide the screen into five parts horizontally
	// for different examples
	if(i.uv.x < 1.0/5.0){ // part1
		edge = 0.5;
		ret = step(edge, i.uv.y);
	}
	else if(i.uv.x < 2.0/5.0){ // part2
		float edge0 = 0.45;
		float edge1 = 0.55;
		float t = (i.uv.y - edge0) / (edge1 - edge0);
		//when i.uv.y == edge0 => t = 0.0
		//when i.uv.y == edge1 => t = 1.0
		//0から1に線形に遷移する
		float t1 = clamp(t, 0.0, 1.0);
		//edge0 未満の時は マイナスの値をとり，
		//edge1 より大きい時は1.0より大きい値をとる．
		//しかし，0~1の値がほしいのでclampを使います
		ret = t1;
	}
	else if(i.uv.x < 3.0/ 5.0){ // part3
		float edge0 = 0.45;
		float edge1 = 0.55;
		float t = clamp((i.uv.y - edge0)/(edge1 - edge0), 0.0, 1.0);
		float t1 = 3.0*t*t - 2.0*t*t*t;
		//線形でなくなめらかにする．
		ret = t1;
	}
	else if(i.uv.x < 4.0/5.0){ // part4
		ret = smoothstep(0.45, 0.55, i.uv.y);
	}
	else if(i.uv.x < 5.0/5.0){
		float edge0 = 0.45;
		float edge1 = 0.55;
		float t = clamp((i.uv.y - edge0)/(edge1 - edge0), 0.0, 1.0);
		float t1 = t*t*t*(t*(t*6.0 - 15.0) + 10.0);
		ret = t1;
	}


	pixel = fixed3 (ret, ret, ret);
	return fixed4(pixel, 1.0);
}
```

> ## Point
|名前|説明|
|:--|:--|
|float smoothstep(float min, float max, float a)|aがminとmaxの間の時に，線形でなく，なめらかに補完するような値を返す．min以下であれば0,max以上で1|

# Tutorial15 lerp

![result_tutorial15.png](https://qiita-image-store.s3.amazonaws.com/0/113504/c50753ee-40d0-51f7-9b58-3c665500de58.png "result_tutorial15.png")

```Tutorial15.shader
// BUILT-IN FUNCTION: LERP
fixed4 frag (v2f i) : SV_Target
{

	fixed3 backgroundColor = fixed3(0.0, 0.0, 0.0); // black
	fixed3 col1 = fixed3(0.216, 0.471, 0.698); // blue
	fixed3 col2 = fixed3(1.00, 0.329, 0.298); // red
	fixed3 col3 = fixed3(0.867, 0.910, 0.247); // yellow

	fixed3 pixel = backgroundColor;
	
	fixed3 ret;

	// divide the screen into five parts horizontally
	// for different examples
	if(i.uv.x < 1.0/5.0){ // part1
		float x0 = 0.2;
		float x1 = 0.7;
		float m = 0.1;
		float val = x0 * (1.0-m) + x1*m;
		ret = fixed3(val, val, val);
	}
	else if(i.uv.x < 2.0/5.0){ // part2
		float x0 = 0.2;
		float x1 = 0.7;
		float m = i.uv.y;
		float val = x0*(1.0-m) + x1*m;
		ret = fixed3(val, val, val);
	}
	else if(i.uv.x < 3.0/ 5.0){ // part3
		float x0 = 0.2;
		float x1 = 0.7;
		float m = i.uv.y;
		float val = lerp(x0, x1, m);
		ret = fixed3(val, val, val);

	}
	else if(i.uv.x < 4.0/5.0){ // part4
		float m = i.uv.y;
		ret = lerp(col1, col2, m);
	}
	else if(i.uv.x < 5.0/5.0){
		//smoothstepとlerpを使った色の遷移
		float m = smoothstep(0.5, 0.6, i.uv.y);
		ret = lerp(col1, col2, m);
	}


	pixel = ret;
	return fixed4(pixel, 1.0);
}
```
> ## Point
|名前|説明|
|:--|:--|
|float lerp(a,b,s)|a+s(b-a)を返す．aからbへの線形補完 sは基本0~1で使う|

# Tutorial16 COLOR ADDITION AND SUBSTRCTION
![result_tutorial16.png](https://qiita-image-store.s3.amazonaws.com/0/113504/2c725327-8411-1ce5-b068-83ca30277ad9.png "result_tutorial16.png")

```Tutorial16.shader
Shader "ShaderTutorial/Tutorial18"
{
	SubShader
	{
		// No culling or depth
		Cull Off ZWrite Off ZTest Always

		// 追加
		CGINCLUDE
		// なめらかなDISK
		float disk(float2 r, float2 center, float radius){
			float distanceFromCenter = length(r - center);
			float outsideOfDisk = smoothstep(radius - 0.005, radius + 0.005, distanceFromCenter);
			float insideOfDisk = 1.0 - outsideOfDisk;
			return insideOfDisk;

		}
		ENDCG


		Pass
		{
			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag
			
			#include "UnityCG.cginc"

			struct appdata
			{
				float4 vertex : POSITION;
				float2 uv : TEXCOORD0;
			};

			struct v2f
			{
				float2 uv : TEXCOORD0;
				float4 vertex : SV_POSITION;
			};

			v2f vert (appdata v)
			{
				v2f o;
				o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
				o.uv = v.uv;
				o.uv.y = 1-o.uv.y;
				return o;
			}

			// ANTI-ALIASING WITH SMOOTHSTEP
			fixed4 frag (v2f i) : SV_Target
			{
				float2 r = 2.0 * (i.uv - 0.5);
				float aspectRatio = _ScreenParams.x / _ScreenParams.y;
				r.x *= aspectRatio;

				fixed3 black = float3(0.0, 0.0, 0.0); // black
				fixed3 white = float3(1.0, 1.0, 1.0);
				fixed3 gray = float3(0.3, 0.3, 0.3);
				fixed3 col1 = float3(0.216, 0.471, 0.698); // blue
				fixed3 col2 = float3(1.00, 0.329, 0.298); // red
				fixed3 col3 = float3(0.867, 0.910, 0.247); // yellow

				fixed3 ret;
				fixed3 pixel;
				float d;


				if(i.uv.x < 1.0/3.0){ // part1
					ret = gray;
					d = disk(r, float2(-1.1, 0.3), 0.4);
					ret = lerp(ret, col1, d);
					d = disk(r, float2(-1.3, 0.0), 0.4);
					ret = lerp(ret, col2, d);
					d = disk(r, float2(-1.05, -0.3), 0.4);
					ret = lerp(ret, col3, d);
				}
				else if(i.uv.x < 2.0/3.0){ // part2
					// Color addition
					ret = black;
					ret += disk(r, float2(0.1, 0.3), 0.4) * col1;
					ret += disk(r, float2(-0.1, 0.0), 0.4) * col2;
					ret += disk(r, float2(0.15, -0.3), 0.4) * col3;
 				}
				else if(i.uv.x < 3.0/ 3.0){ // part3
					// Color substraction
					ret = white;
					ret -= disk(r, float2(1.1, 0.3), 0.4) * col1;
					ret -= disk(r, float2(1.05, 0.0), 0.4) * col2;
					ret -= disk(r, float2(1.35, -0.25), 0.4) * col3;

				}



				pixel = ret;
				return fixed4(pixel, 1.0);
			}


			ENDCG
		}
	}
}
```

> ## Point
円の境界をなめらかにしている．
ret に加算減算することで色を変化させている．

# Tutorial17 回転

![result_tutorial17.PNG](https://qiita-image-store.s3.amazonaws.com/0/113504/78a34857-d850-4b51-010d-de6b9a617e68.png "result_tutorial17.PNG")


```Tutorial17.shader
Shader "ShaderTutorial/Tutorial17"
{
	SubShader
	{
		// No culling or depth
		Cull Off ZWrite Off ZTest Always

		// 追加
		CGINCLUDE

		#define PI 3.14159

		// (anti-aliased)Gridを作る関数
		float coordinateGrid(float2 r){
			float3 axisCol = float3(0.0, 0.0, 1.0);
			float3 gridCol = float3(0.5, 0.5, 0.5);
			float ret = 0.0;

			// Draw grid lines
			const float tickWidth = 0.1;
			for(float i= -2.0;i<2.0; i+= tickWidth){
				ret += 1.0 - smoothstep(0.0, 0.008, abs (r.x - i));
				ret += 1.0 - smoothstep(0.0, 0.008, abs (r.y - i));
			}

			// Draw the axis
			ret += 1.0-smoothstep(0.001, 0.015, abs(r.x));
			ret += 1.0-smoothstep(0.001, 0.015, abs(r.y));
			return ret;
		}

		// returns 1.0 if inside circle
		float disk(float2 r, float2 center, float radius){
			return 1.0 - smoothstep( radius - 0.005, radius + 0.005, length(r - center));
		}

		// returns 1.0 if inside the disk
		float rectangle(float2 r, float2 bottomLeft, float2 topRight){
			float ret;
			float d = 0.005;
			ret = smoothstep(bottomLeft.x - d, bottomLeft.x + d, r.x);
			ret *= smoothstep(bottomLeft.y - d, bottomLeft.y + d, r.y);
			ret *= 1.0 - smoothstep(topRight.y - d, topRight.y + d, r.y);
			ret *= 1.0 - smoothstep(topRight.x - d, topRight.x + d, r.x);
			return ret;
		}
		ENDCG


		Pass
		{
			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag
			
			#include "UnityCG.cginc"

			struct appdata
			{
				float4 vertex : POSITION;
				float2 uv : TEXCOORD0;
			};

			struct v2f
			{
				float2 uv : TEXCOORD0;
				float4 vertex : SV_POSITION;
			};

			v2f vert (appdata v)
			{
				v2f o;
				o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
				o.uv = v.uv;
				o.uv.y = 1-o.uv.y;
				return o;
			}

			//COORDINATE TRANSFORMATIONS: ROTATION
			fixed4 frag (v2f i) : SV_Target
			{
				float2 r = 2.0 * (i.uv - 0.5);
				float aspectRatio = _ScreenParams.x / _ScreenParams.y;
				r.x *= aspectRatio;

				fixed3 bgCol = float3(1.0, 1.0, 1.0); // white
		
				fixed3 col1 = float3(0.216, 0.471, 0.698); // blue
				fixed3 col2 = float3(1.00, 0.329, 0.298); // red
				fixed3 col3 = float3(0.867, 0.910, 0.247); // yellow

				fixed3 ret;
				float2 q;
				float angle;
				angle = 0.2*PI; // 単位はラジアン
				// 2次元の回転
				q.x = cos(angle)*r.x + sin(angle)*r.y;
				q.y = -sin(angle)*r.x + cos(angle)*r.y;

				ret = bgCol;
				// draw the old and new coordinate systems
				ret = lerp(ret, col1, coordinateGrid(r)*0.4);
				ret = lerp(ret, col2, coordinateGrid(q));

				// draw shapes
				ret = lerp(ret, col1, disk(r, float2(1.0, 0.0), 0.2));
				ret = lerp(ret, col2, disk(q, float2(1.0, 0.0), 0.2));
				ret = lerp(ret, col1, rectangle(r, float2(-0.8, 0.2),float2(-0.5, 0.4)));
				ret = lerp(ret, col2, rectangle(q, float2(-0.8, 0.2),float2(-0.5, 0.4)));



				fixed3 pixel = ret;
				return fixed4(pixel, 1.0);
			}


			ENDCG
		}
	}
}
```

> ## Point
回転行列をrに掛け算することで，座標を回転させ，その座標上の図形も回転させている．

# Tutorial18 スケーリング

![result_tutorial18.PNG](https://qiita-image-store.s3.amazonaws.com/0/113504/331dd0c1-cf98-bbf9-d2df-1809b276f70c.png "result_tutorial18.PNG")


```Tutorial18.shader
Shader "ShaderTutorial/Tutorial18"
{
	SubShader
	{
		// No culling or depth
		Cull Off ZWrite Off ZTest Always

		// 追加
		CGINCLUDE

		#define PI 3.14159

		// (anti-aliased)Gridを作る関数
		float coordinateGrid(float2 r){
			float3 axisCol = float3(0.0, 0.0, 1.0);
			float3 gridCol = float3(0.5, 0.5, 0.5);
			float ret = 0.0;

			// Draw grid lines
			const float tickWidth = 0.1;
			for(float i= -2.0;i<2.0; i+= tickWidth){
				ret += 1.0 - smoothstep(0.0, 0.008, abs (r.x - i));
				ret += 1.0 - smoothstep(0.0, 0.008, abs (r.y - i));
			}

			// Draw the axis
			ret += 1.0-smoothstep(0.001, 0.015, abs(r.x));
			ret += 1.0-smoothstep(0.001, 0.015, abs(r.y));
			return ret;
		}

		// returns 1.0 if inside circle
		float disk(float2 r, float2 center, float radius){
			return 1.0 - smoothstep( radius - 0.005, radius + 0.005, length(r - center));
		}

		// returns 1.0 if inside the disk
		float rectangle(float2 r, float2 bottomLeft, float2 topRight){
			float ret;
			float d = 0.005;
			ret = smoothstep(bottomLeft.x - d, bottomLeft.x + d, r.x);
			ret *= smoothstep(bottomLeft.y - d, bottomLeft.y + d, r.y);
			ret *= 1.0 - smoothstep(topRight.y - d, topRight.y + d, r.y);
			ret *= 1.0 - smoothstep(topRight.x - d, topRight.x + d, r.x);
			return ret;
		}
		ENDCG


		Pass
		{
			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag
			
			#include "UnityCG.cginc"

			struct appdata
			{
				float4 vertex : POSITION;
				float2 uv : TEXCOORD0;
			};

			struct v2f
			{
				float2 uv : TEXCOORD0;
				float4 vertex : SV_POSITION;
			};

			v2f vert (appdata v)
			{
				v2f o;
				o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
				o.uv = v.uv;
				o.uv.y = 1-o.uv.y;
				return o;
			}

			//COORDINATE TRANSFORMATIONS: SCALING
			fixed4 frag (v2f i) : SV_Target
			{
				float2 r = 2.0 * (i.uv - 0.5);
				float aspectRatio = _ScreenParams.x / _ScreenParams.y;
				r.x *= aspectRatio;

				fixed3 bgCol = float3(1.0, 1.0, 1.0); // white
		
				fixed3 col1 = float3(0.216, 0.471, 0.698); // blue
				fixed3 col2 = float3(1.00, 0.329, 0.298); // red
				fixed3 col3 = float3(0.867, 0.910, 0.247); // yellow

				fixed3 ret;
				ret = bgCol;

				// original
				ret = lerp(ret, col1, coordinateGrid(r)/2.0);

				// scaled
				float2 q = 0.3*r;
				ret = lerp(ret, col2, coordinateGrid(q));

				// draw shapes
				ret = lerp(ret, col2, disk(q, float2(0.0, 0.0), 0.1)); //大
				ret = lerp(ret, col1, disk(r, float2(0.0, 0.0), 0.1));

				ret = lerp(ret, col1, rectangle(r, float2(-0.5, 0.0),float2(-0.2, 0.2)));
				ret = lerp(ret, col2, rectangle(q, float2(-0.5, 0.0),float2(-0.2, 0.2))); //大



				fixed3 pixel = ret;
				return fixed4(pixel, 1.0);
			}


			ENDCG
		}
	}
}
```

> ## Point
rに係数をかけることで，拡大・縮小できる．(0.3をかけることで，大きくなっている．)

# Tutorial19 Transform

![result_tutorial19.PNG](https://qiita-image-store.s3.amazonaws.com/0/113504/7d2a9ce4-8e31-750e-27c4-9acbfd28062b.png "result_tutorial19.PNG")


```Tutorial19.shader
Shader "ShaderTutorial/Tutorial19"
{
	SubShader
	{
		// No culling or depth
		Cull Off ZWrite Off ZTest Always

		// 追加
		CGINCLUDE

		#define PI 3.14159

		// (anti-aliased)Gridを作る関数
		float coordinateGrid(float2 r){
			float3 axisCol = float3(0.0, 0.0, 1.0);
			float3 gridCol = float3(0.5, 0.5, 0.5);
			float ret = 0.0;

			// Draw grid lines
			const float tickWidth = 0.1;
			for(float i= -2.0;i<2.0; i+= tickWidth){
				ret += 1.0 - smoothstep(0.0, 0.008, abs (r.x - i));
				ret += 1.0 - smoothstep(0.0, 0.008, abs (r.y - i));
			}

			// Draw the axis
			ret += 1.0-smoothstep(0.001, 0.015, abs(r.x));
			ret += 1.0-smoothstep(0.001, 0.015, abs(r.y));
			return ret;
		}

		// returns 1.0 if inside circle
		float disk(float2 r, float2 center, float radius){
			return 1.0 - smoothstep( radius - 0.005, radius + 0.005, length(r - center));
		}

		// returns 1.0 if inside the disk
		float rectangle(float2 r, float2 bottomLeft, float2 topRight){
			float ret;
			float d = 0.005;
			ret = smoothstep(bottomLeft.x - d, bottomLeft.x + d, r.x);
			ret *= smoothstep(bottomLeft.y - d, bottomLeft.y + d, r.y);
			ret *= 1.0 - smoothstep(topRight.y - d, topRight.y + d, r.y);
			ret *= 1.0 - smoothstep(topRight.x - d, topRight.x + d, r.x);
			return ret;
		}
		ENDCG


		Pass
		{
			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag
			
			#include "UnityCG.cginc"

			struct appdata
			{
				float4 vertex : POSITION;
				float2 uv : TEXCOORD0;
			};

			struct v2f
			{
				float2 uv : TEXCOORD0;
				float4 vertex : SV_POSITION;
			};

			v2f vert (appdata v)
			{
				v2f o;
				o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
				o.uv = v.uv;
				o.uv.y = 1-o.uv.y;
				return o;
			}

			//COORDINATE TRANSFORMATIONS
			fixed4 frag (v2f i) : SV_Target
			{
				float2 r = 2.0 * (i.uv - 0.5);
				float aspectRatio = _ScreenParams.x / _ScreenParams.y;
				r.x *= aspectRatio;

				fixed3 bgCol = float3(1.0, 1.0, 1.0); // white
		
				fixed3 col1 = float3(0.216, 0.471, 0.698); // blue
				fixed3 col2 = float3(1.00, 0.329, 0.298); // red
				fixed3 col3 = float3(0.867, 0.910, 0.247); // yellow

				fixed3 ret;
				ret = bgCol;

				float angle = -0.6;
				float2x2 rotationMatrix = float2x2(cos(angle), -sin(angle),
												sin(angle), cos(angle));

				
				if(i.uv.x < 1.0/2.0) //part1
				{
					//座標の中心をuv.x: 1/4の位置にする。
					r = r - float2(-aspectRatio/2.0, 0);
					float2 rotated = mul(rotationMatrix, r);
					float2 rotatedTranslated = rotated - float2(0.4, 0.5);
					ret = lerp(ret, col1, coordinateGrid(r) * 0.3);
					ret = lerp(ret, col2, coordinateGrid(rotated)*0.3);
					ret = lerp(ret, col3, coordinateGrid(rotatedTranslated)*0.3);

					ret = lerp(ret, col1, rectangle(r, float2(-0.1, -0.2), float2(0.1, 0.2)));
					ret = lerp(ret, col2, rectangle(rotated, float2(-0.1, -0.2), float2(0.1, 0.2)));
					ret = lerp(ret, col3, rectangle(rotatedTranslated, float2(-0.1, -0.2), float2(0.1, 0.2)));
				}
				else if(i.uv.x < 2.0/2.0){ //part2
					//座標の中心をuv.x: 1/4の位置にする。
					r = r - float2(aspectRatio/2.0, 0);
					float2 translated = r - float2(0.4, 0.5);
					float2 translatedRotated = mul(rotationMatrix, translated);
					
					ret = lerp(ret, col1, coordinateGrid(r) * 0.3);
					ret = lerp(ret, col2, coordinateGrid(translated)*0.3);
					ret = lerp(ret, col3, coordinateGrid(translatedRotated)*0.3);

					ret = lerp(ret, col1, rectangle(r, float2(-0.1, -0.2), float2(0.1, 0.2)));
					ret = lerp(ret, col2, rectangle(translated, float2(-0.1, -0.2), float2(0.1, 0.2)));
					ret = lerp(ret, col3, rectangle(translatedRotated, float2(-0.1, -0.2), float2(0.1, 0.2)));
				}




				fixed3 pixel = ret;
				return fixed4(pixel, 1.0);
			}


			ENDCG
		}
	}
}
```

> ## Point
float2x2で，2かける2の正方行列を示す．これによって回転行列を表現し，mul関数によって行列の掛け算を行っている．


## Tutorial20 Animations

![result_tutorial21.gif](https://qiita-image-store.s3.amazonaws.com/0/113504/fc3d4d6c-6b09-2703-778a-93dcea221d83.gif "result_tutorial21.gif")


```Tutorial20.shader
Shader "ShaderTutorial/Tutorial20"
{
	SubShader
	{
		// No culling or depth
		Cull Off ZWrite Off ZTest Always

		// 追加
		CGINCLUDE

		#define PI 3.14159

		// (anti-aliased)Gridを作る関数
		float coordinateGrid(float2 r){
			float3 axisCol = float3(0.0, 0.0, 1.0);
			float3 gridCol = float3(0.5, 0.5, 0.5);
			float ret = 0.0;

			// Draw grid lines
			const float tickWidth = 0.1;
			for(float i= -2.0;i<2.0; i+= tickWidth){
				ret += 1.0 - smoothstep(0.0, 0.008, abs (r.x - i));
				ret += 1.0 - smoothstep(0.0, 0.008, abs (r.y - i));
			}

			// Draw the axis
			ret += 1.0-smoothstep(0.001, 0.015, abs(r.x));
			ret += 1.0-smoothstep(0.001, 0.015, abs(r.y));
			return ret;
		}

		// returns 1.0 if inside circle
		float disk(float2 r, float2 center, float radius){
			return 1.0 - smoothstep( radius - 0.005, radius + 0.005, length(r - center));
		}

		// returns 1.0 if inside the rect
		float rectangle(float2 r, float2 bottomLeft, float2 topRight){
			float ret;
			float d = 0.005;
			ret = smoothstep(bottomLeft.x - d, bottomLeft.x + d, r.x);
			ret *= smoothstep(bottomLeft.y - d, bottomLeft.y + d, r.y);
			ret *= 1.0 - smoothstep(topRight.y - d, topRight.y + d, r.y);
			ret *= 1.0 - smoothstep(topRight.x - d, topRight.x + d, r.x);
			return ret;
		}

		float mod(float  a, float  b) { return a-b*floor(a/b); } 
		ENDCG


		Pass
		{
			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag
			
			#include "UnityCG.cginc"

			struct appdata
			{
				float4 vertex : POSITION;
				float2 uv : TEXCOORD0;
			};

			struct v2f
			{
				float2 uv : TEXCOORD0;
				float4 vertex : SV_POSITION;
			};

			v2f vert (appdata v)
			{
				v2f o;
				o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
				o.uv = v.uv;
				o.uv.y = 1-o.uv.y;
				return o;
			}

			//ANIMATION
			fixed4 frag (v2f i) : SV_Target
			{
				float2 r = 2.0 * (i.uv - 0.5);
				float aspectRatio = _ScreenParams.x / _ScreenParams.y;
				r.x *= aspectRatio;

				fixed3 bgCol = float3(1.0, 1.0, 1.0); // white
		
				fixed3 col1 = float3(0.216, 0.471, 0.698); // blue
				fixed3 col2 = float3(1.00, 0.329, 0.298); // red
				fixed3 col3 = float3(0.867, 0.910, 0.247); // yellow

				fixed3 ret;
				ret = bgCol;

				float angle = -0.6;
				float2x2 rotationMatrix = float2x2(cos(angle), -sin(angle),
												sin(angle), cos(angle));

				
				if(i.uv.x < 1.0/5.0) // part1
				{
					float2 q = r + float2(aspectRatio*4.0/5.0, 0);

					ret = fixed3(0.3, 0.3, 0.3);
					//時間は_Time.yで取得できる
					float y = _Time.y;

					//yを-1 ~ 1の値にする
					y = mod(y,2.0) -1.0;
					ret = lerp(ret, col1, disk(q, float2(0.0, y), 0.1));
				}
				else if(i.uv.x < 2.0/5.0) //part2
				{
					float2 q = r + float2(aspectRatio*2.0/5.0, 0);
					ret = fixed3(0.4, 0.4, 0.4);
					//振幅
					float amplitude = 0.8;
					float y = 0.8 * sin(0.5*_Time.y* 2.0 * PI);
					float radius = 0.15 + 0.05 * sin(_Time.y * 8.0);
					ret = lerp(ret, col1, disk(q, float2(0.0, y), radius));
				}
				else if(i.uv.x < 3.0/5.0) //part3
				{
					float2 q = r + float2(aspectRatio*0/5.0, 0);
					ret = float3(0.5, 0.5, 0.5);

					float x = 0.2*cos(_Time.y*5.0);
					float y = 0.3*sin(_Time.y*5.0);
					float radius = 0.2 + 0.1*sin(_Time.y*2.0);
					fixed3 color = lerp(col1, col2, sin(_Time.y)*0.5 + 0.5);
					ret = lerp(ret, color, rectangle(q, float2(x-0.1, y-0.1), float2(x+0.1, y+0.1)));
				}
				else if(i.uv.x < 4.0/5.0) //part4
				{
					float2 q = r + float2(-aspectRatio*2.0/5.0, 0);
					ret = float3(0.4, 0.4, 0.4);

					for(float i=-1.0; i<1.0; i+= 0.2)
					{
						float x = 0.2 * cos(_Time.y*5.0 + i*PI);
						float y = i;

						float2 s = q - float2(x, y);
						float angle = _Time.y * 3.0 + i;
						float2x2 rot = float2x2(cos(angle), -sin(angle),
												sin(angle),  cos(angle));
						s = mul(rot, s);
						ret = lerp(ret, col1, rectangle(s, float2(-0.06, -0.06), float2(0.06, 0.06)));
					}
				}
				else if(i.uv.x < 5.0/5.0) //part5
				{
					float2 q = r + float2(-aspectRatio*4.0/5.0, 0);
					ret = float3(0.3, 0.3, 0.3);

					float speed = 2.0;
					float t = _Time.y * speed;
					float stopEveryAngle = PI / 2.0;
					float stopRatio = 0.5;
					//0.5<frac(t)<1の時,t1は一定となる。そこで止まっている。
					float t1 = (floor(t) + smoothstep(0.0, 1.0 - stopRatio, frac(t)))*stopEveryAngle;

					float x = -0.2*cos(t1);
					float y = 0.3 * sin(t1);
					float dx = 0.1 + 0.03 * sin(t*10.0);
					float dy = 0.1 + 0.03 * sin(t*10.0+PI);
					ret = lerp(ret, col1, rectangle(q, float2(x-dx, y-dy), float2(x+dx, y+dy)));

				
				}


				fixed3 pixel = ret;
				return fixed4(pixel, 1.0);
			}


			ENDCG
		}
	}
}

```

> ## Point
_Time.yで時間を取得できる．


# Tutorial21 Plasma

![result_tutorial21.PNG](https://qiita-image-store.s3.amazonaws.com/0/113504/eed86669-60f2-44c2-0628-9daad72ed081.png "result_tutorial21.PNG")


```Tutorial21.shader
//Plasma
fixed4 frag (v2f i) : SV_Target
{
	float2 r = 2.0 * (i.uv - 0.5);
	float aspectRatio = _ScreenParams.x / _ScreenParams.y;
	r.x *= aspectRatio;
	float t = _Time.y;
	r = r*8.0;

	float v1 = sin(r.x + t);
	float v2 = sin(r.y + t);
	float v3 = sin(r.x + r.y + t);
	float v4 = sin(sqrt(r.x*r.x + r.y*r.y) + 1.7*t);
	float v = v1 + v2 + v3 + v4;
	fixed3 ret;

	if(i.uv.x < 1.0 / 10.0) // part1
	{
		//vertical waves
		ret = float3(v1, v1, v1);
	}
	else if(i.uv.x < 2.0/10.0) // part2
	{
		// horizontal waves;
		ret = float3(v2, v2, v2);
	}
	else if(i.uv.x < 3.0/10.0) // part3
	{
		// diagonal waves
		ret = float3(v3, v3, v3);
	}
	else if(i.uv.x < 4.0/10.0) // part4
	{
		// circular waves
		ret = float3(v4, v4, v4);
	}
	else if(i.uv.x < 5.0/10.0) // part5
	{
		// the sum of all waves
		ret = float3(v, v, v);
	}
	else if(i.uv.x < 6.0/10.0) // part6
	{
		// Add periodicity to the gradients
		ret = float3(sin(2.0 * v), sin(2.0 * v), sin(2.0 * v));
	}
	else if(i.uv.x < 10.0/10.0) // part7
	{
		// mix colors
		v *= 1.0;
		ret = float3(sin(v), sin(v+0.5*PI), sin(v+1.0*PI));
	}

	ret = 0.5 + 0.5 * ret;

	fixed3 pixel = ret;
	return fixed4(pixel, 1.0);
}
```

> ## Point
sin,cosと_Time.yを組み合わせると周期的な模様ができる．