菲涅尔反射描述了一种光学现象,当光照到物体表面时,一部分发生反射,另一部分则进入物体内部,发生折射或散射;相比直接的反射和折射计算,菲涅尔反射更接近真实情况。
可用下面的等式近似计算这种反射效果:
F=F0+(1-F0)*pow((1-dot(v,n)),p);
其中,F0为反射系数,v为视野方向,n为法线方向,p为控制指数,一般p=5。
代码如下:
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 }