ShaderGraph能量护盾(一):接触面检测及边缘发光
在 Youtube 上刷到了 Unity Japan meetup 2019 的分享视频,其中 ShaderGraph 的分享非常不错,跟着学习下。
前言
Unity Japan 原视频:エフェクト作成のために知っておきたいShader Graphの話
最终版 Shader 主要包含如下内容:
- 接触面检测
- 边缘发光
- UV扰动及贴图混合
- 空间扭曲(或空间扰动?)
碍于篇幅,本文章先阐述接触面检测和边缘发光。
效果
这是本文实现的效果:
与头图相比,上图还不包含 UV 扰动和贴图混合,以及不包含空间扭曲(下篇文章内容)。
实现
接触面检测
渲染过程
要进行接触面检测,首先要理解 Unity 的渲染过程:
- (默认情况下)首先按照从近到远的顺序渲染不透明物体,并写入深度值(Z-Write);
- 渲染完不透明物体后,按照从后往前的顺序渲染半透明物体,进行 Z-Test、Alpha Blend 等(但不会写入深度)。
接触检测原理
与海洋 Shader 类似,接触面检测依赖深度图(场景深度)。
接触检测的原理用代码表示如下:
// azimiao.com/梓喵出没博客
DesDepth - SrcDepth < 0 // 被覆盖(一般执行不到这里,被遮挡的片元会被剔掉)
DesDepth - SrcDepth == 0 // 相交
DesDepth - SrcDepth > 0 // 可见
用场景深度,减去能量环 Mesh PS(Pixel Shader,Unity 称 Fragment Shader(图元着色器),下同)深度,如果二者相等,即说明该位置相交。
连连看
虽然代码很简单,但本文谈论的是 ShaderGraph,那就来玩连连看吧:
注意,本 Shader 渲染队列为 Transparent。
说明
上述节点中,通过SceneDepth
节点获取深度图深度,通过ScreenPosition
的 w 分量获取当前片元的深度,二者相减,获得差值 Xa。
可以想到,越往“上”走,这个值会越大。
验证
将 Xa 直接输送给 Color 来确认计算值是否正确,此时渲染如下:
可以看到,接触面附近为逐渐加深的黑色,这说明 Xa 结果是正确的。
接下来加入一些控制节点:
EdgeOffset 与 Xa 相减
为了在接触面渲染一个有宽度的亮带,我们需要让 Xa 的值在接触面附近一小段内为正数,超过这段则为负数。
因此,上述节点增加了一个叫 EdgeOffset 的值来控制输出值范围,用代码表示的话,就是:
// Mesh 的片元们,从被完全覆盖到不被覆盖,Xa 值是持续增加的。
// 当 Xa < EdgeOffset 时,输出值 > 0
// EdgeOffset 是一个控制参数,使得 X 到 EdgeOffset 这段内输出正值,超出后输出负值。
Xb = EdgeOffset - Xa;
平滑与限制输出
为了限制输出范围为 0 到 1,同时还可调整 01 阈值,且尽可能平滑,因此用 smoothstep 节点进一步限制输出:
smoothstep 是一个图形库或数学库中常见的函数,其曲线如下:
Xc = smoothstep(0.2, 0.7, Xb);
渲染
将 Xc 作为 Alpha 值,并增加一个 Color 参数提供颜色值,此时渲染结果如下:
将 RenderFace 改为双面渲染,结果如下:
边缘发光
边缘检测原理
边缘检测的原理更简单,法线与视线方向做一次点乘即可:
Ea = vec3.dot(ps.normal,viewDir);
球形法线是发散向外的,边缘的法线由于与视线垂直,所以点乘数值逐渐接近 0,而中央越来越与视线同向,因此逐渐接近 1 或 -1。
连连看
下面是连连看图:
简要说明
ShaderGraph 的 View Direction 节点,输出的向量方向为(片元 -> 摄像机)。
我们期望的 Alpha 是边缘接近 1,中心接近 0,因此通过 OneMinus 节点对结果“取反”(非数学意义的取反)。
默认情况下,从边缘到中心是平滑变化的,为了让 Alpha 变化的更明显,附加了一条 Pow 曲线(见证幂函数的威力吧)。
后半球的片元法线与 ViewDir 反向,其点乘结果为负数,叠加 OneMinus 后的结果为正数,相当于后半球所有片元 Alpha 均大于 0。上文已经开启了双面渲染,叠加上我们计算的后半球 Alpha 后,整个后半球片元都会被渲染出来,这个结果显然不正确。因此,提前对点乘的结果取了一次绝对值。
渲染结果
混合
将两部分的 Alpha 值相加,赋给片元:
结果:
关掉 CastShadow:
结果还是很不错的。
结语
对于简单的 Shader,之前都是手撸,一个 VS 一个 PS(FragmentShader)闯天下;
对于复杂的 Shader,之前都有技美提供美术资产,因此也从未担心过。
以后大概没有这种分工明确的工作环境了,所以搞一搞 ShaderGraph 也是好的。