高级计算机图形学:体积渲染

Volume Rendering

Posted by R1NG on November 30, 2022 Viewed Times

体积渲染

本章介绍体积渲染的概念和两种相关技术: 直接体积渲染与间接体积渲染.

在实际场景中, 除了渲染和绘制物体的 外表面, 我们可能还需要关注物体的 内部结构: 考虑如何渲染和绘制 并不具备表面信息 的物体数据. 渲染这类数据的工作就被统称为 体积渲染.

体积渲染的数据来源是对现实物体的某种 三维测度 (3D-Dataset), 它可以通过声纳扫描, CT 扫描, MRI 扫描等方式得到, 也可以使用地面穿透雷达等设备获取. 无论使用什么设备或手段采集什么物体的数据, 得到的数据类型必须表示为 三维数组, 称为 Volume Set, 而这些三维数组中的每一个 entry 都被称为 voxel, 和二维数组中的 cell 对应.

下面首先考虑第一种体积渲染技术: 直接体积渲染.

直接体积渲染 Direct Volume Rendering

直接体积渲染的基本流程类似光线追踪: 从视点穿过视平面向 Volume Set 射出一束 “光线”, 然后通过一系列的计算决定视平面上的对应位置上像素的颜色.

和光线追踪中, 每一次射出的光线和场景中的任何物体交互时都会生成新的 secondary rays 不同, 在直接体积渲染中, 只要光线射出视平面, 在对这一条光线的追踪过程中, 我们从始至终只考虑这同一条光线. 在光线穿透 Volume Set 的过程中, 我们将 Volume Set 对光线的 “颜色效果”“透明度效果” 进行 累积, 从而计算出这束光线应有的颜色: 光线穿透每一个 Voxel 时, 这个 Voxel 都需要能够对光线的颜色和其本身的透明度产生影响, 最后这些影响反映为: 改变光线的颜色, 或将 “光线的透明度余额” 消耗光使其停止传播.

要实现这一点, 就需要首先为 Volume Set 中的 Voxel 赋予 颜色和透明度.

首先需要考虑的问题是: 如何从 本质上不具备颜色信息的 Volume Set构造 出颜色. 由于体积渲染的使用场景中往往 并不关注物体的真实颜色 而只关心 能否看出立体物体中是否存在某些不正常的结构或值得关注的现象, 因此我们只需要设法 区分出 Volume Set 中含有哪些不同的物质, 然后给这些物质分别赋予足以起到区分作用的颜色即可.

因此, 我们从现在开始假设每个 Voxels只存储了一个数值. 首先统计并绘制 Voxels 数量与其存储数值的直方图, 类似图像处理中的图像灰度值直方图. 这个直方图所表示的就是 对于给定的一个 Voxel 值, 它属于某一类材质或某一类材质的混合的概率分布: 图中的波峰对应不同的材质, 而波谷可以表示材质与材质之间的 过渡.

20221226121441

换言之, 它允许我们统计在给定的 Volume Set 中大致包含了几种不同的材质, 以及给定一个 Voxel 值, 我们可以推测这个 Voxel 大概属于哪一种材质.

20221226121809

随后, 我们为 Volume Set 中不同的材质赋予不同的颜色, 随后我们可以基于 是否希望让这个材料在渲染结果中可见 来决定不同材料的 透明度.

为了避免渲染时出现明显的 锯齿效应 (Aliasing Effect), 我们往往需要在执行渲染前对 Volume Set 进行 Trilinear Interpolation 从而获得更具表达力的采样值.

其基本逻辑是: 对 Volume Set 中的任何点, 考虑如下图所示的八个邻接点, 然后基于这八个点的数据值对这个中心店的数值进行平滑.

20221226122122

在完成对 Volume Set 的数据处理后, 就需要进行 “光线追踪” 实现最后一步的渲染. 在直接体积渲染中, 基于此前所计算的, Volume Set 中每个 Voxel 的颜色值和透明度值, 我们记录射出光线在穿透 Volume Set 过程中碰到的所有 Voxel, 并对这些不同 Voxel 的颜色值和透明度值进行 累积, 最终判断光线何时停止传播, 以及光线的颜色如何.

20221226122936

使用合适的颜色和透明度组合, 基于直接体积渲染方法, 渲染得到的图像会由于 不具备局部阴影 而显得 并不立体. 这是因为直接体积渲染并不会得到任何关于 物体表面平面 的特征, 由此我们无法计算出真实的阴影效果.

20221226122923

但是, 我们仍可以 基于某个 Voxel 的值关于其 $x, y, z$ 方向的变化趋势 为这个点计算出 “假的曲面法线” (Faux Surface Normal Vector), 然后使用这些假的曲面法线在局部光照模型中渲染出一定的阴影效果.

可见, 直接体积渲染和光线追踪与路径追踪一样, 其渲染效果依赖于视点的位置, 只要视点位置发生变化就必须重新执行渲染的步骤. 但由于整个渲染流程直接基于给定的数据, 因此也有渲染效果更真实, 不会丢失细节, 也不会包含任何人为构造的细节的特点.

间接体积渲染 Indirect Volume Rendering

另一种体积渲染方式是 间接体积渲染. 由于现代 GPU 不支持端到端的快速直接体积渲染能力, 因此衍生出了 间接体积渲染: 和直接体积渲染不同, 它并不会 直接基于 Volume SetVoxels 存储的数据渲染出视平面上的画面, 而是先 基于这些数据进行三维建模, 在 推断出 数据集中蕴含的多边形立体模型后, 再对得到的立体模型进行渲染. 显然, 渲染用多边形表示的物体表面速度更快, 效率更高.

间接体积渲染的基本假设是: Volume SetVoxels 存储的数值可以如同 等高线上的高度数值 一样看作是 区分某个位置在平面内或平面外的依据, 因此可以基于这些信息一步步地构造出小的平面区块 (Patches), 由此逐步构建出完整的曲面多边形表示, 也就是所谓的 “等高面”. (ISO Surface)

在二维平面中寻找等高线是非常容易的, 这种情况下所需要考虑的只是在单个方向上, 相邻的两个点的值之间的差别: 如下图所示: 考虑分划值为 $55$, 横向切割平面的等高线. 为了让起到分划作用的等高线更平滑, 还可以对直接找到的折线进行平滑操作, 得到曲线, 尽管这样得到的分划曲线本质上是 不精确 的.

20221226123438

在三维空间中寻找用于分划曲面的 “等高面” 远比二维平面中的情形困难. 一种实现这一目标的技术是 Marching Cubes: 它考虑 Volume Set 中一个个由 $8$ 个 Voxel 组成的小立方体, 并尝试基于 Voxel 的值将立方体中的 $8$ 个顶点分为 两类: 一类属于平面外的点, 另一类属于平面内.

这一技术的主要问题是 Ambiguity: 在许多情形下, Marching Cube 完全可以用多种 一样合理 的方式对立方体中的点进行 完全不同 的归类, 这就会实际上导致: 我们并不能确定性地渲染出多边形曲面表示, 而且更不能确定这种曲面表示是否正确.

20221226140034

另一种用于寻找并渲染 ISO Surface 的技术是 Proxy Geometry. 其基本思想是: 将物体视为一系列 和视角平行的 (半) 透明切片, 然后将 Volume Data 投影到这些切片上, 从而使得我们从平行的视角观察时, 也能够感受到由于切片在不同的深度上累积而呈现的, 类似深度的效果.

20221226140435

Proxy Geometry 的问题是: 在视角发生变化时, 这些切片会因为不再与视角平行而导致观测的结果不但失去立体感, 而且失去结构感, 难以辨识. 合适的解决方法是 重新渲染一组和新的视角平行的切片.

20221226140558

紧急补充:

Proxy Gemoetry 是所谓的 “代理几何体”: 因为在 Indirect Volume Rendering 中我们不直接使用 Volume Set 中的数据进行渲染, 而是需要先将它们转换成 某种 Proxy Gemoetry, 然后再去渲染这些 Proxy Geometry. 基于 Proxy Geometry 的不同, 本课程中介绍了两种 Indirect Volume Rendering 方法: 第一种是所谓的 Marching Cube: 基于判断每个立方体中八个顶点 “被某个或某些平面分为两个部分” 的总共 $256-2 = 254$ 种可能 (实际上考虑申必的对称性之后可以简化为 $14$ 种分划可能, 前面减去的 $2$ 分别对应所有八个顶点都在平面的一边或另一边的情况), 在每个立方体中构造多边形曲面; 而第二种原本在本笔记中称为 Proxy Geometry 的方法其实叫 Splatting: 将计算得到的多边形 “溅射” 到一系列和视角平行分布的切面上. 并且此处不加说明地给出结论: Splatting 也是 Viewpoint dependent 的.

同时, 对这些多边形的渲染可以有下列的方法: Shear WrapTexture Mapping.