2-5 让颜色过渡更加平滑

  在上一章中,我们重构了为三角面片赋值颜色的代码,为每个不同的顶点赋值了不同的颜色。实现了最基本的颜色不同切相邻的两个地图单元之间,会有颜色过渡的功能。但是视觉效果上并没有达到我们的预期。在这一章中,我们将优化现在的颜色混合视觉效果,让颜色过渡更加平滑。
  首先,颜色不同切相邻的两个地图单元之间的边界颜色,应该是两个地图单元颜色的平均值。

HexMesh.cs
1
2
3
4
5
6
7
8
9
10
11
private void Triangulate(HexDirection direction, HexCell cell)
{


//两个相邻的cell,其交界处的颜色应该是两个cell颜色的平均值
Color edgeColor = (cell.color + neighbor.color) * 0.5f;

//为三角面片的顶点赋颜色值
//AddTriangleColor(cell.color, neighbor.color, neighbor.color);
AddTriangleColor(cell.color, edgeColor, edgeColor);
}

  经过修改,虽然视觉效果好了一些,但是颜色交界的地方过渡依然显得有些突兀。这是因为在颜色过渡不平滑的位置,会有三个地图单元共享一个顶点位置的颜色,我们之前的方法只是在两两混合颜色。

  按照这个思路,我们在混合N方位地图单元的颜色时,还需要考虑N+1和N-1位置地图单元的颜色。

HexDirection.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public static class HexDirectionExtensions
{


/// <summary>
/// 获取当前相邻cell 之前的一个cell的方位
/// </summary>
/// <param name="direction">当前相邻cell的方位</param>
/// <returns></returns>
public static HexDirection Previous(this HexDirection direction)
{
//如果当前cell位置为NE,即索引为0,其之前的一个cell方位应该为NE,即索引为6
//除此之外的情况,只要当前索引值减1即可
return direction == HexDirection.NE ? HexDirection.NW : (direction - 1);
}

/// <summary>
/// 获取当前相邻cell 之后的一个cell的方位
/// </summary>
/// <param name="direction">当前相邻cell的方位</param>
/// <returns></returns>
public static HexDirection Next(this HexDirection direction)
{
//与Previous方法中类似,方位索引为6时,回到0,其余情况则方位索引加1
return direction == HexDirection.NW ? HexDirection.NE : (direction + 1);
}
}

  现在,我们可以通过新增的两个方法,来获取N+1和N-1位置地图单元的颜色了。然后再分别进行颜色混合。

HexMesh.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
private void Triangulate(HexDirection direction, HexCell cell)
{


//获取当前相邻方位cell,索引值-1相邻cell的实例
HexCell prevNeighbor = cell.GetNeighbor(direction.Previous()) ?? cell;

//获取与自身当前相邻的cell的颜色值
//每个cell会在 Triangulate(HexCell cell) 方法中将与自身相邻的cell遍历一次
//?? 为 可空合并运算符,即cell.GetNeighbor(direction)的值为null时,使用 cell的值
HexCell neighbor = cell.GetNeighbor(direction) ?? cell;

//获取当前相邻方位cell,索引值+1相邻cell的实例
HexCell nextNeighbor = cell.GetNeighbor(direction.Next()) ?? cell;

//两个相邻的cell,其交界处的颜色应该是两个cell颜色的平均值
//Color edgeColor = (cell.color + neighbor.color) * 0.5f;

//获取到相邻方位cell,以及相邻方位cell +1和-1 cell的实例,接下来进行颜色混合
//三角面片3个顶点颜色分别为
//自身颜色
//自身颜色,自身颜色+相邻cell方位减1颜色,相邻cell颜色
//自身颜色,自身颜色+相邻cell方位加1颜色,相邻cell颜色
AddTriangleColor(
cell.color,
(cell.color+prevNeighbor.color+neighbor.color)/3.0f,
(cell.color+nextNeighbor.color+neighbor.color)/3.0f
);
}

  现在,我们就得到了新的颜色混合效果。但是通过观察发现,在地图边缘的这些地图单元,颜色混合是存在一些问题的。造成这种现象的原因是边缘的单元格缺失了N+1和N-1位置的地图单元,导致了颜色混合还是会有明显的边界。在下一章中,我们需要更换一下思路,来解决这个问题。

Github代码