MiToon内置的法线平滑工具,先看效果:
工具介绍
法线平滑面板如下:


内置了三种平滑后法线输出模式:UV7,VertexColor,Tangent。
内置了一种法线压缩格式:八面体压缩(Octahedron),以及不压缩的方式。
此外,还可以启用角度加权平滑,对于同一位置顶点个数>设置阈值的位置启用特殊的加权平滑,对于发尖这种描边容易断裂的位置有更好的平滑效果。
使用示例
法线平滑

易断裂位置法线平滑
未平滑:

正常平滑:

启用加权角度平滑

部分代码

根据三角面相应角度加权平滑:
public static float CalculateWeightedAngle(Vector3[] vertices,int[] indices,int currentIndex,out Vector3 smoothNormal)
{
//The following vectors are defined in Object Space. Such as: tangent ==> tangentOS
Vector3 P1 = vertices[indices[0]];
Vector3 P2 = vertices[indices[1]];
Vector3 P3 = vertices[indices[2]];
Vector3 D1 = Vector3.zero;
Vector3 D2 = Vector3.zero;
switch(currentIndex)
{
case 0:
D1 = P1 - P3;
D2 = P2 - P1;
break;
case 1:
D1 = P2 - P1;
D2 = P3 - P2;
break;
case 2:
D1 = P3 - P2;
D2 = P1 - P3;
break;
}
D1 = D1.normalized;
D2 = D2.normalized;
smoothNormal = Vector3.Cross((P1 - P3), (P2 - P1));
smoothNormal = smoothNormal.normalized;
float angle = Mathf.Acos(Vector3.Dot(D1, -D2));
return angle;
}
平均算法平滑法线:
smoothedNormalHashMap[vertices[vertexIndex]] += normals[vertexIndex];
按照角度加权平均平滑法线:
Vector3 smoothNormal = Vector3.zero;
float angle = CalculateWeightedAngle(vertices, indices, j ,out smoothNormal);
smoothedNormalHashMap[vertices[vertexIndex]] += angle * normals[vertexIndex];
按照面积加权平均平滑法线:
smoothedNormalHashMap[vertices[vertexIndex]] += normals[vertexIndex];
smoothedNormalHashMap[vertices[vertexIndex]] = smoothedNormalHashMap[vertices[vertexIndex]].normalized;
to do
1.平滑法线能够同时写入描边宽度。
2.支持更多的压缩算法。
其他
这里记录一些其他DCC里自动平滑的工具: