Unity Shader入门精要 第十一章

  1. 1. 让画面动起来
  2. 2. 11.1 Unity Shader中的内置时间变量
  3. 3. 11.2 纹理动画
    1. 3.0.1. 11.2.1 序列帧动画
    2. 3.0.2. 11.2.2 滚动的背景
  • 4. 11.3 顶点动画
    1. 4.0.1. 11.3.1 流动的河流
    2. 4.0.2. 11.3.2 广告牌
    3. 4.0.3. 11.3.3 注意事项

  • 让画面动起来


    11.1 Unity Shader中的内置时间变量

    • 名称 类型 描述
    • _Time float4 4个分量(t/20, t, 2t, 3t),t是自该场景加载开始所经过的时间
    • _SinTime float4 4个分量(t/8, t/4, t/2, t),t是时间的正弦值
    • _CosTime float4 4个分量(t/8, t/4, t/2, t),t是时间的余弦值
    • unity_DeltaTime float4 4个分量(dt, 1/dt, smoothDt, 1/smoothDt),dt是时间增量

    11.2 纹理动画

    11.2.1 序列帧动画

    • 序列帧动画的原理非常简单,它像放电影―样,依次播放一系列关键帧图像,当播放速度达到一定数值时,看起来就是一个连续的动画
    • 它的优点在于灵活性很强,我们不需要进行任何物理计算就可以得到非常细腻的动画效果
    • 而它的缺点也很明显,由于序列帧中每张关键帧图像都不一样,因此,要制作一张出色的序列帧纹理所需要的美术工程量也比较大


    11.2.2 滚动的背景

    • 很多2D游戏都使用了不断滚动的背景来模拟游戏角色在场景中的穿梭,这些背景往往包含了多个层(layers)来模拟一种视差效果。
    • _MainTex、_DetailTex 第一层较远和第二层较近的背景纹理
    • _ScrollX、_Scroll2X 各自的水平滚动速度
    • _Multiplier 纹理的整体亮度

    11.3 顶点动画

    11.3.1 流动的河流

    • 河流的模拟是顶点动画最常见的应用之一,它的原理通常就是使用正弦函数等来模拟水流的波动效果
    • 变量分别是,河流纹理、整体颜色、水流波动的幅度、波动的频率、波长的倒数、河流纹理的移动速度
    • 一些SubShader在使用Unity的批处理功能时会出现问题,这是可以通过DisableBatching标签直接指明是否对该SubShader使用批处理。这些需要特殊处理的Shader通常是包含了模型空间的顶点动画Shader,这是因为批处理会合并所有相关的模型,而这些模型各自的模型空间就会丢失
    • 定义一个偏移量offset,只控制它的x分量,相当于x = sin(xt+y)·A

    11.3.2 广告牌

    • 另一种常见的顶点动画就是广告牌技术(Billboarding)。广告牌技术会根据视角方向来旋转一个被纹理着色的多边形(通常就是简单的四边形,这个多边形就是广告牌),使得多边形看起来好像总是面对着摄像机。广告牌技术被用于很多应用,比如渲染烟雾、云朵、闪光效果等
    • _VerticalBillboarding用于调整是固定法线的还是固定指向上的方向,也就是约束垂直方向的一个程度
    • 首先选择模型空间下的一个原点作为广告牌的一个锚点
    • 利用内置变量获取模型空间下的视角位置
    • 计算目标法线,根据_VerticalBillboarding来控制垂直方向上的约束度
    • 接下来得到粗略的向上方向,为了防止法线方向和向上方向平行,对法线方向的y分量进行判断以得到合适的向上方向
    • 根据法线方向和粗略的向上方向得到向右的方向
    • 根据原始位置相对于锚点的偏移量以及三个正交矢量,可以得到新的顶点位置
    • 需要说明的是,这里必须使用四边形Quad而不能使用Plane,这是因为代码是建立在一个竖直摆放的多边形的基础上的。也就是说,这个多边形的顶点结构需要满足在模型空间下是竖直排列的,这样才能使用v.vertex来计算得到正确的相对于中心的偏移位置

    11.3.3 注意事项

    • 首先,如11.3.2节看到的那样,如果我们在模型空间下进行了一些顶点动画,那么批处理往往就会破坏这种动画效果

      • 这时,我们可以通过SubShader 的DisableBatching标签来强制取消对该Unity Shader的批处理。然而,取消批处理会带来一定的性能下降,增加了Draw Call,因此我们应该尽量避免使用模型空间下的一些绝对位置和方向来进行计算
      • 在广告牌的例子中,为了避免显式使用模型空间的中心来作为锚点,我们可以利用顶点颜色来存储每个顶点到锚点的距离值,这种做法在商业游戏中很常见
    • 其次,如果我们想要对包含了顶点动画的物体添加阴影,那么如果仍然像9.4节中那样使用内置的Diffuse等包含的阴影Pass来渲染,就得不到正确的阴影效果(这里指的是无法向其他物体正确地投射阴影)

      • 这是因为,Unity的阴影绘制需要调用一个ShadowCaster Pass,而如果直接使用这些内置的ShadowCaster Pass,这个Pass中并没有进行相关的顶点动画,因此 Unity会仍然按照原来的顶点位置来计算阴影,这并不是我们希望看到的
      • 这时,我们就需要提供一个自定义的ShadowCaster Pass,在这个Pass 中,我们将进行同样的顶点变换过程。需要注意的是,在前面的实现中,如果涉及半透明物体我们都把Fallback设置成了Transparent/ VertexLit,而Transparent/VertexLit没有定义ShadowCaster Pass,因此也就不会产生阴影(详见9.4.5节)。
    • 实现阴影效果:

      • 删除所有透明效果的标签,打开深度写入,关闭混合,增加自己的ShadowCast Pass