Unity Shader模拟玻璃效果
本文实例为大家分享了UnityShader实现玻璃效果的具体代码,供大家参考,具体内容如下
Shader"GlassRefraction"{
Properties{
_MainTex("MainTex",2D)="white"{}
_BumpMap("NormalMap",2D)="bump"{}
_Cubemap("EnvironmentCubemap",Cube)="_Skybox"{}
_Distortion("Distortion",Range(0,100))=10
_RefractAmount("RefractAmount",Range(0.0,1.0))=1.0
}
SubShader{
//1.队列设置成透明的可以保证渲染该物体的时候,其他所有不透明的物体都已经被渲染到屏幕上了
//这样GrabPass保存屏幕图像的时候才能完整
//2.渲染类型设置为不透明是为了使用着色器替换的时候,物体可以在被需要时正确的渲染
Tags{"Queue"="Transparent""RenderType"="Opaque"}
//抓取屏幕图像并保存到纹理_RefractionTex中
GrabPass{"_RefractionTex"}
Pass{
CGPROGRAM
#pragmavertexvert
#pragmafragmentfrag
#include"UnityCG.cginc"
sampler2D_MainTex;
float4_MainTex_ST;
sampler2D_BumpMap;
float4_BumpMap_ST;
samplerCUBE_Cubemap;
float_Distortion;
fixed_RefractAmount;
sampler2D_RefractionTex;
//可以得到系统保存的纹素的尺寸大小1/256,1/512
//对屏幕图像坐标采样进行偏移的时候需要使用该变量
float4_RefractionTex_TexelSize;
structa2v{
float4vertex:POSITION;
float3normal:NORMAL;
float4tangent:TANGENT;
float2texcoord:TEXCOORD0;
};
structv2f{
float4pos:SV_POSITION;
float4scrPos:TEXCOORD0;
float4uv:TEXCOORD1;
float4TtoW0:TEXCOORD2;
float4TtoW1:TEXCOORD3;
float4TtoW2:TEXCOORD4;
};
v2fvert(a2vv){
v2fo;
o.pos=mul(UNITY_MATRIX_MVP,v.vertex);
//得到对应被抓取的屏幕图像的采样坐标
o.scrPos=ComputeGrabScreenPos(o.pos);
//原图和法线贴图公用同一套UV坐标,进行纹理偏移缩放设置
o.uv.xy=TRANSFORM_TEX(v.texcoord,_MainTex);
o.uv.zw=TRANSFORM_TEX(v.texcoord,_BumpMap);
//世界方向
float3worldPos=mul(unity_ObjectToWorld,v.vertex).xyz;
//法线世界方向
fixed3worldNormal=UnityObjectToWorldNormal(v.normal);
//切线世界方向
fixed3worldTangent=UnityObjectToWorldDir(v.tangent.xyz);
//世界副切线方向
fixed3worldBinormal=cross(worldNormal,worldTangent)*v.tangent.w;
//定义:切线空间到世界空间的变换矩阵
//所有的TBN都从切线空间转换到了世界空间
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);
returno;
}
fixed4frag(v2fi):SV_Target{
//世界空间
float3worldPos=float3(i.TtoW0.w,i.TtoW1.w,i.TtoW2.w);
//世界空间下的观察方向
fixed3worldViewDir=normalize(UnityWorldSpaceViewDir(worldPos));
//对法线贴图进行采样,并使用UnpackNormal解压*2-1,但实际上法线贴图在切线空间下
//所以需要将bump从切线空间转换到世界空间
fixed3bump=UnpackNormal(tex2D(_BumpMap,i.uv.zw));
//对采样坐标进行偏移
float2offset=bump.xy*_Distortion*_RefractionTex_TexelSize.xy;
i.scrPos.xy=offset*i.scrPos.z+i.scrPos.xy;
//对屏幕纹理进行采样
fixed3refrCol=tex2D(_RefractionTex,i.scrPos.xy/i.scrPos.w).rgb;
//将bump从切线空间转换到世界空间
//TtoW0的xyz:T的X,B的X,N的X
//用点积得到一个常量
bump=normalize(half3(dot(i.TtoW0.xyz,bump),dot(i.TtoW1.xyz,bump),dot(i.TtoW2.xyz,bump)));
//用法线贴图求反射方向
fixed3reflDir=reflect(-worldViewDir,bump);
//主纹理采样
fixed4texColor=tex2D(_MainTex,i.uv.xy);
//对_Cubemap进行纹理采样,使用反射方向
fixed3reflCol=texCUBE(_Cubemap,reflDir).rgb*texColor.rgb;
//反射颜色+折射颜色
fixed3finalColor=reflCol*(1-_RefractAmount)+refrCol*_RefractAmount;
returnfixed4(finalColor,1);
}
ENDCG
}
}
FallBack"Diffuse"
}
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。