前段时间基本上完成了场景编辑器的大部分工作,现在已经可以用它生成自己需要的网格模型了。目前,在编辑器中对生成的网格是指定面的法向量,这对于用场景生成BSP等相关操作已经足够了。不过为了测试BSP的健壮性,准备实现一下基于BSP的光线跟踪算法来看看效果,于是只是指定面的法向量就显得不太够用,因为在逐像素作着色时就需要对面上各个点的法向量进行插值,因此就需要各个顶点的法向量。查了下相关的资料,找到了一种简单但却有效的顶点法向量生成算法。
最简单也是最直接的求顶点的法向量的方法是遍历此顶点所关联的所有三角形,将这些三角形上的法向量单位化后叠加,然后求出法向量的均值即可。
vertexNormal = 0,0,0;
foreach triangle connect to current vertex;
vertexNormal += triangleNormal;
vertexNormal /= connectedTriangleNums;
但这样求出的法向量往往效果不好,特别是当一些很小的多边形共面时。为了解决这个问题就需要使各个三角形并不是简单的等比例贡献法向量。直观上很容易发现,每个三角形与顶点相关联的那个角的大小是变化的,因此就可以使用此角度的大小来作为单个三角形对顶点法向量的贡献因子。
vertexNormal = 0,0,0;
totalAngle = 0;
foreach triangle connect to current vertex;
angle = acos(dot(edge1 , edge2));
vertexNormal += trangleNormal * angle;
totalAngle += angle;
vertexNormal /= totalAngle;
在实现时要注意,使用的角为关联当前顶点的那个角。
末使用顶点法向量进行的渲染:
使用计算出的顶点法向量的渲染: