效果对比 - Visual Comparison
Visual Comparison

开启 Weighted Normal 之前, 渲染结果不平滑。
Before enabling Weighted Normal, the rendering result is not smooth.
图片中的收益完全来自于对法线的加权计算, 不增加顶点数和三角形数。如果通过平滑细分来实现相同的效果, 三角形面数可能会增加到原来的 16 倍。
The benefits in the images come entirely from the weighted calculation of the normals, without increasing the number of vertices and triangles. If the same effect were to be achieved through subdivision, the number of triangles could increase by up to 16 times.
原理
Principle
原理其实十分简单。假设有一个顶点 被4个面共享。由于顶点本身没有法线的概念, 顶点处的法线只能由它所 在面的法线来确定。在计算法线时选择不同的面, 会获得4个不同的法线 。
The principle is actually very simple. Suppose a vertex is shared by 4 faces. Since the vertex itself has no concept of normals, the normal at the vertex can only be determined by the normals of the faces it belongs to. When different faces are selected to calculate the normal, 4 different normals will be obtained.
如果单独计算每个面的法线, 并直接将计算结果从 vertex shader 送往 fragment shader 插值, 那么四个面的法线将完全不连续, 出现明显的 sharp edge。这种渲染方式叫做 Flat Shading。
If the normal of each face is calculated separately and the calculation result is directly sent from the vertex shader to the fragment shader for interpolation, the normals of the four faces will be completely discontinuous, resulting in a sharp edge. This rendering technique is called Flat Shading.
常用的解决方法是在顶点处储存法线,再通过 GPU 的插值能力计算平面上各个点处的发现,从而消除 sharp edge。这种 渲染方式叫做 Smooth Shading。
The common solution is to store normals at the vertices and use the GPU's interpolation capabilities to calculate the normals at various points on the surface, thus eliminating sharp edges. This rendering technique is called Smooth Shading.

这种方法对面数较高的模型效果很好,但是对于面数较低,或者表面形状复杂的模型,效果就不是很理想了。
This method works well for models with a high polygon count, but for models with a lower polygon count or complex surface shapes, the results are not as ideal.
源代码分析 - Source Code Analysis
Source Code Analysis
Blender Weighted Normal Node - Github
Weighted Normal 就是通过这4个法线的加权平均来保证面转角处的法线过度平滑, 从而在 shading 阶段 获得更加平滑的渲染效果。
Weighted Normal ensures the smooth transition of normals at the corners of faces by taking the weighted average of these 4 normals, resulting in a smoother rendering effect in the shading stage.
Weighted Normal modifier 的核心算法可以分解为以下步骤:
The core algorithm for the FaceArea mode of the Weighted Normal modifier can be broken down into the following steps:
// 1. Initialization prepare_data() initialize_buffers() // 2. Face area calculation for each face of mesh: with different mode, face area: calculate_weight_by_face_area() corner angle: calculate_weight_by_corner_angle() face area and corner angle: calculate_weight_by_face_area_and_corner_angle() sort_face_by_its_weight() // 3. Normal aggregation for each face of sorted faces: for each vertex of face: // 3.1. aggregate normal to the vertex's weighted normal let weight = exponentially_decreasing_weight(vertex.id) vertex.normal += vertex.normal * weight // 4. Normalization normalize_vertex_normals() // 5. Cleanup free_allocated_buffers()