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 也是好的。

梓喵出没博客(azimiao.com)版权所有,转载请注明链接:https://www.azimiao.com/9944.html
欢迎加入梓喵出没博客交流群:313732000

我来吐槽

*

*