﻿Shader "Onisawa/OnisawaKirieShader" {
	Properties 
	{
		[Header(Position)]
		[Space(10)]
		_Distance ("Distance", Range(0.01, 1.0)) = 0.1
		_Depth    ("Depth", Range(0.0, 1.0)) = 0.05

		[Header(Wall color)]
		[Space(10)]
		_WallColorU ("Upper", Color) = (1, 1, 1, 1)
		_WallColorD ("Lower", Color) = (1, 1, 1, 1)
		_WallColorL ("Left", Color) = (1, 1, 1, 1)
		_WallColorR ("Right", Color) = (1, 1, 1, 1)

		[Header(Texture)]
		[Space(10)]
		_LayerNum ("Layer Number", Int) = 5
		[NoScaleOffset] _Texture0 ("Layer1", 2D) = "white"
		[NoScaleOffset] _Texture1 ("Layer2", 2D) = "white"
		[NoScaleOffset] _Texture2 ("Layer3", 2D) = "white"
		[NoScaleOffset] _Texture3 ("Layer4", 2D) = "white"
		[NoScaleOffset] _Texture4 ("Layer5", 2D) = "white"
		[NoScaleOffset] _Texture5 ("Layer6", 2D) = "white"
		[NoScaleOffset] _Texture6 ("Layer7", 2D) = "white"
		[NoScaleOffset] _Texture7 ("Layer8", 2D) = "white"
		[NoScaleOffset] _Texture8 ("Layer9", 2D) = "white"
		[NoScaleOffset] _Texture9 ("Layer10", 2D) = "white"
	}

	CGINCLUDE
	#include "UnityCG.cginc"

	// シェーダー上の最大レイヤー数
	#define LAYER_NUM_MAX (10)
	
	// シェーダープロパティ
	float _Distance;		// レイヤー間の幅
	float _Depth;			// レイヤー1の位置(奥行き方向)
	int _LayerNum;			// レイヤー数(使用するテクスチャ数)
	sampler2D _Texture0;	// 使用テクスチャ
	sampler2D _Texture1;	// 使用テクスチャ
	sampler2D _Texture2;	// 使用テクスチャ
	sampler2D _Texture3;	// 使用テクスチャ
	sampler2D _Texture4;	// 使用テクスチャ
	sampler2D _Texture5;	// 使用テクスチャ
	sampler2D _Texture6;	// 使用テクスチャ
	sampler2D _Texture7;	// 使用テクスチャ
	sampler2D _Texture8;	// 使用テクスチャ
	sampler2D _Texture9;	// 使用テクスチャ

	fixed4 _WallColorU;
	fixed4 _WallColorD;
	fixed4 _WallColorL;
	fixed4 _WallColorR;

	struct v2f
	{
		float4 pos : SV_POSITION;
		float3 normal : TEXCOORD0;
		float3 viewPos : TEXCOORD1;
		float3 objectViewDir : TEXCOORD2;
		float3 objectPos : TEXCOORD3;
	};

	v2f vert(appdata_base i)
	{
		v2f o;
		o.viewPos = UnityObjectToViewPos(i.vertex);
		o.pos = mul(UNITY_MATRIX_P, float4(o.viewPos, 1.0));
		o.normal = i.normal;

		// カメラから頂点位置への方向を求める（オブジェクト空間）
		o.objectViewDir = -ObjSpaceViewDir(i.vertex);
		o.objectPos = i.vertex;
			
		return o;
	}

	float GetCollideDistance(float3 rayPos, float3 rayDir, float3 planePos, float3 planeNormal)
	{
		return dot(planePos - rayPos, planeNormal) / dot(rayDir, planeNormal);
	}

	half4 frag(v2f i) : SV_TARGET
	{
		float3 rayDir = normalize(i.objectViewDir);
		float3 rayPos = i.objectPos + rayDir * 0.0001;
		float3 planePos = float3(0, 0, 0);
		float3 planeNormal = float3(0, 0, 0);
		float  collideDistance = 999;	// 壁との衝突位置
		float3 color = float3(0,0,0);
		fixed4 wall_color = fixed4(0,0,0,0);

		const float3 UpVec = float3(0, 1, 0);
		const float3 DownVec = float3(0, -1, 0);
		const float3 RightVec = float3(1, 0, 0);
		const float3 FrontVec = float3(0, 0, 1);

		// 天井と床
		{
			float which = step(0.0, dot(rayDir, UpVec));
			planeNormal = float3(0, lerp(1, -1, which), 0);
			planePos.xyz = 0.0;
			planePos.y -= lerp(0.5, -0.5, which);

			float distance = GetCollideDistance(rayPos, rayDir, planePos, planeNormal);
			if (distance < collideDistance)
			{
				collideDistance = distance;
				if(planeNormal[1] > 0)
				{
					color = _WallColorD;
				}
				else
				{
					color = _WallColorU;
				}
			}
		}

		// 左右の壁
		{
			float which = step(0.0, dot(rayDir, RightVec));
			planeNormal = float3(lerp(1, -1, which), 0, 0);
			planePos.xyz = 0.0;
			planePos.x -= lerp(0.5, -0.5, which);

			float distance = GetCollideDistance(rayPos, rayDir, planePos, planeNormal);
			if (distance < collideDistance)
			{
				collideDistance = distance;
				if(planeNormal[0] > 0)
				{
					color = _WallColorL;
				}
				else
				{
					color = _WallColorR;
				}
			}
		}

		// レイヤー数最大値の制限
		int LayerNum = _LayerNum;
		if(LayerNum > LAYER_NUM_MAX) 
		{
			LayerNum = LAYER_NUM_MAX;
		}

		// 画像の描画
		for(int index = LayerNum-1; index>=0; index--)
		{
			// 奥の壁1枚目
			float which = step(0.0, dot(rayDir, FrontVec));
			planeNormal = float3(0, 0, lerp(1, -1, which));
			planePos.xyz = 0.0;
			planePos.z -= 0.5 - _Depth - _Distance * index;
			planePos.z -= lerp(0.5, -0.5, which);

			float distance = GetCollideDistance(rayPos, rayDir, planePos, planeNormal);
			if (distance < collideDistance)
			{

				collideDistance = distance;
				float3 pos = rayPos + rayDir * distance + 0.5;
				float3 uvw = pos.xyz;

				switch(index)
				{
				case 0:
					wall_color = tex2D(_Texture0, uvw.xy);
					break;
				case 1:
					wall_color = tex2D(_Texture1, uvw.xy);
					break;
				case 2:
					wall_color = tex2D(_Texture2, uvw.xy);
					break;
				case 3:
					wall_color = tex2D(_Texture3, uvw.xy);
					break;
				case 4:
					wall_color = tex2D(_Texture4, uvw.xy);
					break;
				case 5:
					wall_color = tex2D(_Texture5, uvw.xy);
					break;
				case 6:
					wall_color = tex2D(_Texture6, uvw.xy);
					break;
				case 7:
					wall_color = tex2D(_Texture7, uvw.xy);
					break;
				case 8:
					wall_color = tex2D(_Texture8, uvw.xy);
					break;
				case 9:
					wall_color = tex2D(_Texture9, uvw.xy);
					break;

				default:
					wall_color = float4(1.0, 0.0, 0.0, 1.0);
					break;
				}

				color = wall_color.rgb * wall_color.a + color * (1-wall_color.a);
			}
		}

		return half4(color, 1);
	}
	ENDCG

	
	SubShader 
	{
		Tags
		{
			"RenderType"="Opaque"
		}
		
		Pass
		{
			CGPROGRAM
			#pragma target 3.5
			#pragma vertex vert
			#pragma fragment frag
			ENDCG
		}
	}
}
