Unity Shaders and Effects Cookbook (4-5)Cubemap与菲涅尔反射

菲涅尔是人名,他发现,当我们站在水中,直直的往下看水面,是看不到反射的太阳光的。而当我们往远处看时,就能看到很强的反光,也就是成语波光粼粼所体现的。这一现象就被命名为 菲涅尔反射。


刚看这一节的时候觉得莫名其妙,感情书上一开始写的有问题,书上是这么写的:

当你的视线对着物体表面的时候,反射量会明显增加。

我对这句话的理解是 正对着表面的时候,反射量会增加。……真是误导。

不过好在代码是不会骗我的。

代码实现的效果是符合菲涅尔反射的,正对着物体表面,反射量减少。

转自http://blog.csdn.net/huutu http://www.thisisgame.com.cn

创建新的场景 、材质、Shader。


完整Shader 代码如下:

Shader "CookBookShaders/Chapt4-5/FresnelReflections" 
{
	Properties 
	{
		_MainTint("Diffuse Tint",Color)=(1,1,1,1)
		_MainTex ("Base (RGB)", 2D) = "white" {}

		_Cubemap("Cubemap",CUBE)=""{}

		_ReflectionAmount("Reflection Amount",Range(0,1))=1

		_RimPower("Fresnel Falloff",Range(0.1,3))=2

		_SpecColor("Specular Color",Color)=(1,1,1,1)

		_SpecPower("Specular Power",Range(0,1))=0.5
	}

	SubShader 
	{
		Tags { "RenderType"="Opaque" }
		LOD 200
		
		CGPROGRAM
		#pragma surface surf BlinnPhong
		#pragma target 3.0


		float4 _MainTint;
		sampler2D _MainTex;

		samplerCUBE _Cubemap;

		float _ReflectionAmount;

		float _RimPower;

		float _SpecPower;

		struct Input 
		{
			float2 uv_MainTex;
			float3 worldRefl;
			float3 viewDir;
		};

		void surf (Input IN, inout SurfaceOutput o) 
		{
			half4 c = tex2D (_MainTex, IN.uv_MainTex)*_MainTint;

			//首先求 法线 和 视线 夹角的cos值,然后使用saturate限定到(0,1)范围。因为是cos,所以当视线垂直表面,平行法线时,值最大为1.
			//然后用 1 去减cos值,得到反转值。
			//所以当视线垂直表面时,rim值最小,为0.

			float rim=1.0 - saturate(dot(o.Normal,normalize(IN.viewDir)));
			rim=pow(rim,_RimPower);

			o.Albedo = c.rgb;

			//所以当视线垂直表面时,rim=0,o.Emission =0 。视线越靠近垂直,反射越小。
			o.Emission=(texCUBE(_Cubemap,IN.worldRefl).rgb * _ReflectionAmount)*rim;
			o.Specular=_SpecPower;
			o.Gloss=1.0;
			o.Alpha = c.a;
		}
		ENDCG
	} 
	FallBack "Diffuse"
}

代码注释上面已经有了。

我也画了个图。



最终实现的效果

Unity Shaders and Effects Cookbook (4-5)Cubemap与菲涅尔反射_第1张图片


看到视线正对的那一块区域是很少反射的。



示例项目下载:

http://pan.baidu.com/s/1dF9Eu5b


你可能感兴趣的:(unity3d,CUBEMAP,菲涅尔反射)