【猫猫的Unity Shader之旅】之反光材质

来源:互联网 发布:linux配置文件目录 编辑:程序博客网 时间:2024/04/29 16:38

利用天空盒实现简单的反光效果

  现实生活中有许多反射的例子,镜子、平静的水面、光滑的金属表面都有或多或少的反射效果,一种简单的模拟这种现象的做法是利用天空盒和Input结构中的worldRefl变量。

  为了使用天空盒资源,我们可以导入官方的Skyboxes资源包,然后自己创建一个天空盒资源。一个天空盒资源需要六张贴图,分别表示盒子的六个面。

  这里写图片描述

  worldRefl表示世界空间中的反射向量,关于这个东西,猫猫目前把它理解成反射过程中的入射光方向,具体的细节还不清楚,有时间会详细研究一下。总之,有了这个向量,我们就可以用texCUBE函数去索引到天空盒上的一个颜色。具体的代码如下:

Shader "Custom/CubeRefl" {    Properties {        _MainTint ("Main Color", Color) = (1, 1, 1, 1)        _MainTex ("Base (RGB)", 2D) = "white" {}        _CubeMap ("Cube Map", CUBE) = ""{}        _ReflPower("Refl Power", Range(0, 1)) = 0.5    }    SubShader {        Tags { "RenderType"="Opaque" }        LOD 200        CGPROGRAM        #pragma surface surf Lambert        sampler2D _MainTex;        samplerCUBE _CubeMap;        fixed4 _MainTint;        fixed _ReflPower;        struct Input {            float2 uv_MainTex;            float3 worldRefl;        };        void surf (Input IN, inout SurfaceOutput o) {            half4 c = tex2D (_MainTex, IN.uv_MainTex);            o.Albedo = _MainTint.rgb * c.rgb;            o.Emission = texCUBE(_CubeMap, IN.worldRefl).rgb * _ReflPower;            o.Alpha = c.a;        }        ENDCG    }     FallBack "Diffuse"}

  实现的效果是这样的:

  这里写图片描述
  

菲涅尔效果

  咦?这里有奇怪的名字出现哦~

  话说这位菲先生其实是法国的一位物理学家。关于这位老先生的生平事迹这里就不说啦,总之这位菲先生发现了一个有趣的光学现象,所以这个现象就直接叫做菲先生现象啦。这个现象具体指的是:当我们观察物体表面的角度(相对于法线)越大时,看到的反射效果也越明显。

  基于菲先生的结论,我们可以实现一个这样的Shader,效果也很不错。为了得到观察的方向,我们需要用到Input结构中的另一个变量:viewDir。对上面的代码稍作修改就可以做出菲涅尔效果:

Shader "Custom/CubeRefl" {    Properties {        _MainTint ("Main Color", Color) = (1, 1, 1, 1)        _MainTex ("Base (RGB)", 2D) = "white" {}        _CubeMap ("Cube Map", CUBE) = ""{}        _ReflPower("Refl Power", Range(0, 1)) = 0.5        _FresnelPower("Frensnel Power", Range(0.1, 5)) = 2    }    SubShader {        Tags { "RenderType"="Opaque" }        LOD 200        CGPROGRAM        #pragma surface surf Lambert        sampler2D _MainTex;        samplerCUBE _CubeMap;        fixed4 _MainTint;        fixed _ReflPower;        fixed _FresnelPower;        struct Input {            float2 uv_MainTex;            float3 worldRefl;            float3 viewDir;        };        void surf (Input IN, inout SurfaceOutput o) {            half4 c = tex2D (_MainTex, IN.uv_MainTex);            fixed diff = 1.0 - saturate(dot(o.Normal, normalize(IN.viewDir)));            diff = pow(diff, _FresnelPower);            o.Albedo = _MainTint.rgb * c.rgb;            o.Emission = texCUBE(_CubeMap, IN.worldRefl).rgb * diff * _ReflPower;            o.Alpha = c.a;        }        ENDCG    }     FallBack "Diffuse"}

  得到的效果是这样的:

  这里写图片描述
  

  话说这位菲先生确实给我们提供了一些思路。用viewDir这个变量,我们可以轻松表示出观察物体表面角度的变化。利用这种变化我们可以实现出很多效果,比如边缘发光,随视角变化的颜色衰减等,如果有足够的想象力,这种方式可以做出很多效果。

结束语

  反射效果可以极大的增强渲染的真实效果,使用天空盒这种方式牺牲的效率也是比较小的,结合上一回说过的利用贴图实现表面不同部分的不同处理,反射也可以做出不同的形式。而viewDir这个东西也给了我们充分的发挥想象力的空间,这里真的要感谢菲先生啦~

0 0
原创粉丝点击