4-2 纹理采样

  在上一章中,我们导入了一张RGB噪点图,并完成了噪点图的相关导入设置,在本章中,我们将创建一些基础的方法,来获取噪点图的实例。
  首先我们要在HexMetrics.cs中添加一个静态方法,用来读取彩色噪点图中的各类信息,并进行相关操作。因为创建的方法是静态方法,所以其引用的噪点图变量也必须是静态的。这样,我们就可以在程序的任意位置调用这个方法了。

HexMetrics.cs
1
2
3
4
5
6
7
public static class HexMetrics
{
//彩色噪点图的实例
public static Texture2D noiseSource;


}

  由于HexMetrics.cs并未继承MonoBehaviour,所以它不是一个组件,其中的变量也不能在Inspector面板中显示。我们也不能像普通变量那样,直接使用拖拽实例放入变量在Inspector面板的位置上进行赋初始值。那我们就简单地把HexGrid当一个中转,因为HexGrid是第一个运行的,所以在它的Awake方法开始的位置传递值就行了。代码如下:

HexGrid.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class HexGrid : MonoBehaviour
{
//彩色噪点图的实例,直接将图片拖拽至Inspector面板对应位置赋初始值
public Texture2D noiseSource;



private void Awake()
{
//为HexMetrics的静态变量赋值
//由于此脚本最先被调用,所以在这里赋初始值
HexMetrics.noiseSource = noiseSource;


}
}

  在Play模式下,如果我们想要引用另一个彩色噪点图,那么在Awake的赋值语句就不起作用了。要解决这个问题还需要在OnEnable方法中重新赋值彩色噪点图的实例。

HexGrid.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
public class HexGrid : MonoBehaviour
{


private void OnEnable()
{
//Unity在Play模式中,Awake只会在脚本被实例化时调用一次,如果之后噪点图改变了,没办法重新为静态变量赋值
//所以这里再次进行赋值,之后只要disable后在enable,静态变量就会被重新赋值
HexMetrics.noiseSource = noiseSource;
}


}

  现在HexMetrics.cs就能访问彩色纹理贴图了,我们添加一个方便的噪声采样方法,这个方法用来读取彩色噪点图,并返回一个包含四种噪声模式的4D向量。代码如下

HexMetrics.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
public static class HexMetrics
{


/// <summary>
/// 对彩色噪点图进行采样
/// </summary>
/// <param name="position">采样点位置坐标,世界坐标</param>
/// <returns>RGBA四个值组成的4D向量</returns>
public static Vector4 SampleNoise(Vector3 position)
{
}
}

  接下来,我们完成来SampleNoise方法。通过双线性过滤的方式对彩色纹理图进行采样得到样本数据,由于是使用世界坐标系下的X和Z轴坐标作为UV坐标,所以噪声源是3D的,这里我们忽略掉Y轴坐标。采样后我们得到一个可以转换成4D向量的颜色,这个转换是隐式的,这意味着我们可以直接返回颜色,而不用显式的转换成Vector4。代码如下:

HexMetrics.cs
1
2
3
4
5
6
7
8
public static class HexMetrics
{


//由于入参是世界位置的vector3,而图片UV是二维的,这里忽略掉垂直方向的Y
//GetPixelBilinear获取的是指定点的RGBA值,转换为Vector4是隐式的。
return noiseSource.GetPixelBilinear(position.x, position.z);
}

  至此。我们通过世界坐标内的一个点,就能获取到彩色噪点图中对应位置的RGBA值,这样我们就完成了采样的工作。在接下来的章节中,我们将利用采样得到的数据,对地图上的顶点进行偏移,也就是扰动。就会让地图产生更多的变化。

双线性过滤
Jasper Flick大神有专门介绍UV的教程:Rendering 2 Shader Fundamentals,里面详细介绍了UV坐标和纹理的相关知识。

Github代码