体素化的定义,根据imagej[1]的介绍
Voxelization is the process of converting a data structures that store geometric information in a continuous domain (such as a 3D triangular mesh) into a rasterized image (a discrete grid).
翻译过来介绍把其他储存几何信息的数据结构转为体素的结构。体素的性质对比多边形有许多优点,因此在一些任务经常会使用体素(具体的优劣,本文不进行赘述)。
根据我们之前流程,我们需要搞清楚乐高化这个任务的输入输出是什么。对于游戏资产来说,我们常用三角形作为数据储存方式。因此输入的是三角形的模型,而输出则是乐高化后的(三角形的)模型。而体素化只是中间一个步骤。示意图如下:
2.体素化算法分析
体素化的算法有很多,这里列举几种常用的表面体素化算法。 A. 三角形-体素求交法[2]。该算法输入三角形和Box(也就是更泛化的体素,由Center和Extent构成,也叫做AABB),输出bool判断是否有交点。
利用这个算法,我们有两种做法,一是For Each Grid,利用BVH Query这个Grid可能覆盖的三角形,求交,填入结果;二是For Each Triangle,求出其Bounding Box包裹的体素,然后对于每个体素进行这个算法进行求交。这两个方法各有优劣,本文不过多分析复杂度。前者可以无锁进行多线程加速,后者可以通过原子操作也进行多线程加速。(个人偏好后者) B.光栅化。该算法最初是在SVOGI(或者VXGI)里经常用到的。原理也很简单,通过正交视图的光栅化获得当前像素的深度来还原表面体素的位置。该算法可以通过关闭深度剔除来多次写入体素(没实现过,这里可能有误,但是意思大概是这样)来实现被自身遮挡的部分的体素化。
vxgi的配图
C.多次光栅化。该算法是B的简化版。我们知道,体素可以看作是一堆相同维度的图像的堆叠,换句话说沿着轴,每个Slice都是一张图像。我们可以通过让正交相机在体素BoundingBox范围内For Each Slice进行捕获,慢慢堆叠出来一个完整的体素模型。这个功能笔者也曾经在UE中复现过,具体可以参考,比较Tricky这里不在赘述。 D.LevelSet。其实就是把Mesh转为有向距离场,然后在水平集=0的地方(也就是和三角形距离为0的地方)填入体素。该步骤可以直接简化为,对于每个体素的Grid,找到最近三角形的距离,如果小于某个阈值则写入体素。