UE4 Material 101学习笔记——30-37 植物叶片(透光/mask/面片隐藏/法线调整/AO/渐隐/世界空间色彩/随风舞动)

Posted 清清!

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了UE4 Material 101学习笔记——30-37 植物叶片(透光/mask/面片隐藏/法线调整/AO/渐隐/世界空间色彩/随风舞动)相关的知识,希望对你有一定的参考价值。

UE4 Material 101学习笔记——30-37 植物叶片(透光/mask/面片隐藏/法线调整/AO/渐隐/世界空间色彩/随风舞动)

本系列学习资料来源,Ben Cloward大佬的频道,B站的搬运翻译

接下来的章节将会讨论一些提升树叶表现的技术

Lec30 叶子透光 Foliage Translucency

在这一节,我们会讨论叶子的半透明

首先来看看现实中太阳照射叶子的情况

太阳光穿过树叶,我们在树叶背面也能够看到其颜色变化,这就是我们希望得到的目标

首先我们在初学者包里拿到这个SM_Bush,作为我们的实验对象

使用其自带的材质,拷贝一份作为实验对象

我们在12课做过一个叶子的shader,我们把它放进来


这是我们的基础效果

当我们到背光面,可以看到现在是黑黑的,我们希望能够得到透光的效果

在根节点的着色模型选择双面植物

创建给次表面颜色的蒙版,应用UV偏移(该蒙版是把叶子选出来,去掉其他不应该透射的部分)

Lec31 叶子贴图打包 Foliage Texture Packing

上节我们用了三种纹理,但其实可以有更好的处理方法

首先我们忘记处理一个问题,我们启用了双面照明,但是法线贴图只是一面的

所以为了修正这点,使用TwoSideSign节点,它会输出±1来标识正面

见仁见智,开起来反面会死黑?感觉不连TwoSideSign也没事

1 合并粗糙度/透明度/次表面mask

这一节要教的是,如何打包 粗糙度 和 次表面散射的透明度 到一个通道中

另外资产我们也进行了替换,使用Luis Garcia制作的树的资产,可以从这里免费获得

我们来看看怎么打包这些图

  • 第一个红绿蓝的图,是我们自己画出来的mask
    第二个图,是原本的树叶的不透明度的mask
    二到三,我们把树干擦掉
  • 三到四,我们取得原本diffuse图的灰度版本

    与之前的遮罩进行叠加

    提亮一点
  • 四到五,把第二张图灰阶调低
    然后五到六,叠加上第四张图
    得到这个结果,其直方图是这样的

2 一图多用

我们把它塞入A通道
——————
为了获取不透明度的模板,我们获取它的值,乘一个较大的数,所有非0的都会超过1
这样在UE中会自动clamp到1

——————
再者,我们来设置次表面颜色
我们如果想通过这个alpha图获取叶子的部分,用来做叶子次表面颜色的系数的话
那么我们只需要整个纹理减去一个灰度值,相当于做一个灰度的截断即可

之后需要补上个乘法提亮,然后saturate限制到0和1


这样不用做更多的纹理采样,对性能有所帮助
——————
接下来,用它设置粗糙度,使用1-x节点,让叶子变黑,其他变白,稍微加一点,就可以做粗糙度

切换到粗糙度视图

然而现在看这些树,似乎分叉非常的明显,呈现Y状,这样不好,我们之后要改进它

Lec32 隐藏叶子面片 Foliage Hiding Planes

在本节,我们要学习如何隐藏植物的那些面片
一棵树,不加shader原本是这样的

树由许多面片组成,叶子是在面片上添加着色器形成的
在一个面片上呈现几十片叶子,而不是用好多多边形去组成一个叶子
我们需要去隐藏面片的效果

1 修正

在此之前,做一些小修正

  • 我们看到叶子会这样长出了树干

    这显然是不合理的,原因是因为 我们shader的UV 和 叶子在面片的UV 不一样
    做如下改正

  • 上一节在透明模板部分乘了个4,有些太高,可以改成1.5

2 “计算”法线——DDX&DDY

如何让人看不出叶子在一个平面上呢?
我们需要在角度较偏的时候,隐藏叶子

做法采用,相机和法线的点乘,因为双面,所以再附上绝对值,反转自乘反转,限制一下角度
也就是以下节点,把它们乘上不透明模板

想一想这样的做法,确实可行

但是我们看看模型的法线,发现有些诡异

  • 法线实际上并不在这个面片指向的方向
  • 模型的法线实际上已经被调整过,不是沿着面片的朝向,而是指着离开树木中心的方向,为了让树木的照明正确(这些是下节要讨论的内容)
  • 但是为了达到我们需要的目的,我们要做一些tricky的东西,去克服表面法线不对劲这个事情

于是我们要去计算多边形的表面法线,这在UE中有两个节点,一个叫做DDX一个叫做DDY,可以给我们提供帮助

  • DDX和DDY,是片段着色器指令,可以用于计算任何值相对于屏幕空间坐标的变化率
  • 我们知道在光栅化的时刻,GPUs会在同一时刻并行运行很多Fragment Shader,但是并不是一个pixel一个pixel去执行的,而是将其组织在2x2的一组pixels分块中,去并行执行。
  • 而偏导数就正好是计算的这一块像素中的变化率。
    从下图可以看出来ddx 就是右边的像素块的值减去左边像素块的值,而ddy就是下面像素块的值减去上面像素块的值。其中的x,y代表的是屏幕坐标。

我们使用DDX获取X方向的斜率,DDY获取Y方向的斜率,相当于获取了两个向量
那么这两个向量的叉积,就是法线

(这里最后反正要点积再取绝对值,所以DDY和DDX谁叉乘谁都影响不大,不过下节就会有影响了)

连出来到不透明模板这里


Ben提到,我们目前做的事情,都是为了让效果看起来尽可能好,可能对于手游来说要更加简便为好

Lec33 叶子法线 Foliage Normals

1 引入

叶片的法线需要特殊处理,为什么呢?

我们知道,叶片是由面片构成的,但是面片实际上代表了好多好多叶子,我们并不想让一整个片上的叶子都是同样的光照情况

之前我们制作了叶子的抖动动画,平面的渐隐渐出,这节我们来调整面片的法线。

为了尽可能直观,我们把SkyLight关掉,把材质里的次表面颜色断开,方便直白的观察法线的影响

2 四种法线

有以下几种方法构建面片的叶子法线

2.1 Face Normals

FaceNormal就是叶子所在这个面片的VertexNormal,也就是面片的朝向
虽然面片方向确实是这样,但是照的不好看
我们之前用过法线计算遮挡,在红框处做的调整我们就能得到FaceNormal,连到节点上
(为什么这里要乘以-1呢?因为这里是DDY叉乘DDX,右手定则是朝-Z的法线,所以乘个-1翻回去
(如果改成DDX叉乘DDY也行,就不要乘以-1了


切换到法线视图,可以看到法线都是平面化的,这样不太适合“叶子”,显得很笨拙

这是我们要避免的FaceNormal

2.2 Bent Normals

对于特定的树,我们有第二种法线,BentNormal
这也是之前我们自带的normal做法,我们点开模型,点开法线

在树梢的末端,这些绿色的法线,以一种指向外部的方式背对中心,这就是BentNormal

我们在生成树的模型的3D软件中,可以从一个球来烘焙法线,烘焙到树的几何体上

有一些具体的实际制作教程,如以下链接

对比一下植物的法线和球的法线,是很接近的

2.3 Object Pivot Normals

如果我们因为一些原因,无法去改变几何体的法线,或者想要某种类型的法线

那么,我们可以从几个不同的位置生成法线

我们知道,向量是一个位置减去另一个位置

我们可以用像素的物体的世界中心的位置与对象中心的位置,两者相减,得到从物体向外朝着像素的向量,把这个当法线,输出球状照明


效果是这样,和之前BentNormal很像,并且是真的平滑过渡,我们也没有使用顶点法线

但是我们现在还没用法线贴图呢,所以我们要把这个平滑过渡加到之前的法线贴图上(注意,下方应该是world space到Tangent space)

非常平滑又有法线

2.4 Camera Normals

第四种方法其实是用CameraVector作为表面的法线

这种方法制作的法线,通常用做那些一直要朝向我们的面片

3 方法混合 Bonus Hybrid Method

对于树,我们想这么混合
树枝,使用CameraVector,叶子,使用Object Pivot Normals,插值的参数用之前的mask(注意,下方应该是world space到Tangent space)


可以看到叶子和枝干是区分开的,这是我们的节点

对比一下,这是我们做法线调整之前的树

这是之后

动图对比
这是之前

这是之后,法线的过渡更加平滑

然而这样做会有死黑的问题,因为Object Pivot Normals可能和插片的方向一样,导致法线和插片的面法线垂直了,直接黑掉了

Ben后来的做法,该用面法线,vert normal

Lec34 叶片AO Foliage Ambient Occlusion

本节将会为叶片制作AO,做法有些和一般的AO不一样,因为我们的叶子是存在于面片上的

我们想一想,树上有大量的树叶,其由一堆不同方向的随机面片组成,我们需要一个均匀平滑的好AO——也就是,树的中心变暗,朝着树的方向变亮

为什么呢?思考一棵树在阳光下是什么样的情况,我们往树的中心走,透过叶子的阳光就越少,就越暗了

上一节我们用过Object Pivot Normals
如果我们用像素位置减去树模型这个对象的位置,得到这个向量并测量长度,那么我们就可能知道我们离中心有多远,以此来设置黑白的值

连到高光度,去看看高光度缓冲的效果(此处法线连的要是add那个地方,不过只是看缓冲区,没关系,后面改回来了)(注意,法线应该是world space到Tangent space)


再加一个power,加大对比度看看


我们将其运用到次表面颜色和镜面值(注意,法线应该是world space到Tangent space)


中间暗,周围亮很明显

我们如果把它也真的连到AO上,整个数黑了很多


我们整理一下节点,总览(注意,法线应该是world space到Tangent space)

分布



(感觉连了AO太黑的,可以不连)

Lec35 叶片渐隐 Foliage Camera Fade

我们会让相机进入叶子时,叶子渐隐

真实的世界不会这样,但是为了游戏性考虑,进入丛林时,会让丛林变得暗淡

我们建立一个CameraDistanceMask的材质函数

随着相机的前后移动,会呈现0-1的变化,Near和Far设置的是200到600厘米,将预览值作为默认值

我们把它乘上不透明模板

确实,裁减了,但是很生硬

我们接着用dither temporal aa


效果还不错

我们注意到,我们的shader很复杂,不过实际用的时候,可以按需选择想要的部分

Lec36 叶片的色彩变化 Foliage Color Variation

这节,我们为树制作颜色变化的shader
如果我们只有一棵树,那很不错,但是如果我们有一座森林呢?
每个树的shader都一样,颜色都一样

实际生活中并不会这样

所以我们想要制作一个材质函数,让每个树的颜色略有不同

我们需要将这个纹理,从上到下投影到世界空间,每棵树,对这个纹理做稍微不同的采样,将树的纹理和这个噪声纹理混合起来
(我做不到一样,就用其他噪声纹理替代了)

以下是这个材质函数,绝对位置作为梯度,物体位置作为基准决定颜色
1000是基于位置的比例,0.5是混合程度

同时我们发现以前的叶子有些黑边,在此做一些修改


创造了几棵树,使用同一个shader,他们随着位置的不同,采样了纹理的不同位置

Lec37 叶片随风飘舞 Foliage Wind Sway

这节,我们要加入风的做法
之前的动图,我们看得到树干在摇摇晃晃的,但是我们的叶子整体保持不动

确实之前我们做过叶片动画,但是那是像素的UV移动
这次我们让顶点动起来

我们的风,既能wiggle(小幅度、快速的扭动)也能sway(节奏比较缓慢的摇摆,摇曳)

1 Wiggle——小幅扭动

也就是我们要专注于世界位置偏移了
我们会用到这个节点

wiggle非常好做,这就是它所要用的

它最后连出来的是

2 Sway——缓慢摇摆

Sway略显复杂,我们需要用到一个节点,RotateAboutAxis

Position使用世界位置
PivotPoint,我们不会使用ObjectPosition而会是原点
NormalizedRotationAxis,需要风向和向上向量的叉积
RotationAngle,需要两组正弦波叠加
同时在Sway最后,让上面叶子动的多,下面动得少,最后的最后和之前的Wiggle进行叠加,连到偏移上

以上是关于UE4 Material 101学习笔记——30-37 植物叶片(透光/mask/面片隐藏/法线调整/AO/渐隐/世界空间色彩/随风舞动)的主要内容,如果未能解决你的问题,请参考以下文章

UE4 Material 101学习笔记——19-22 程序化噪声的使用(Noise节点)

UE4 Material 101学习笔记——23-29 水涟漪/水深/折射反射/Gerstner海浪/波光焦散/泡沫/FlowMap

UE4-注册已序列化Shaderl流程

UE4-注册已序列化Shader流程

UE4-注册已序列化Shader流程

ue4 material custom node - global function and method