# CG之菲涅尔效果简单实现

菲涅尔效果，指当光到达两种材质的接触面时，一些光在接触面的表面被反射出去，而另一部分光将发生折射穿过接触面。

reflectionCoefficient = max(0, min(1, bias + scale * pow(1 + dot(I,N), power)))

finalColor = reflectionCoefficient * reflectedColor + (1 - reflectionCoefficient ) * refractedColor

 1 Shader "Custom/Test"
2 {
3     Properties
4     {
5         _Cube("Cube", Cube) = "white" {}
6         _EtaRatio("Eta ratio", float) = 0.8
7         _FresnelPower("Fresnel power", float) = 2
8         _FresnelScale("Fresnel scale", float) = 1
9         _FresnelBias("Fresnel bias", float) = 0
10     }
11
13     {
14         Tags
15         {
16             "RenderType" = "Opaque"
17         }
18
19         Pass
20         {
21             CGPROGRAM
22             #pragma vertex Vert
23             #pragma fragment Frag
24
25             #include "UnityCG.cginc"
26
27             uniform samplerCUBE _Cube;
28             uniform float _EtaRatio;
29             uniform float _FresnelPower;
30             uniform float _FresnelScale;
31             uniform float _FresnelBias;
32
33             struct AppData
34             {
35                 float4 pos : POSITION;
36                 float3 nor : NORMAL;
37             };
38
39             struct V2F
40             {
41                 float4 pos : SV_POSITION;
42                 float reflectionFactor : Color;
43                 float3 r : TEXCOORD0;
44                 float3 t : TEXCOORD1;
45             };
46
47             V2F Vert(AppData vi)
48             {
49                 V2F fi;
50                 fi.pos = mul(UNITY_MATRIX_MVP, vi.pos);
51
52                 float3 n = normalize(mul(vi.nor, (float3x3)_World2Object));
53                 float3 viewDir = WorldSpaceViewDir(vi.pos);
54                 float3 i = normalize(-viewDir);
55
56                 fi.r = reflect(i, n);                                                                        // 反射向量
57                 fi.t = refract(i, n, _EtaRatio);                                                            // 折射向量
58                 fi.reflectionFactor = _FresnelBias + _FresnelScale * pow(1 + dot(i, n), _FresnelPower);        // 反射颜色所占比例
59
60                 return fi;
61             }
62
63             float4 Frag(V2F fi) : Color
64             {
65                 float4 reflectC = texCUBE(_Cube, fi.r);
66                 float4 refractC = texCUBE(_Cube, fi.t);
67                 return lerp(refractC, reflectC, fi.reflectionFactor);
68             }
69
70             ENDCG
71         }
72     }
73 }