shader 玻璃效果

玻璃效果主要是折射效果的计算和反射效果的计算。

折射:
1.利用Grass Pass对当前屏幕的渲染图像进行采样
2.得到法线贴图对折射的影响
3.对采集的屏幕图像进行关于法线方向上的扭曲和偏移,以模拟折射效果

反射:
主要利用环境贴图产生反射的残影,并和主贴图采样结果混合

得到反射和折射的结果后,以一个变量控制最终效果(类似于玻璃的透光率);

效果如下:
在这里插入图片描述

代码如下:

Shader "MyShader/011"
{
	Properties
	{
		_MainTex("Texture", 2D) = "white" {}
		_Diffuse("Color",Color) = (1,1,1,1)
		_BumpMap("Normal Map",2D) = "white"{}
		_BumpScale("Bump Scale", float) = 1
		_Cubemap("CubeMap",Cube) = "_Skybox"{}
		_Distortion("Distortion",Range(0,100)) = 10//模糊程度
		_RefractAmount("RefractAmount",Range(0,1)) = 1//一个折射系数,用于控制折射和反射的占比
	}

	SubShader
	{
		Tags { "RenderType" = "Opaque" "Queue" = "Transparent+100"}//在所有物体渲染之后再抓屏
		LOD 100

		GrabPass{"GrabPass"}//抓取当前屏幕的渲染图像并存入指定纹理

		Pass
		{
			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag

			#include "UnityCG.cginc"
			#include "Lighting.cginc"

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

			sampler2D _MainTex;
			float4 _MainTex_ST;
			fixed4 _Diffuse;
			sampler2D _BumpMap;
			float4 _BumpMap_ST;
			float _BumpScale;
			sampler2D GrabPass;//要和GrabPass中的名字一样
			float4 GrabPass_TexelSize;//抓取的纹理图的大小
			float _Distortion;
			samplerCUBE _Cubemap;
			float _RefractAmount;

			v2f vert(appdata_tan v)
			{
				v2f o;
				o.vertex = UnityObjectToClipPos(v.vertex);
				o.scrPos = ComputeGrabScreenPos(o.vertex);//得到屏幕采样坐标
				o.uv.xy = TRANSFORM_TEX(v.texcoord, _MainTex);
				o.uv.zw = TRANSFORM_TEX(v.texcoord, _BumpMap);

				fixed3 worldPos = mul(unity_ObjectToWorld, v.vertex);
				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
			{
				fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT;

				fixed4 albedo = tex2D(_MainTex, i.uv.xy);

				float3 worldPos = float3(i.TtoW0.w,i.TtoW1.w,i.TtoW2.w);

				fixed3 lightDir = UnityWorldSpaceLightDir(worldPos);
				fixed3 viewDir = normalize(UnityWorldSpaceViewDir(worldPos));

				//求法线
				fixed4 packedNormal = tex2D(_BumpMap,i.uv.zw);
				fixed3 tangentNormal = UnpackNormal(packedNormal);
				tangentNormal.xy *= _BumpScale;
				fixed3 worldNormal = normalize(float3(dot(i.TtoW0.xyz, tangentNormal), dot(i.TtoW1.xyz, tangentNormal),dot(i.TtoW2.xyz,tangentNormal)));

				//采样抓屏贴图
				//对采集的屏幕图像进行关于法线方向上的扭曲和偏移,也就是模拟折射的效果
				float2 offset = tangentNormal.xy * _Distortion * GrabPass_TexelSize.xy;
				i.scrPos.xy = offset * i.scrPos.z + i.scrPos.xy;
				fixed3 refrCol = tex2D(GrabPass, i.scrPos.xy / i.scrPos.w).rgb;//齐次除法还原

				//模拟反射的效果,反射越强,也就是透光度越低,越能看到主贴图纹理以及周围环境反射的残影
				fixed3 reflCol = texCUBE(_Cubemap, reflect(-viewDir, worldNormal)).rgb * albedo;

				//将折射和反射进行一个综合叠加,_RefractAmount可以认为是透光率,当它为1时,就是全透过而没有反射,为0时就是全反射跟镜子一样
				fixed3 color = reflCol * (1 - _RefractAmount) + refrCol * _RefractAmount;
				return fixed4(color,1);
			}
			ENDCG
		}
	}
}

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值