相信做过 Unity 开发的同学都在 Inspector 里面见过 Tiling 和 Offset。一般情况下它们两总是形影相随,不分不离,你中有我,我中有你。。。咳咳,我们回归正题。正常情况下它们都是成对出现的,如下图。
讲 Tiling 和 Offset 之前我们先讲些其他相关的零散的知识。
纹理的 UV
UV 是一种标准化了的 2D 坐标系统,等同于 XY 坐标系统,为了不和 XY 混淆,用 U 和 V 分别表示对应的 X 和 Y。UV 系统中, (0, 0)
表示左纹理的下角,(1, 1)
表示纹理的右上角。
纹理的 Wrap Mode
Unity 中纹理的 Wrap Mode 可以设置值有:Repeat 和 Clamp。
Clamp 模式中 UV 都将被限制在 0-1
的范围内,如下图 U 轴(图来自这里),左右两侧不相连:
Repeat 中 U 轴是相连的:
同学们现在是否有一种看到 Repeat 模式像是在地板上贴瓷砖的感觉。如果能有这种感觉,我这里给你点个赞。
纹理的 _ST
Shaderlab 中纹理都会分配一个对应属性名后加 _ST 的变量来表示纹理的缩放(Scale => S)和偏移(Translation => T)。比如属性 _MainTex
其对应的变量为 _MainTex_ST
。关于 Shaderlab 属性,可以参照 [瞎聊 Unity Shader 系列之九:用来包装变量的 Properties]
Shaderlab 中 TRANSFORM_TEX
Unity Shaderlab 中的 UnityCG.cginc 有 TRANSFORM_TEX
的定义:
#define TRANSFORM_TEX(tex,name) (tex.xy * name##_ST.xy + name##_ST.zw)
其中 name 为纹理对应属性名,其中 name##_ST.xy
表示缩放,name##_ST.wz
表示偏移。
下面我们先贴 Unity 手册 中一段代码看看 TRANSFORM_TEX
是如何在 Shaderlab 编程中使用的。
1 | Shader "Unlit/NewUnlitShader" |
Tiling 和 Offset
在 Unity 编辑器中创建一个新的 Shader 和材质, 然后将新的 Shader 拖到新建的材质上,在 Inspector 中得到下图:
我们看到纹理材质的 Inspector UI 中 _MainTex
出现了 Tiling
和 Offset
。通过阅读反编译过来的 MaterialEditor 的源码,我们可以得到 ScaleOffset 属性就是 Tilling 和 Offset, 也就是说 _MainText_ST.xy 就是 Tiling, _MainTexST.wz 是 Offset。
Tiling 和 Offset 与纹理 Wrap Mode
当 Tiling 的 XY 在 [-1, -1]
区间的时候,纹理的 Wrap Mode 无论是 Repeat 还是 Clamp 对现实效果都没有影响,但是在 [-1, 1] 范围之外就有影响了。
例如,假设 Tiling 为 (3, 3) Offset 为 (0, 0), 在 Repeat 模式下显示为:
而 Clamp 模式下为:
为什么会这样?还记得吗?clamp 模式下 UV 是不连续的,而 repeat 模式下 UV 是连续的。
Tiling 和 Offset 能用来做什么?
还记得吗,上面提到的贴往地板上贴瓷砖,我们可以把纹理的 Wrap Mode 设置成 Repeat, 然后加大 Tiling 的值就“可以贴好多个瓷砖了”。抽象一下就是可以得到:
- 使用在需要重复很多相同纹理的情景。
除此之外,还可以
- 通过修改 Tiling 和 Offset 对纹理做裁剪。
- 对 Offset 做动画来改变 UV 实现水流效果等特效
- 实现精灵动画
还有很多其他情况大家可以自己去发掘。好了这篇就啰嗦到这里。Enjoy!