参考文献:《Unity Shader入门精要》
渲染纹理
镜子效果
Shader "Unlit/Chapter10-Mirror"
{
Properties
{
_MainTex ("Main Tex", 2D) = "white" {}
}
SubShader
{
Tags { "RenderType"="Opaque" "Queue"="Geometry"}
//LOD 100
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
sampler2D _MainTex;
struct a2v{
float4 vertex:POSITION;
float3 texcoord:TEXCOORD0;
};
struct v2f{
float4 pos:SV_POSITION;
float3 uv:TEXCOORD0;
};
v2f vert(a2v v){
v2f o;
o.pos=UnityObjectToClipPos(v.vertex);
o.uv=v.texcoord;
//作为镜子此刻需要翻转x
o.uv.x=1-o.uv.x;
//o.uv.y=1-o.uv.y;
return o;
}
fixed4 frag(v2f i):SV_Target{
return tex2D(_MainTex,i.uv);
}
ENDCG
}
}
FallBack Off
}
玻璃效果
Shader "Unlit/Chapter10-GlassRefraction"
{
Properties
{
_MainTex("Main Tex",2D)="white" {} //玻璃材质纹理,默认为白色纹理
_BumpMap("Normal Map",2D)="bump" {} //玻璃的法线纹理
_Cubemap("Envirnoment Cubemap",Cube)="Skybox" {} //模拟反射的环境纹理
_Distortion("Distortion", Range(0,100))=10 //用于控制模拟折射时图像的扭曲程度
_RefractAmount("Refract Amount",Range(0.0,10))=1.0 //控制折射程度,为0,该玻璃只包含反射效果,为1只包含折射效果
}
SubShader
{
Tags { "Queue"="Transparent" "RenderType"="Opaque" }
GrabPass {"_RefractionTex"} //通过GrabPass定义一个抓取屏幕图像的Pass
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
sampler2D _MainTex;
float4 _MainTex_ST; //为了定义偏移和缩放属性(Scale,Transform)
sampler2D _BumpMap;
float4 _BumpMap_ST;
samplerCUBE _Cubemap;
float _Distortion;
fixed _RefractAmount;
//对应了使用GrabPass时指定的纹理名称
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=UnityObjectToClipPos(v.vertex);
o.scrPos=ComputeGrabScreenPos(o.pos); //获得对应被抓取的屏幕图像的采样坐标
//获得MainTex和BumpMap的采样坐标
o.uv.xy=TRANSFORM_TEX(v.texcoord,_MainTex);
o.uv.zw=TRANSFORM_TEX(v.texcoord,_BumpMap);
//计算顶点从切线空间到世界坐标空间的转换矩阵,通过得到切线空间三个坐标轴(副切线,切线,法线)在世界坐标空间下的表示来得到
float3 worldPos=mul(unity_ObjectToWorld,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);
fixed3 worldViewDir=normalize(UnityWorldSpaceViewDir(worldPos));
fixed3 bump=UnpackNormal(tex2D(_BumpMap,i.uv.zw));
float2 offset=bump.xy*_Distortion*_RefractionTex_TexelSize.xy;
i.scrPos.xy=offset*i.scrPos.z+i.scrPos.xy;
fixed3 refrCol=tex2D(_RefractionTex,i.scrPos.xy/i.scrPos.w).rgb;
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;
fixed3 finalColor=reflCol*(1-_RefractAmount)+refrCol*_RefractAmount;
return fixed4(finalColor,1);
}
ENDCG
}
}
FallBack "Diffuse"
}