Perlin noise shader

追記：[こんないいもの](https://github.com/keijiro/NoiseShader)がありました。
やっぱりkeijiroさんだ！

***

[periln noise](http://mrl.nyu.edu/~perlin/noise/) をそのままシェーダーに移植しました。

```hlsl:PerlinNoise.shader
Shader "Unlit/PerlinNoise"
{
	Properties
	{
		_MainTex ("Texture", 2D) = "white" {}
		_Color ("Main Color", Color) = (1,1,1,1)
		_BaseColor ("Base Color", Color) = (0,0,0,1)
		_Scale ("Scale", Vector) = (10,10,10,0)
	}
	SubShader
	{
		Tags { "RenderType"="Opaque" }
		LOD 100

		Pass
		{
			CGPROGRAM
// Upgrade NOTE: excluded shader from DX11, Xbox360, OpenGL ES 2.0 because it uses unsized arrays
#pragma exclude_renderers d3d11 xbox360 gles
			#pragma vertex vert
			#pragma fragment frag
			// make fog work
			#pragma multi_compile_fog
			
			#include "UnityCG.cginc"

			static int p[] = {
			   151,160,137,91,90,15,
			   131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,23,
			   190, 6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33,
			   88,237,149,56,87,174,20,125,136,171,168, 68,175,74,165,71,134,139,48,27,166,
			   77,146,158,231,83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244,
			   102,143,54, 65,25,63,161, 1,216,80,73,209,76,132,187,208, 89,18,169,200,196,
			   135,130,116,188,159,86,164,100,109,198,173,186, 3,64,52,217,226,250,124,123,
			   5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42,
			   223,183,170,213,119,248,152, 2,44,154,163, 70,221,153,101,155,167, 43,172,9,
			   129,22,39,253, 19,98,108,110,79,113,224,232,178,185, 112,104,218,246,97,228,
			   251,34,242,193,238,210,144,12,191,179,162,241, 81,51,145,235,249,14,239,107,
			   49,192,214, 31,181,199,106,157,184, 84,204,176,115,121,50,45,127, 4,150,254,
			   138,236,205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180,
			};

			float fade(float t) { return t * t * t * (t * (t * 6.0 - 15.0) + 10.0); }
   			float lerp(float t, float a, float b) { return a + t * (b - a); }
   			float4 lerp(float t, float4 a, float4 b) { return a + t * (b-a); }
		    float grad(int hash, float x, float y, float z) {
		      int h = hash & 15;                      // CONVERT LO 4 BITS OF HASH CODE
		      float u = h<8 ? x : y,                 // INTO 12 GRADIENT DIRECTIONS.
		             v = h<4 ? y : h==12||h==14 ? x : z;
		      return ((h&1) == 0 ? u : -u) + ((h&2) == 0 ? v : -v);
		    }
 
			float noise(float x, float y, float z) {
			  int X = (int)floor(x) & 255,                  // FIND UNIT CUBE THAT
			      Y = (int)floor(y) & 255,                  // CONTAINS POINT.
			      Z = (int)floor(z) & 255;
			  x -= floor(x);                                // FIND RELATIVE X,Y,Z
			  y -= floor(y);                                // OF POINT IN CUBE.
			  z -= floor(z);
			  float u = fade(x),                                // COMPUTE FADE CURVES
			         v = fade(y),                                // FOR EACH OF X,Y,Z.
			         w = fade(z);
			  int A = p[X  %256]+Y, AA = p[A%256]+Z, AB = p[(A+1)%256]+Z,      // HASH COORDINATES OF
			      B = p[(X+1)%256]+Y, BA = p[B%256]+Z, BB = p[(B+1)%256]+Z;      // THE 8 CUBE CORNERS,

			  return lerp(w, lerp(v, lerp(u, grad(p[AA  %256], x  , y  , z   ),  // AND ADD
			                                 grad(p[BA  %256], x-1, y  , z   )), // BLENDED
			                         lerp(u, grad(p[AB  %256], x  , y-1, z   ),  // RESULTS
			                                 grad(p[BB  %256], x-1, y-1, z   ))),// FROM  8
			                 lerp(v, lerp(u, grad(p[(AA+1)%256], x  , y  , z-1 ),  // CORNERS
			                                 grad(p[(BA+1)%256], x-1, y  , z-1 )), // OF CUBE
			                         lerp(u, grad(p[(AB+1)%256], x  , y-1, z-1 ),
			                                 grad(p[(BB+1)%256], x-1, y-1, z-1 ))));
			}

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

			struct v2f
			{
				float2 uv : TEXCOORD0;
				UNITY_FOG_COORDS(1)
				float4 vertex : SV_POSITION;
			};

			sampler2D _MainTex;
			float4 _MainTex_ST;
			float4 _Color;
			float4 _BaseColor;
			float4 _Scale;
			
			v2f vert (appdata v)
			{
				v2f o;
				o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
				o.uv = TRANSFORM_TEX(v.uv, _MainTex);
				UNITY_TRANSFER_FOG(o,o.vertex);
				return o;
			}
			
			fixed4 frag (v2f i) : SV_Target
			{
				// sample the texture
				float3 ixyz = float3(i.uv*_Scale.xy,_Scale.z);
				fixed4 col = tex2D(_MainTex, i.uv) * lerp(noise(ixyz.x,ixyz.y,ixyz.z),_BaseColor,_Color);
				// apply fog
				UNITY_APPLY_FOG(i.fogCoord, col);
				return col;
			}

			ENDCG
		}
	}
}
```

![スクリーンショット 2016-03-17 23.09.11.png](https://qiita-image-store.s3.amazonaws.com/0/59911/66dfa81a-6893-168f-4230-add30790fdc7.png)

`float3 ixyz = float3(i.uv*_Scale.xy,_Scale.z);`
を
`float3 ixyz = float3(i.uv*_Scale.xy,_Scale.z*(_SinTime.x*0.5+0.5));`
に変更するとリアルタイムに動きます。

static int[256] とか、コンテキストスイッチ的にも実用性があるのかどうか疑問ですがどうなんでしょう？

ステンドグラステクスチャに適用するといい感じですね。

![スクリーンショット 2016-03-19 0.39.34.png](https://qiita-image-store.s3.amazonaws.com/0/59911/05d4a039-5eb1-b847-e06c-b15c7e1822ab.png)
![スクリーンショット 2016-03-19 0.40.08.png](https://qiita-image-store.s3.amazonaws.com/0/59911/c6eac1c5-b9f3-5385-e58c-c5686ea83a3e.png)