// Upgrade NOTE: replaced '_Object2World' with 'unity_ObjectToWorld'
Shader "Custom/Reflection"
{
Properties//属性
{
_MainTex("Main Tex",2D) = "white"{}//贴图代替漫反射颜色
_Color("Tex Color",Color) = (1,1,1,1)//贴图颜色:与贴图uv坐标下的像素点颜色混合
_NormalMap("Normal Map",2D) = "bump"{}//未添法线贴图时为默认法线
_NormalST("Normal ST",Float) = 1//法线贴图强度参数
_Specular("_Specular", Color) = (1, 1, 1, 1)//高光颜色
_Gloss("_Gloss", Range(1, 200)) = 20//高光参数
_ReflectAmount("_ReflectAmount",Range(0,1)) = 1
_RefractRate("RefractRate",Range(0.1,1))=0.5
_CubeMap("_CubeMap",Cube) = "_Skybox"{}//天空和贴图
}
SubShader
{
Pass
{
Tags {"Lighting" = "ForwardBase"} //定义LightMode,获取UNITY内部光照变量
CGPROGRAM
//在CG声明属性
sampler2D _MainTex;//ShaderCG中的关键字
float4 _MainTex_ST; //主贴图的缩放与偏移“属性名称固定”_MainTex_ST.xy缩放属性;_MainTex_ST.zw偏移属性
fixed4 _Color;//与贴图叠混合颜色
sampler2D _NormalMap;
float4 _NormalMap_ST;
float _NormalST;
fixed4 _Specular;
int _Gloss;
fixed _ReflectAmount;
fixed _RefractRate;
samplerCUBE _CubeMap;
#include "Lighting.cginc"//引入UNITY内置文件,获取光照变量 _LightColor0.rgb;光源颜色
#pragma vertex vert//声明顶点函数
#pragma fragment frag//声明片原函数

	struct a2v//应用向顶点函数传递参数
	{
		float4 vertex:POSITION;//模型空间顶点坐标
		//切线空间的确定是通过(存储到模型里的/模型空间)法线 与 (存储到模型里的/模型空间)切线确定的
		float3 normal:NORMAL;//模型空间法线方向
		float4 tangent:TANGENT;//模型空间下的切线方向:tangent.w:是用来确定切线空间中坐标轴的方向(切线空间下的Z轴方向默认为顶点的法线方向:通过控制缩放xy可改变法线强度)
		float4 texcoord :TEXCOORD0;//获取纹理坐标
	};
	struct v2f//顶点函数向片原函数传递参数
	{
		float4 svPos:SV_POSITION;//顶点函数返回值:剪裁空间中的顶点坐标-系统直接使用
		//float3 worldNormal : TEXCOORD3;//顶点函数向片原函数传递世界坐标下的法线方向(使用法线贴图后不需要)
		float3 lightDir:TEXCOORD0;//切线空间下的平行光方向
		float3 viewDir:TEXCOORD1;//顶点函数向片原函数传递且切线空间下的视线方向

		float4 uv:TEXCOORD2;//xy用来存储_MainTex的纹理坐标,zw用来存储_NormalMap的纹理坐标
		float3 WorldRefl:TEXCOORD3;
	};

	v2f vert(a2v v)//顶点函数将顶点从模型空间转到世界空间,返回值在世界坐标系下的顶点坐标
	{
		v2f f;//声明传参结构体,并对其中的值赋值
		f.svPos = UnityObjectToClipPos(v.vertex);
		//f.worldNormal = UnityObjectToWorldNormal(v.normal);
		//f.worldView = (UnityObjectToWorldNormal(v.vertex), 0);
		f.uv.xy = v.texcoord.xy * _MainTex_ST.xy + _MainTex_ST.zw;//将纹理坐标传递到片原函数 * 乘上主贴图缩放属性 + 加上主贴图的偏移属性
		f.uv.zw = v.texcoord.xy * _NormalMap_ST.xy + _NormalMap_ST.zw;//将法线纹理坐标与其属性结合存储到uv.zw中

		TANGENT_SPACE_ROTATION;//调用这个宏后(保证a2v "v"中存在"normal""tangent"宏自动调用),会得到一个矩阵"rotation"这个矩阵用来把模型空间下的法线转换到切线空间下

		//ObjSpaceLightDir(v.vertex);//模型空间下的平行光方向
		f.lightDir = mul(rotation, ObjSpaceLightDir(v.vertex));//将切线就下的平行光方向传到片原函数
		f.viewDir = mul(rotation, ObjSpaceViewDir(v.vertex));//计算切线空间下的视角方向

		//反射:世界空间下实现反方向,法线方向
		//f.WorldRefl = reflect(-UnityWorldSpaceViewDir(mul(unity_ObjectToWorld,v.vertex)),UnityObjectToWorldNormal(v.normal));

		//折射:归一化的世界空间下反向视线方向,归一化的法线方向,折射率
		f.WorldRefl = refract(-normalize(UnityWorldSpaceViewDir(mul(unity_ObjectToWorld,v.vertex))),normalize(UnityObjectToWorldNormal(v.normal)),_RefractRate);

		return f;//返回结构体
	}

	//把与法线有关相关计算放到切线空间下(从法线贴图取到的方向坐标为切线空间下的)
	fixed4 frag(v2f f) :SV_Target//片原函数,返回值为输出到像素颜色值的缓存
	{
		//计算漫反射
		//fixed3 normalDir = normalize(f.worldNormal);//法线方向
		fixed4 normalColor = tex2D(_NormalMap,f.uv.zw);//法线贴图在纹理坐标下的颜色值(只使用其中RGB值)

		//此方法法线读取不正确//fixed3 tangentNormal = normalize(normalColor.xyz * 2 - 1);//切线空间下的法线方向
		fixed3 tangentNormal = normalize(UnpackNormal(normalColor));//在UNITY中将法线贴图类型设置为法线贴图时可用此方法获得切线空间下的法线方向
		//切线空间下的Z轴方向默认为顶点的法线方向:通过控制缩放xy可改变法线强度,则如下
		tangentNormal.xy = tangentNormal.xy * _NormalST;//强度为0时使用的即是模型顶点默认的法线方向

		fixed3 lightDir = normalize(f.lightDir);//单位化切线空间下的光源方向

		fixed3 texColor = tex2D(_MainTex, f.uv.xy) * _Color.rgb;//获取纹理坐标下贴图像素点的颜色*与外部属性控制的贴图颜色混合

		

		fixed3 diffuse = _LightColor0.rgb * texColor * max((dot(lightDir,tangentNormal) * 0.5 + 0.5), 0);//fixed3 harfLambert =dot(f.wordNormalDir, lightDir)*0.5+0.5;//半兰伯特光照模型:直射光颜色 * (cos夹角(光与法线)*0.5+0.5):使背光面不完全为黑色

		//计算高光反射
		//fixed3 reflectDir = normalize(reflect(-lightDir, normalDir));
		fixed3 viewDir = normalize(f.viewDir);//实视线方向
		fixed3 harfDir = normalize(viewDir + lightDir);//视角与平行光的平分方向
		fixed3 specular = _LightColor0.rgb * texColor * _Specular.rgb * pow(max(dot(tangentNormal, harfDir),0), _Gloss);//BP模型://Blinn-Phong光照模型Specular = 直射光*pow(max(cos夹角,0)*高光参数) ,夹角:法线与x方向夹角,x:平行光与视野方向的平分项。


		//fixed3 worleRefl = reflect(-viewDir,tangentNormal);

		//根据反射折射方向进行环境贴图采样
		fixed3 reflection = texCUBE(_CubeMap,f.WorldRefl).rgb;
		//反射/折射与漫反射线性混合
		fixed3 tempColor = lerp(diffuse, reflection,_ReflectAmount) + specular + UNITY_LIGHTMODEL_AMBIENT.rgb * texColor;//漫反射+高光+环境光*纹理,相加混合(环境光与纹理混合:使强光下的纹理仍保持清晰)
		

		return fixed4(tempColor,1);
	}
	ENDCG
}

	}
		FallBack "Diffuse"

}