玻璃效果【Unity Shader 入门精要10.2.2】

//玻璃效果 10.2.2

Shader "Unlit/Chapter10-GlassRefraction"
{
	Properties
	{
		//玻璃的材质纹理
		_MainTex ("Texture", 2D) = "white" {}
		//玻璃的法线纹理
		_BumpMap("Normal Map",2D) = "bump"{}
		//模拟反射环境的纹理
		_Cubemap("Environment Cubemap",Cube) = "_Skybox"{}
		//模拟折射时的图像扭曲程度
		_Distortion("Distortion",Range(0,100))=10
		//控制折射程度
		_RefractAmount("Reftact Amount",Range(0.0,1.0))=1.0
	}
	SubShader
	{
			// We must be transparent, so other objects are drawn before this one.(transparent必须透明的,这样其他的物体就会被画在这个之前。)
			Tags{ "Queue" = "Transparent" "RenderType" = "Opaque" }

			// This pass grabs the screen behind the object into a texture.(这个传递将对象后面的屏幕抓取到一个纹理中。)
			// We can access the result in the next pass as _RefractionTex(我们可以在下一次传递中访问结果为_RefractionTex)
			GrabPass{ "_RefractionTex" }

			Pass{
			CGPROGRAM

#pragma vertex vert
#pragma fragment frag

#include "UnityCG.cginc"

		sampler2D _MainTex;
		float4 _MainTex_ST;
		sampler2D _BumpMap;
		float4 _BumpMap_ST;
		samplerCUBE _Cubemap;
		float _Distortion;
		fixed _RefractAmount;
		sampler2D _RefractionTex;
		float4 _RefractionTex_TexelSize;

		struct a2v {
			float4 vertex : POSITION;
			float3 normal : NORMAL;
			float4 tangent : TANGENT;
			float2 texcoord: TEXCOORD0;
		};

		struct v2f {
			float4 pos : SV_POSITION;
			float4 scrPos : TEXCOORD0;
			float4 uv : TEXCOORD1;
			float4 TtoW0 : TEXCOORD2;
			float4 TtoW1 : TEXCOORD3;
			float4 TtoW2 : TEXCOORD4;
		};

			
			
		v2f vert(a2v v) {
			v2f o;
			//坐标转换
			o.pos = mul(UNITY_MATRIX_MVP, v.vertex);

			//获取屏幕坐标
			o.scrPos = ComputeGrabScreenPos(o.pos);

			//TRANSFORM_TEX:根据比例尺/偏压特性转换2D UV,包含在#include "UnityCG.cginc"
			o.uv.xy = TRANSFORM_TEX(v.texcoord, _MainTex);
			o.uv.zw = TRANSFORM_TEX(v.texcoord, _BumpMap);

			//坐标转换
			float3 worldPos = mul(_Object2World, v.vertex).xyz;
			//法线转换
			fixed3 worldNormal = UnityObjectToWorldNormal(v.normal);
			//切线转换
			fixed3 worldTangent = UnityObjectToWorldDir(v.tangent.xyz);
			//副法线转换
			fixed3 worldBinormal = cross(worldNormal, worldTangent) * v.tangent.w;

			//(切线,副法线,法线,位置)
			o.TtoW0 = float4(worldTangent.x, worldBinormal.x, worldNormal.x, worldPos.x);
			o.TtoW1 = float4(worldTangent.y, worldBinormal.y, worldNormal.y, worldPos.y);
			o.TtoW2 = float4(worldTangent.z, worldBinormal.z, worldNormal.z, worldPos.z);

			return o;
		}
			
			fixed4 frag (v2f i) : SV_Target
			{
				//获取位置
				float3 worldPos = float3(i.TtoW0.w,i.TtoW1.w,i.TtoW2.w);
				//float3 UnityWorldSpaceViewDir(float4 v)  输入一个世界空间中的顶点位置,返回世界空间中从该点到摄像机的观察方向。
				fixed3 worldViewDir = normalize(UnityWorldSpaceViewDir(worldPos));

				// Get the normal in tangent space (获得切线空间下的法线位置)
				fixed3 bump = UnpackNormal(tex2D(_BumpMap, i.uv.zw));

				
				// 位移=法线位置*扭曲程度*抓取的纹理的纹素值
				float2 offset = bump.xy*_Distortion*_RefractionTex_TexelSize.xy;
				//屏幕坐标=位移+屏幕原坐标
				i.scrPos.xy = offset + i.scrPos.xy;
				//折射颜色=二维纹理查询(抓取的纹理,屏幕位置/深度).rgb
				fixed3 refrCol = tex2D(_RefractionTex, i.scrPos.xy /i.scrPos.w).rgb;
				
				//把法线方向从切线空间变换到世界空间下,得到视角方向的相对于法线方向的反射方向
				//(使用变换矩阵的每一行,既切线、副法线、法线、TtoW,分别和切线空间下的法线方向点积,构成新的法线方向)
				bump = normalize(half3 (dot(i.TtoW0.xyz, bump), dot(i.TtoW1.xyz, bump), dot(i.TtoW2.xyz, bump)));

				//反射方向=反射函数(视角方向取反,新法线方向)
				fixed3 reflDir = reflect(-worldViewDir, bump);
				//纹理颜色=二维纹理查询(主纹理,纹理坐标)
				fixed4 texColor = tex2D(_MainTex, i.uv.xy);
				//反射颜色=在世界空间中使用反射方向访问立方体图
				fixed3 reflCol = texCUBE(_Cubemap, reflDir).rgb*texColor.rgb;

				//最终颜色=反射颜色*(1-折射程度)+反射颜色*折射程度
				fixed3 finalColor = reflCol * (1 - _RefractAmount) + refrCol * _RefractAmount;

				return fixed4(finalColor, 1);
			}
			ENDCG
		}
	}
		FallBack "Diffuse"
}

 

 

今天就只弄了一个这个。。。心情不好,从早上一起床开始。。上午群里讨论了游戏版本号的问题,大多数公司都死掉了。。。独立游戏开发者根本没有出路,那图形学的出路呢,别辛辛苦苦弄了好久找不到工作。。。。今天一跟我妈提,我妈兴致勃勃的问我是不是打算转行了啊,哎,她一直希望我转行。看着这个玻璃效果还算能有点心安,没有同行的人,也没有支持的人,我的图形学道路能坚持到什么时候,莫名心酸,昨天真正意识到就算学会unityshader也只是冰山一角,真的再一次体会路漫漫其修远。。。

 

你可能感兴趣的:(玻璃效果【Unity Shader 入门精要10.2.2】)