《Unity shader》10.1.5 菲涅尔反射

在本节中,我们将使用Schlick菲涅耳近似等式来模拟菲涅耳反射。在本节最后,我们可以得到类似图10.10中的效果。注意图中在模型边界处的反射现象。


(1)新建一个场景,在本书资源中,该场景名为Scene_10_1_5。我们替换掉Unity 5中场景默认的天空盒子,而把10.1.1节中创建的天空盒子材质拖曳到Window → Lighting → Skybox选项中(当然,我们也可以为摄像机添加Skybox组件来覆盖默认的天空盒子)。

(2)向场景中拖曳一个Teapot模型,并调整它的位置。

(3)新建一个材质,在本书资源中,该材质名为FresnelMat,把材质赋给第2步中创建的Teapot模型。

(4)新建一个Unity Shader,在本书资源中,该Shader名为Chapter10-Fresnel。把Chapter10-Fresnel赋给第3步中创建的材质。

打开Chapter10-Fresnel,删除原有的代码,进行如下关键修改。

(1)首先,我们在Properties语义块中声明了用于调整菲涅耳反射的属性以及反射使用的Cubemap:

(2)在顶点着色器中计算世界空间下的法线方向、视角方向和反射方向:

(3)在片元着色器中计算菲涅耳反射,并使用结果值混合漫反射光照和反射光照:

保存后返回场景,在材质面板中把Cubemap_0拖曳到Cubemap属性中,并调整其他参数,即可得到类似图10.10中的效果。当我们把_FresnelScale调节到1时,物体将完全反射Cubemap中的图像;当_FresnelScale为0时,则是一个具有边缘光照效果的漫反射物体。

https://github.com/candycat1992/Unity_Shaders_Book/blob/master/Assets/Shaders/Chapter10/Chapter10-Fresnel.shader

cs 复制代码
// Upgrade NOTE: replaced '_Object2World' with 'unity_ObjectToWorld'
// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'

Shader "Custom/Chapter10-Fresnel"
{
    Properties {
        _Color ("Color Tint", Color) = (1, 1, 1, 1)
        _FresnelScale ("Fresnel Scale", Range(0, 1)) = 0.5  // 菲涅尔缩放系数:控制边缘反射强度,0.0:禁用菲涅尔效应,均匀反射,0.5:中等边缘反射强度(默认)1.0:最大菲涅尔效应,边缘反射强烈
        _Cubemap ("Reflection Cubemap", Cube) = "_Skybox" {}
    }

    SubShader {
        Tags { "RenderType"="Opaque" "Queue"="Geometry"}
        
        Pass {
            Tags { "LightMode"="ForwardBase" }
            CGPROGRAM
            #pragma multi_compile_fwdbase
            #pragma vertex vert
			#pragma fragment frag

            #include "Lighting.cginc"
			#include "AutoLight.cginc"

            fixed4 _Color;
			fixed _FresnelScale;
			samplerCUBE _Cubemap;

            struct a2v {
                float4 vertex : POSITION;
                float3 normal : NORMAL;
            };

            struct v2f {
                float4 pos : SV_POSITION;
                float3 worldPos : TEXCOORD0;
                fixed3 worldNormal : TEXCOORD1;
                fixed3 worldViewDir : TEXCOORD2;
                fixed3 worldRefl : TEXCOORD3;
                SHADOW_COORDS(4)
            };

            v2f vert(a2v v) {
                v2f o;
                o.pos = UnityObjectToClipPos(v.vertex);
                o.worldNormal = UnityObjectToWorldNormal(v.normal);
                o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
                o.worldViewDir = UnityWorldSpaceViewDir(o.worldPos);
                o.worldRefl = reflect(-o.worldViewDir, o.worldNormal);
                TRANSFER_SHADOW(o);
                return o;
            }

            fixed4 frag(v2f i) : SV_Target {
                fixed3 worldNormal = normalize(i.worldNormal);
                fixed3 worldLightDir = normalize(UnityWorldSpaceLightDir(i.worldPos));
                fixed3 worldViewDir = normalize(i.worldViewDir);
                fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;
                UNITY_LIGHT_ATTENUATION(atten, i, i.worldPos);
                fixed3 reflection = texCUBE(_Cubemap, i.worldRefl).rgb;
                fixed fresnel = _FresnelScale + (1 - _FresnelScale) * pow(1 - dot(worldViewDir, worldNormal), 5);
                fixed3 diffuse = _LightColor0.rgb * _Color.rgb * max(0, dot(worldNormal, worldLightDir));
				fixed3 color = ambient + lerp(diffuse, reflection, saturate(fresnel)) * atten;
                return fixed4(color, 1.0);
            }

            ENDCG
        }
    }
    FallBack "Reflective/VertexLit"
}
相关推荐
小贺儿开发1 天前
Unity3D 智慧城市管理平台
数据库·人工智能·unity·智慧城市·数据可视化
June bug2 天前
【领域知识】休闲游戏一次发版全流程:Google Play + Apple App Store
unity
星夜泊客2 天前
C# 基础:为什么类可以在静态方法中创建自己的实例?
开发语言·经验分享·笔记·unity·c#·游戏引擎
dzj20212 天前
PointerEnter、PointerExit、PointerDown、PointerUp——鼠标点击物体,则开始旋转,鼠标离开或者松开物体,则停止旋转
unity·pointerdown·pointerup
心前阳光2 天前
Unity 模拟父子关系
android·unity·游戏引擎
在路上看风景2 天前
26. Mipmap
unity
咸鱼永不翻身2 天前
Unity视频资源压缩详解
unity·游戏引擎·音视频
在路上看风景2 天前
4.2 OverDraw
unity
在路上看风景2 天前
1.10 CDN缓存
unity
ellis19703 天前
Unity插件SafeArea Helper适配异形屏详解
unity