菲涅尔反射描述了一种光学现象,当光照到物体表面时,一部分发生反射,另一部分则进入物体内部,发生折射或散射;相比直接的反射和折射计算,菲涅尔反射更接近真实情况。
可用下面的等式近似计算这种反射效果:
F=F0+(1-F0)*pow((1-dot(v,n)),p);
其中,F0为反射系数,v为视野方向,n为法线方向,p为控制指数,一般p=5。
代码如下:
1 Shader "MyUnlit/FresnelReflection" 2 { 3Properties 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 SubShader11{12 Tags{ "RenderType" = "Opaque" }13 14 Pass15{16 Tags{ "lightmode" = "forwardbase" }17 18 CGPROGRAM19 #pragma multi_compile_fwdbase20 #pragma vertex vert21 #pragma fragment frag22 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 32struct appdata33{34 float4 vertex : POSITION;35 float3 normal:NORMAL;36};37 38struct v2f39{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 48v2f 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 61fixed4 frag(v2f i) : SV_Target62{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 ENDCG79}80}81 fallback "Reflective/VertexLit"82 }