
在 Unity地形 中大家可能会在陡峭的斜坡上体验过拉伸和难看的伪阴纹理,这是由于内置的地形着色器使用的是简单平面UV映射引起的,该问题可以通过应用三平面纹理映射来解决,它会在 X、Y 、Z 上提供一个较好的表面形体纹理。
那么本教程将解释该技术的相关工作原理,并提供了简单的代码示例可供大家参考使用。
如果你不熟悉着色器语言,可以首先考虑使用现成的工具解决,比如 Triplanar UVs 插件,它与着色器相比,它提供了更好的智能的混合纹理选项。
首先什么是简单平面UV映射?我们需要搞清楚这个问题, 简单平面UV映射是Unity地形根据模型的UV坐标进行纹理化,对于Unity的坐标体系它们均匀分布在 XZ 平面上,而 Y 轴被忽略掉了,所以会导致纹理被拉伸,但地形不会像平躺的公路那样没有起伏,特别是在地形陡峭的山体斜坡处表现的尤其拉伸严重。

对于上述问题,其实也有很多种解决方案,最简单的一种是使用三平面映射。它会从 Unity模型 的 X、Y 和 Z 方向对纹理进行采样,好比我们平时穿T恤,前后左右上下会正确的匹配,仅仅只是合不合身问题。但三平面映射更像衣服的制作过程,重复的部分剪掉并缝合起来,那么地形纹理重合的部分需要进行混合而不是裁切,使其三者在表面上提供一个平滑的过渡。

那下面我们将看一个示例效果,使用默认平面纹理映射的代码类似于:
// input variables
sampler2D _Texture;
float2 uv_Texture;
// sampling
fixed4 color = tex2D(_Texture, uv_Texture);
在上面的代码中,纹理只是根据提供的 UV 坐标进行采样。在下一部分代码中,将修改采样方法。
三平面技术使用世界空间坐标而不是UV,计算三个方向中的每一个映射的颜色:
// world-space position
float2 worldPos;
fixed4 cX = tex2D(_Texture, worldPos.yz);
fixed4 cY = tex2D(_Texture, worldPos.xz);
fixed4 cZ = tex2D(_Texture, worldPos.xy);
使用法线向量混合三种颜色:
// world-space normal vector
float3 worldNormal;
// we drop the sign because we do not distinguish positive and negative directions
float3 blend = abs(worldNormal);
// the values should sum to 1 but we must avoid dividing by 0
blend /= blend.x + blend.y + blend.z + 0.001f;
// blending
fixed4 color = blend.x * cX + blend.y * cY + blend.z * cZ;
相同的方法可以应用于采样法线贴图。
以上是关于Unity地形的简单映射和使用三平面映射解决拉伸的相关讨论技术,还是前面所说的,如果你不懂着色器,可使用熟悉的适合自己的工具解决优化地形纹理。