15.2 水波效果
在模拟实时水平的过程中,我们往往也会使用噪音纹理。此时,噪音纹理通常会用作一个高度图,以不断修改水面的法线方向。为了模拟水不断流动的效果,我们会使用和时间相关的变量来对噪声纹理进行采样,当得到法线信息后,再进行正常的反射+折射计算,得到最后的水面波动效果。
本节中,我们将会使用一个由噪声纹理得到的法线贴图,实现一个包含菲涅尔反射(10.1.5)的水面效果。如下图所示:
在10.2.2节中我们实现了使用反射和折射来模拟一个透明玻璃的效果。本节使用的Shader和10.2.2节中的实现基本相同。我们使用一张立方体纹理(Cubemap)作为环境纹理,模拟反射。为了模拟折射效果,我们使用GrabPass来获取当前屏幕的渲染纹理,并使用切线空间下的法线方向对像素的屏幕坐标进行偏移,再使用该坐标对渲染纹理进行屏幕采样,从而模拟近似的折射效果。以10.2.2节中的实现不同的是,水波的法线纹理是由一张噪声纹理生成而得,而且会随着时间变化不断平移,模拟波光粼粼的效果。除此之外,我们没有使用一个定值来混合反射和折射颜色,而是使用之前提到的菲涅耳系数来动态决定混合系数。我们使用如下公式来计算菲涅耳系数:
fresnel = pow (1 - max (0,v×n),4)
其中,v和n分别对应了视角方向和法线方向。它们之间的夹角越小,fresnel值越小,反射越弱,折射越强。菲涅耳系数还经常会用于边缘光照的计算中。
实现
(1)新进场景(Scene_15_2)。
(2)新建材质(WaterWaveMat)。
(3)新建Unity Shader(Chapter15-WaterWave),并赋给第二步中的材质。
(4)新建测试水波效果的场景。并把第二步中创建的材质赋给模拟水面的对象。
Shader "Unity Shaders Book/Chapter 15/Water Wave" {
Properties {
//水面颜色
_Color ("Main Color", Color) = (0, 0.15, 0.115, 1)
//水面波纹材质纹理
_MainTex ("Base (RGB)", 2D) = "white" {}
//由噪声纹理生成的法线纹理。
_WaveMap ("Wave Map", 2D) = "bump" {}
//用于模拟反射的立方体纹理
_Cubemap ("Environment Cubemap", Cube) = "_Skybox" {}
//分别用于控制模拟折射时图像的扭曲程度
_WaveXSpeed ("Wave Horizontal Speed", Range(-0.1, 0.1)) =