Shader "URP/Environment/Sky&Fog/Clouds 2D" 
{
	Properties 
	{
		[Header(Lighting)]
		[Enum(Sky Color,0,Equator Color,1)] _AmbientSource ("Ambient Source", int) = 1
		_Attenuation ("Attenuation", Range(0,5)) = 0.6
		_StepSize ("Step size", Range(0.001,0.02)) = 0.004
		_AlphaSaturation("Alpha saturation", Range(1,10)) = 2.0
		_LightColorMultiplier ("Light Color multiplier", Range(0,10)) = 4
		_SkyColorMultiplier("Sky Color multiplier", Range(0,10)) = 1.5
		_Mask ("Clouds density", Range (0,4)) = 1.0
		_ScatterMultiplier("Scatter multiplier", Range (0,10)) = 1.0
    	
		[Header(Texture)]
		[Enum(Rectangular,0,Polar,1)] _Mapping ("Mapping mode", int) = 0	
		_CloudSampler ("Clouds Texture (R)", 2D) = "white" {}
	
		[Header(Animation)]
		// Range 0 ~ 360 for non-animated Rotation
		_RotateSpeed("Rotate speed", Range (-1,1)) = 0.0
		_RotateAngle("Rotate Angle", Range(-1,1)) = 0.0

		[Header(Others)]
		_HeightOffset("Height Offset", float) = 0.0
    
	}
	SubShader 
	{
		
		HLSLINCLUDE
		#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
		#include "AtmosphericScattering/AtmosphereFunctions.hlsl"
		#include "VolumetricFogForObject.hlsl"

			TEXTURE2D(_CloudSampler);	SAMPLER(sampler_CloudSampler);
		//UNITY_DECLARE_TEX2D (_CloudSampler);
		CBUFFER_START(UnityPerMaterial)

		float4 _CloudSampler_ST;
		float4 _Color;

		float _RotateAngle;

		//uniform float3	_MoonDirSize, _uSkyLightColor, _NightZenithColor;
		uniform float	_RotateSpeed, _LightColorMultiplier;
		uniform half	_Attenuation, _StepSize, _AlphaSaturation, _Mask, _ScatterMultiplier;
		uniform int		_Mapping;
		uniform float	_HeightOffset;
		uniform half4	_CloudAmbient;
		CBUFFER_END

		struct appdata_t {
			float4	vertex		: POSITION;
			float4	tangent		: TANGENT;
			float3	normal		: NORMAL;
			float2  rectangular	: TEXCOORD0; // uv0
			float2  polar		: TEXCOORD1; // uv2
		};

		struct v2f {
			float4	pos 		: SV_POSITION;
			float2	baseTC		: TEXCOORD0;
			float2	toSun		: TEXCOORD1;
			half3	skyColor	: TEXCOORD2;
			half3	lightColor	: TEXCOORD3;
			half3	worldPos	: TEXCOORD4;
			half3	lightDir	: TEXCOORD5;
			half3	miePhase_g	: TEXCOORD6;
			float4 fogCoord		: TEXCOORD7;
		};

		float3 RotateAroundYInDegrees(float3 vertex, float degrees)
		{
			float alpha = degrees * (PI / 180.0);
			float sina, cosa;
			sincos(alpha, sina, cosa);
			float2x2 m = float2x2(cosa, -sina, sina, cosa);
			return float3(mul(m, vertex.xz), vertex.y).xzy;
		}

		half3 PhaseFunctionG(half g)
		{
			// Mie phase G function and Mie scattering scale, (compute this function in Vertex program)
			float g2 = g * g;
			return float3(1.5 * (1.0 / (4.0 * PI)) * ((1.0 - g2) / (2.0 + g2)), 1.0 + g2, 2.0 * g);
		}

		half PhaseFunctionM(half mu, half3 miePhase_g)  // optimized
		{
			// Mie phase function (optimized)
			// Precomputed PhaseFunctionG() with constant values in vertex program and pass them in here
			// we will multiply (1.0 + mu * mu) together with Rayleigh phase later.
			return miePhase_g.x / pow(miePhase_g.y - miePhase_g.z * mu, 1.5);
		}

		half PhaseFunctionR() // optimized
		{
			// Rayleigh phase function without multiply (1.0 + mu * mu)
			// We will multiply (1.0 + mu * mu) together with Mie phase later.
			return 3.0 / (16.0 * PI);
		}

		v2f vert(appdata_t v)
		{
			v2f OUT;
			float offsetValue = _RotateAngle;// _RotateSpeed *_Time.y + unity_DeltaTime.z;
			float3 t = RotateAroundYInDegrees(v.vertex.xyz, offsetValue).xyz; //  animate rotation
			// scale with camera’s far plane and following camera position.
			t = t * _ProjectionParams.z + _WorldSpaceCameraPos.xyz;
			t.y += _HeightOffset;

			OUT.pos = TransformWorldToHClip(t); //UnityObjectToClipPos(float4( t, v.vertex.w ));
			float4 ndc = OUT.pos * 0.5f;
			ndc.xy = float2(ndc.x, ndc.y * _ProjectionParams.x) + ndc.w;
			ndc.zw = OUT.pos.zw;
			OUT.fogCoord = VolumetricFog_GetFogCoord(ndc, TransformWorldToView(float4(t.xyz, 1.0)).z);
#if UNITY_REVERSED_Z
			OUT.pos.z = 0;
#else
			OUT.pos.z = OUT.pos.w;
#endif
			//UnityLight mainLight = X2M_MainLight();
			//float3 dir = mainLight.dir;//lerp(x2m_SunDirSize.xyz, x2m_MoonDirSize.xyz, saturate(x2m_SkyNightParams.y));
			float3 dir = _MainLightPosition.xyz;

			// inverse rotation to correct the light direction from vertex animation
			dir = RotateAroundYInDegrees(dir, -offsetValue);
			OUT.lightDir = dir;

			float3 binormal = cross(normalize(v.normal), normalize(v.tangent.xyz)) * v.tangent.w;
			float3x3 rotation = float3x3(v.tangent.xyz, binormal, v.normal);
			OUT.toSun = mul(rotation, dir).xy * _StepSize;

			// uv mapping
			OUT.baseTC = (_Mapping == 0) ? TRANSFORM_TEX(v.rectangular, _CloudSampler) : v.polar;

			// Shade Color
			OUT.skyColor = _CloudAmbient;// unityAmbient * _SkyColorMultiplier;
			//OUT.lightColor = mainLight.color * _LightColorMultiplier;// max(_LightColor0.xyz * _LightColorMultiplier, OUT.skyColor);
			OUT.lightColor = _MainLightColor.rgb * _LightColorMultiplier;


			OUT.worldPos.xyz = mul((float3x3)unity_ObjectToWorld, v.vertex.xyz);

			OUT.miePhase_g = PhaseFunctionG(hazeEccentricity);
			/*#ifdef SKY_FOG
				const float3 camToWorld = OUT.worldPosAndCamHeight.xyz - _WorldSpaceCameraPos.xyz;
				OUT.localFogColor = GetHeightFogColor(OUT.worldPosAndCamHeight.xyz, camToWorld);
			#endif*/

				return OUT;
			}

			half4 frag(v2f IN) : SV_Target
			{
				const int c_numSamples = 3; //  keep in SM 2.0

				float3 dir = normalize(IN.worldPos.xyz);
				float nu = dot(dir, IN.lightDir.xyz);

				// uv
				float2 sampleDir = IN.toSun.xy;
				float2 uv = IN.baseTC.xy;

				// only use red channel as clouds density 
				half opacity = SAMPLE_TEXTURE2D(_CloudSampler, sampler_CloudSampler, uv).r;
				// user define opacity level (need to clamp to 1 for HDR Camera)

				opacity = min(opacity * _Mask, 1.0);

				// Increase the "Alpha Opacity" during the night time for better masking out the background moon and stars
				//opacity = lerp(opacity, min(opacity * 1.15, 1.0), x2m_SkyNightParams.x);

				half density = 0;

				UNITY_FLATTEN
				if (opacity > 0.01) // bypass sampling any transparent pixels 
				{
					for (int i = 0; i < c_numSamples; i++)
					{
						float2 sampleUV = uv + i * sampleDir;
						half t = SAMPLE_TEXTURE2D(_CloudSampler, sampler_CloudSampler, sampleUV).r;
						density += t;
					}
				}
				density /= c_numSamples;
				density *= 8; // 为了保持兼容乘以8

				// scatter term
				half phase = PhaseFunctionR();
				half phaseM = PhaseFunctionM(nu, IN.miePhase_g);
				half scatter = (phase + phaseM) * (1 + nu * nu) * _ScatterMultiplier;

				half c = saturate(exp2(-_Attenuation * density + scatter));
				half a = pow(opacity, _AlphaSaturation);
				half3 col = lerp(IN.skyColor, IN.lightColor, c);
				
				col.rgb = VolumetricFog_GetFog(col.rgb, IN.fogCoord);
	
	#ifdef SKY_FOG
				//col.xyz = lerp(IN.localFogColor.xyz, col.xyz, IN.localFogColor.w);
	#endif
				return half4(col, a);
			}

		ENDHLSL


				Tags
			{
				"Queue" = "Transparent-10"
					"IgnoreProjector" = "True"
					"RenderType" = "Transparent"
					"RenderPipeline" = "LightweightPipeline"
			}

		Pass 
		{
			Name "ForwardLit"
			Tags{"LightMode" = "FoliageForward"}
			Blend SrcAlpha OneMinusSrcAlpha
			ZWrite Off

			HLSLPROGRAM
			#pragma vertex vert
			#pragma fragment frag
			
			ENDHLSL
		}

		Pass
		{
			Name"ForwardLit"
			Tags{"LightMode" = "SRPDefaultUnlit"}
			//Blend SrcAlpha OneMinusSrcAlpha
			ZWrite Off

			ColorMask A
			HLSLPROGRAM
			#pragma vertex vert
			#pragma fragment frag2

			uniform half _SceneBloomFactor;
			uniform half _SkyBloomFactor;

			half4 frag2(v2f IN) : SV_Target
			{
								//half4 col = SAMPLE_TEXTURE2D(_CloudSampler, sampler_CloudSampler, IN.baseTC.xy);
				half4 col = _SceneBloomFactor * _SkyBloomFactor;
				return col;
			}
			ENDHLSL
		}
	}
	Fallback Off
} 