イラスト、モデリング、Unity、VR関連

unityとかblenderとかvr関連の作業メモ

shader TexBugシェーダ、vertex ver

ParinNoise

#include "UnityCG.cginc"

float4 permute(float4 x){
    return fmod(34.0 * pow(x, 2) + x, 289.0);
}

float2 fade(float2 t){
    return 6.0 * pow(t, 5.0) - 15.0 * pow(t, 4.0) + 10.0 * pow(t, 3.0);
}

float4 taylorInvSqrt(float4 r) {
    return 1.79284291400159 - 0.85373472095314 * r;
}

#define DIV_289 0.0034602076124567474048442906

float mod289(float x) {
  return x - floor(x * DIV_289) * 289.0;
}

float PerlinNoise2D(float2 P){

      float4 Pi = floor(P.xyxy) + float4(0.0, 0.0, 1.0, 1.0);
      float4 Pf = frac (P.xyxy) - float4(0.0, 0.0, 1.0,1.0);
      float4 ix = Pi.xzxz;
      float4 iy = Pi.yyww;
      float4 fx = Pf.xzxz;
      float4 fy = Pf.yyww;
      float4 i = permute(permute(ix) + iy);
      float4 gx = frac(i / 41.0) * 2.0 - 1.0 ;
      float4 gy = abs(gx) - 0.5 ;
      float4 tx = floor(gx + 0.5);
      gx = gx - tx;
      float2 g00 = float2(gx.x,gy.x);
      float2 g10 = float2(gx.y,gy.y);
      float2 g01 = float2(gx.z,gy.z);
      float2 g11 = float2(gx.w,gy.w);
      float4 norm = taylorInvSqrt(float4(dot(g00, g00), dot(g01, g01), dot(g10, g10), dot(g11, g11)));
      g00 *= norm.x;
      g01 *= norm.y;
      g10 *= norm.z;

      float n00 = dot(g00, float2(fx.x, fy.x));
      float n10 = dot(g10, float2(fx.y, fy.y));
      float n01 = dot(g01, float2(fx.z, fy.z));
      float n11 = dot(g11, float2(fx.w, fy.w));
      float2 fade_xy = fade(Pf.xy);
      float2 n_x = lerp(float2(n00, n01), float2(n10, n11), fade_xy.x);
      float n_xy = lerp(n_x.x, n_x.y, fade_xy.y);
      return 2.3 * n_xy;
}

float GetNoise(float2 xy,float scroll,float size){
    xy *= size;
    xy += float2(scroll,1);
    float ns = PerlinNoise2D(xy) / 2 + 0.5f;
    return ns;
}
Shader "Custom/TexBug" {
	Properties{
		_MainTex("MainTex",2D) = "white"{}
		_Height("Height",float) = 1.8//アバターの足裏をゼロとした場合の頭頂部の位置、つまり身長
		_Width("Width",float) = 0.3//アバターの中心からの横幅
		_Digit("Digit",Range(1,10)) = 1
		_ChangeFrec("ChangeFrec",Range(1,500)) = 1 //バグ発生個所の変更頻度
		_MaxBoxSize("MaxBoxSize",Range(0,0.1)) = 0.1
		_MaxNoiseLen("MaxNoiseLen",Range(0,0.5)) = 0.5
		_BugLoop("BugLoop",Range(1,50)) = 30
		_BugLineColor("BugLineColor",Color) = (1,0,0,1)
		_BugLineWidth("BugLineWidth",Range(0,0.01)) = 0.01
		_BugSpd("BugSpd",Range(1,10)) = 3
		_BugNum("BugNum",Range(1,20)) = 2
	}

	SubShader{
		Tags{"RenderType"="Opaque" "DisableBatching"="true"}
		//透明部分のあるテクスチャを使う場合
		//Tags{"Queue" = "Transparent" "RenderType" = "Transparent"}
		//Blend SrcAlpha OneMinusSrcAlpha
		Lighting Off
		Pass{
			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag
			#include "UnityCG.cginc"
			#include "ParinNoise.cginc"
			struct appdata {
				float4 vertex:POSITION;
				float4 uv:TEXCOORD0;
			};

			struct v2f {
				float4 pos:SV_POSITION;
				float4 uv:TEXCOORD0;
				float type:TEXCOORD1;
			};

			float _PI = 3.141592;
			sampler2D _MainTex;
			float _Height;
			float _Width;
			float _Digit;
			float _ChangeFrec;
			float _MaxBoxSize;
			float _MaxNoiseLen;
			float _BugLoop;
			float4 _BugLineColor;
			float _BugLineWidth;
			float _BugSpd;
			float _BugNum;
			//0~1を返す
			float rand(float2 co){
				return frac(sin(dot(co.xy ,float2(12.9898,78.233))) * 43758.5453);
			}

			float noise(float2 xy){
					return frac(sin(dot(xy, float2(1000, 1000))) * 2000);
			}

			float NormalizeX(float x){
				return x/_Width;
			}
			//-1~1に
			float NormalizeY(float y){
				return y/_Height;
			}

			float Pow(float val,int times){
				float res = 1;
				for(int k=0;k<times;k++){
					res *= val;
				}
				return res;
			}
			float GetNumByTime(float digit,float change_frec){
				int d = trunc(digit);
				float tm = _Time.y/change_frec*Pow(10,d);
				float mx = trunc(tm);//小数部3桁を整数部に移動
				return frac(mx/10000);//整数部5桁を小数部に移動しそれのみxに代入
			}

			//-1~1の値を取る
			float2 BugCenterPos(float av){
				float x = rand(GetNumByTime(_Digit,_ChangeFrec)+av);
				float y = rand(float2(x,x));
				x = (x - 0.5)*2;
				y = (y - 0.5)*2;
				//return float2(0,0);
				return float2(x,y);
			}

			//箱の距離関数
			float rectangle(float2 p, float2 size){
				return max(abs(p.x) - size.x/_Width, abs(p.y) - size.y/_Height);
			}

			float4 BugBoxFrame(float4 c,float2 p,float ActBoxSizeX,float ActBoxSizeY){
				float leng = rectangle(p,float2(ActBoxSizeX+_BugLineWidth,ActBoxSizeY+_BugLineWidth));
				return lerp(c,_BugLineColor,step(leng,0.001));
			}

			float4 BugBoxCont(float4 c,float2 p,float ActBoxSizeX,float ActBoxSizeY){
				float leng = rectangle(p,float2(ActBoxSizeX,ActBoxSizeY));
				return lerp(c,float4(0,0,0,0),step(leng,0.001));
			}

			v2f vert(appdata v){
				v2f o = (v2f)0;
				o.pos = UnityObjectToClipPos(v.vertex);
				o.uv = v.uv;
				float nx = NormalizeX(v.vertex.x);
				float ny = NormalizeY(v.vertex.y);
				for(int j=0;j<_BugNum;j++){
					float2 o_cpos = BugCenterPos(rand(j));
					float time = GetNumByTime(_Digit,_ChangeFrec/_BugSpd);
					//unroll内の数値は_BugLoopに合わせて置き換える
					//ループ展開するだけのはずだが結果が変わる場合がある
					//[unroll(10)]
					for(int k=0;k<_BugLoop;k++){
						float2 cpos = o_cpos;
						uint f = k - k % 2;
						//中心となる位置から少しずらしたランダムなBoxの位置
						cpos.x = o_cpos.x + (noise(float2(rand(f+0.1+time),rand(f+0.2+time)))-0.5)*2*_MaxNoiseLen/_Width;
						cpos.y = o_cpos.y + (noise(float2(rand(f+0.3+time),rand(f+0.4+time)))-0.5)*2*_MaxNoiseLen/_Height;
						//_MaxBoxSizeを最大値としたランダムな数
						float mx = rand(f+0.5+time)*_MaxBoxSize;
						float ActBoxSizeX = _MaxBoxSize - mx;
						//_MaxBoxSizeを最大値としたランダムな数
						float my = rand(f+0.7+time)*_MaxBoxSize;
						float ActBoxSizeY = _MaxBoxSize - my;
						float2 p = float2(cpos.x-nx,cpos.y-ny);

						if(rectangle(p,float2(ActBoxSizeX,ActBoxSizeY))<0.00001){
							o.type = 1;//clip(-1)
							return o;
						}
						if(rectangle(p,float2(ActBoxSizeX+_BugLineWidth,ActBoxSizeY+_BugLineWidth))<0.00001){
							o.type = 2;//BugLineColor
							return o;
						}
					}
				}
				o.type = 0;//DefaultTex
				return o;
			}

			float4 frag(v2f i) :SV_Target {
				if(i.type >=0 && i.type < 0.66) return tex2D(_MainTex,i.uv);
				if(i.type >=0.66 && i.type < 1.32) clip(-1);
				if(i.type >=1.32 && i.type <=2 ) _BugLineColor;
				return float4(0,0,1,1);
			}
			ENDCG
		}//Pass
	}//SubShader
	//FallBack "Diffuse"
}