顶点曲率不能直接用std::atan2或法向量差角计算,因青铜器边缘磨损取决于局部几何突变程度而非角度大小;正确方法是基于邻接面法向量与面积构建加权协方差矩阵并特征分解,提取主曲率方向与标量,再映射至BRDF参数以真实模拟氧化/磨损光学特性。

顶点曲率计算为什么不能直接用 std::atan2 或法向量差角
因为青铜器边缘磨损的高光不是靠“角度大小”决定的,而是靠局部几何突变程度——也就是曲率在顶点处的离散近似。直接对相邻面法向量求夹角会忽略顶点邻域内面片朝向的分布密度,导致钝角边缘(如器物腹部过渡区)误判为高磨损。正确做法是把顶点周围所有邻接面看作一个加权方向场,用 principal_curvature_direction 的极值变化率来建模。但 C++ 没有内置曲率算子,得自己构造协方差矩阵。
实操建议:
- 对每个顶点
v,收集其一环邻接面(face),提取各面法向量n_i和对应面面积A_i - 构建 3×3 协方差矩阵:
C = Σ A_i * (n_i * n_i^T),注意n_i是单位向量,A_i用海伦公式或叉积模长的一半算 - 对
C做特征分解,最小特征值对应的特征向量近似为该顶点的主曲率方向;曲率标量取λ_max / (λ_min + ε)(ε=1e-6 防除零) - 别用
Eigen::SelfAdjointEigenSolver默认排序——它不保证特征值升序,必须手动找min_element索引
怎么把曲率映射到青铜氧化/磨损的 BRDF 参数上
老旧青铜不是金属度拉满的 PBR 材质,它的“高光磨损”本质是:边缘氧化层薄 → 露出底层铜锡合金 → 微观粗糙度下降 → 镜面反射增强 + 各向异性略升。所以不能只调 roughness,要联动控制三个参数。
实操建议:
- 定义曲率归一化值
k = clamp(curvature * 0.3f, 0.0f, 1.0f)(系数 0.3 是经验值,适配青铜常见网格密度) -
metallic设为0.4f + k * 0.35f(本体氧化铜 metallic≈0.4,纯合金≈0.75) -
roughness设为0.6f - k * 0.4f(边缘更光滑,但不会低于 0.2,否则像抛光新器) - 额外加个
anisotropy偏移:1.0f + k * 0.8f(模拟青铜结晶沿边缘取向排列) - 千万别在 fragment shader 里实时算曲率——顶点着色器传
in float v_curvature,插值后做平滑 clamping
为什么用 OpenMesh 而不是 assimp 做预处理
assimp 导入后只有顶点/索引数组,没有显式邻接关系,重建一环面片需要 O(n²) 暴力搜索;而青铜网格常带孔洞、非流形边(如耳部连接处),assimp 会自动 triangulate 并破坏原始拓扑,导致曲率在连接缝处跳变。OpenMesh 的 VertexFaceCWIter 可直接遍历,且支持 is_boundary() 判断是否为器物物理边缘——这对区分“铸造分型线”和“使用磨损线”很关键。
实操建议:
- 加载时强制启用
OM::Options::VertexNormal | OM::Options::FaceNormal - 对每个顶点调用
mesh.is_boundary(vh),若是边界顶点,曲率值 ×1.8(模拟实际中边缘受力更集中) - 跳过
mesh.valence(vh) 的顶点(孤点或退化三角面,多见于扫描噪声) - 导出时用
OpenMesh::IO::write_mesh()保存带custom property的 .off 文件,存曲率到mesh.vertex_property("v:curv")
OpenGL 渲染时怎么避免曲率插值导致的“亮边断裂”
顶点曲率是离散采样值,线性插值到片元后,在锐利转折处(比如鼎耳根部)会出现阶梯状高光条带。这不是精度问题,而是插值本身违背了几何连续性假设。
实操建议:
- 在 vertex shader 中输出曲率时,用
flat out float v_curv替代out float v_curv,禁用插值 - fragment shader 中对
v_curv做 3×3 邻域中值滤波:float curv = median(vec3(v_curv, prev_curv, next_curv))(需用texelFetch查相邻像素,提前绑定曲率纹理) - 或者更稳的方案:把曲率烘焙进 R 通道的 1024×1024 纹理,UV 展开时用
OpenFlipper的UniformLSCM算法,避免 UV 拉伸扭曲曲率分布 - 切记:不要用
smoothstep对曲率做二次柔化——会抹掉真实磨损的非线性衰减特征
真正难的是青铜表面氧化层厚度与曲率的空间耦合关系——它不是逐顶点独立的,而是受重力沉积、手部接触频次等隐变量影响。工程上只能靠多组实拍图拟合曲率-颜色查找表,代码里硬编码反而失真。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











