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

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

shader テクスチャバグ的なもの

 

 

Shader "Custom/TexBugSquare" {
	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,10)) = 10 //バグ発生個所の変更頻度
		_BugSpd("BugSpd",Range(1,10)) = 3
		_MaxBugBoxSize("MaxBugBoxSize",Range(0,0.1)) = 0.05
		_MaxNoiseLen("MaxNoiseLen",Range(0,0.5)) = 0.1
		_BugMacroNum("BugMacroNum",Range(1,10)) = 10
		_BugMicroNum("BugMicroNum",Range(1,50)) = 5
		_BugLineColor("BugLineColor",Color) = (1,0,0,1)
		_BugColor("BugColor",Color) = (0,0,0,1)
		_BugColor2("BugColor2",Color) = (0,0,0,1)
		_BugColor3("BugColor3",Color) = (0,0,0,1)
		_BugColor4("BugColor4",Color) = (0,0,0,1)
		_BugLineWidth("BugLineWidth",Range(0,0.01)) = 0.01
		_ObjBoxScale("ObjBoxScale",Float) = 1 //Boxオブジェクト前提

	}

	SubShader{
		//透明部分のあるテクスチャを使う場合
		Tags{"Queue" = "Transparent" "RenderType" = "Transparent" "DisableBatching"="true"}
		Blend SrcAlpha OneMinusSrcAlpha
		GrabPass { "_GPT" }
		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;
				float4 lpos:TEXCOORD1;
				float4 gpos:POSITION1;
			};

			float _PI = 3.141592;
			sampler2D _MainTex;
			float _Height;
			float _Width;
			float _Digit;
			float _ChangeFrec;
			float _MaxBugBoxSize;
			float _MaxNoiseLen;
			int _BugMicroNum;
			float4 _BugLineColor;
			float _BugLineWidth;
			float _BugSpd;
			float _BugMacroNum;
			float4 _BugColor;
			float4 _BugColor2;
			float4 _BugColor3;
			float4 _BugColor4;
			float _ObjBoxScale;
			sampler2D _GPT;


			//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に代入
			}

			//scaleのxyzが同一,ローカル座標の原点(0,0,0)のBox前提
			void MaxScreenPos(out float3 mm[2]){
				float val = 0.5 * _ObjBoxScale;
				float4 ary[8];
				ary[0] = UnityObjectToClipPos(float4(val,-val,val,1));
				ary[1] = UnityObjectToClipPos(float4(val,val,val,1));
				ary[2] = UnityObjectToClipPos(float4(val,val,-val,1));
				ary[3] = UnityObjectToClipPos(float4(val,-val,-val,1));
				ary[4] = UnityObjectToClipPos(float4(-val,val,val,1));
				ary[5] = UnityObjectToClipPos(float4(-val,-val,val,1));
				ary[6] = UnityObjectToClipPos(float4(-val,val,-val,1));
				ary[7] = UnityObjectToClipPos(float4(-val,-val,-val,1));
				float4 gpos_ary[8];
				mm[0] = ComputeGrabScreenPos(ary[0]);
				mm[1] = mm[0];
				[unroll(8)]
				for(int k=0;k<8;k++){
					float3 t = ComputeGrabScreenPos(ary[k]);
					//最大、最小のxyzを見つける
					if(t.x < mm[0].x) mm[0].x = t.x;
					if(t.y < mm[0].y) mm[0].y = t.y;
					if(t.z < mm[0].z) mm[0].z = t.z;
					if(t.x > mm[1].x) mm[1].x = t.x;
					if(t.y > mm[1].y) mm[1].y = t.y;
					if(t.z > mm[1].z) mm[1].z = t.z;
				}
			}

			float2 BugCenterPos(float av){
				float rateX = rand(GetNumByTime(_Digit,_ChangeFrec)+av);
				float rateY = rand(float2(rateX,rateX));
				float3 min_max[2];
				MaxScreenPos(min_max);
				float x_width = min_max[1].x - min_max[0].x;
				float y_width = min_max[1].y - min_max[0].y;
				return float2(min_max[0].x+x_width*rateX, min_max[0].y+y_width*rateY);
			}

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

			float4 GetRandColor(float pram){
				float time = GetNumByTime(_Digit,_ChangeFrec/_BugSpd);
				int k = trunc(rand(float2(time,pram))*10)%4;
				float4 colors[4] = {_BugColor,_BugColor2,_BugColor3,_BugColor4};
				return colors[k];
			}

			float GetLengthFromCamera(){
				float3 c = _WorldSpaceCameraPos;
				float3 cu = mul(unity_ObjectToWorld,float4(0,0,0,1));
				return length(cu-c);
			}

			float GetAspect(){
				float4 projectionSpaceUpperRight = float4(1, 1, UNITY_NEAR_CLIP_VALUE, _ProjectionParams.y);
				float4 viewSpaceUpperRight = mul(unity_CameraInvProjection, projectionSpaceUpperRight);
				return viewSpaceUpperRight.x / viewSpaceUpperRight.y;
			}


			v2f vert(appdata v){
				v2f o;
				o.lpos = v.vertex;
				o.pos = UnityObjectToClipPos(v.vertex);
				o.gpos = ComputeGrabScreenPos(o.pos);
				o.uv = v.uv;
				return o;
			}

			float4 frag(v2f i) :SV_Target {
				float nx = i.gpos.x;
				float ny = i.gpos.y;
				int BN = trunc(_BugMacroNum);
				for(int j=0;j<trunc(BN);j++){
					float2 o_cpos = BugCenterPos(rand(j));
					float time = GetNumByTime(_Digit,_ChangeFrec/_BugSpd);
					//[unroll(30)]//unroll内の数値は_BugMicroNumに合わせて置き換える
					float aspect = GetAspect();
					for(int k=0;k<_BugMicroNum;k++){
						float2 cpos = o_cpos;
						int f = k - k % 2;
						//テクスチャバグの四角形の中心
						cpos.x = o_cpos.x + (noise(float2(rand(f+0.1+time),rand(f+0.2+time)))-0.5)*2*_MaxNoiseLen;
						cpos.y = o_cpos.y + (noise(float2(rand(f+0.3+time),rand(f+0.4+time)))-0.5)*2*_MaxNoiseLen*aspect;
						float mx =  abs(rand(f+0.5+time) - rand(f+0.6+time))*_MaxBugBoxSize;
						//カメラの距離に比例してBoxSizeを縮小
						float ActBoxSizeX = _MaxBugBoxSize - mx;
						//float ActBoxSizeX = _MaxBugBoxSize;
						float my = abs(rand(f+0.7+time) - rand(f+0.8+time))*_MaxBugBoxSize;
						float ActBoxSizeY = (_MaxBugBoxSize - my) * aspect;
						//float ActBoxSizeY = _MaxBugBoxSize* aspect;
						float2 p = float2(cpos.x-nx,cpos.y-ny);
						float leng;
						leng = rectangle(p,float2(ActBoxSizeX,ActBoxSizeY));
						if(leng<0.00001) return GetRandColor(rand(float2(k,j)));
						//leng = rectangle(p,float2(ActBoxSizeX+_BugLineWidth,ActBoxSizeY+_BugLineWidth));
						//if(leng<0.00001) return _BugLineColor;
					}
				}
				//return tex2D(_MainTex,i.uv);
				clip(-1);
				return float4(0,0,0,1);
			}
			ENDCG
		}//Pass
	}//SubShader
	FallBack "Diffuse"
}   

ParinNoise.cginc

#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;
}