菲涅尔反射描述了一种光学现象,当光照到物体表面时,一部分发生反射,另一部分则进入物体内部,发生折射或散射;相比直接的反射和折射计算,菲涅尔反射更接近真实情况。
可用下面的等式近似计算这种反射效果:
F=F0 (1-F0)*pow((1-dot(v,n)),p);
其中,F0为反射系数,v为视野方向,n为法线方向,p为控制指数,一般p=5。
代码如下:
代码语言:javascript复制 1 Shader "MyUnlit/FresnelReflection"
2 {
3 Properties
4 {
5 _Color("Color Tint", Color) = (1,1,1,1)
6 _ReflectColor("Reflection Color",Color) = (1,1,1,1)
7 _FresnelScale("Fresnel Scale",range(0,1)) = 0.5
8 _CubeMap("Reflection CubeMap",cube) = "_skybox"{}
9 }
10 SubShader
11 {
12 Tags{ "RenderType" = "Opaque" }
13
14 Pass
15 {
16 Tags{ "lightmode" = "forwardbase" }
17
18 CGPROGRAM
19 #pragma multi_compile_fwdbase
20 #pragma vertex vert
21 #pragma fragment frag
22
23 #include "UnityCG.cginc"
24 #include "autolight.cginc"
25 #include "lighting.cginc"
26
27 fixed4 _Color;
28 fixed4 _ReflectColor;
29 fixed _FresnelScale;
30 samplerCUBE _CubeMap;
31
32 struct appdata
33 {
34 float4 vertex : POSITION;
35 float3 normal:NORMAL;
36 };
37
38 struct v2f
39 {
40 float3 worldPos : TEXCOORD0;
41 float4 pos : SV_POSITION;
42 float3 worldNormal:TEXCOORD1;
43 float3 worldViewDir:TEXCOORD2;
44 float3 worldRef:TEXCOORD3;
45 SHADOW_COORDS(4)
46 };
47
48 v2f vert(appdata v)
49 {
50 v2f o;
51 o.pos = UnityObjectToClipPos(v.vertex);
52 o.worldNormal = UnityObjectToWorldNormal(v.normal);
53 o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
54 o.worldViewDir = UnityWorldSpaceViewDir(o.worldPos);
55 o.worldRef = reflect(-o.worldViewDir, o.worldNormal);
56
57 TRANSFER_SHADOW(o);
58 return o;
59 }
60
61 fixed4 frag(v2f i) : SV_Target
62 {
63 fixed3 worldNormal = normalize(i.worldNormal);
64 fixed3 worldViewDir = normalize(i.worldViewDir);
65 fixed3 worldLightDir = normalize(UnityWorldSpaceLightDir(i.worldPos));
66
67 fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;
68 fixed3 col = texCUBE(_CubeMap, i.worldRef).rgb;
69 fixed3 reflection = col * _ReflectColor.rgb;
70
71 fixed3 diffuse = _LightColor0.rgb*_Color.rgb*saturate(dot(worldNormal, worldLightDir));
72 fixed fresnel = _FresnelScale (1 - _FresnelScale)*pow(1 - dot(worldViewDir, worldNormal), 5);
73
74 UNITY_LIGHT_ATTENUATION(atten, i, i.worldPos);
75 fixed3 color = ambient lerp(diffuse, reflection, saturate(fresnel))*atten;
76 return fixed4(color,1.0);
77 }
78 ENDCG
79 }
80 }
81 fallback "Reflective/VertexLit"
82 }