Tetrahedron based light probe interpolation(基于四面体的Light Probe插值)

在当前的游戏引擎中,使用Light Probe来计算全局环境光对于动态物体的影响是一种很主流的方法。在预处理阶段生成完场景的Light Probe之后,传统的方法采用查找最近的8个相邻的Probe然后使用三线性的方式(Trilinear Interpolation)进行插值,但是这样的插值代价稍大,不过一个可行的优化就是尽可能地减少插值中使用的Probe的数量,比如由8个减少到4个不等。但是这时就不能再用三线性插值,而需要用其它的插值方法比如Inverse Distance等,不过这样就会带来另外一个问题,那就是使用的Probe一般是最近的几个(如三个到四个),如此一来当物体移动之时得到的最近Probe变化可能会比较明显,进而得到的插值结果也会不太连续,影响效果。今年的GDC上Unity的一篇Presentation提到了使用四面体来进行无序Probe的插值,稍花了些时间简单实验了下,还是蛮不错的。文章可以在这里看到:Slide,其最大的一个特点就是Probe可以无序地随机分布,这样在编辑器里边添加以后对美工还是蛮友好的。

四面体网格的生成

为了对Probe所对应的点集使用基于四面体的插值,首先就需要生成这堆点集所对应的四面体集合,这个问题属于传统几何图形学的典型问题,解决方法也很多,比如广泛用在三角细分算法中的Delaunay方法(Paper)。使用Delaunay的方法可以实现对三维空间点集的四面体化操作,不过鉴于此操作不是所关注的问题的关键所在,可以借助于已有的代码来完成该步骤。比如这里就有一个开源的代码库:TetGen(作者应该是一个身在德国的中国哥们)可以完成点集的四面体切分,当然这个里边还有其它不少更高级的功能,感兴趣也可以学习一下。它支持输入很简单的点集描述,然后在一些简单的配置参数下计算得到该点集的四面体化结果。比如对一堆随机生成的点集的四面体化效果如下所示:

四面体重心坐标的计算

要使用四面体对一个给定的目标点进行插值,就要计算其相对于该四面体的重心坐标,也即是其相对于四个顶点的权重比值。这个操作要在每次Probe进行更新的时候都需要进行,因而就要求效率尽可能地高,之前的blog中介绍了使用有向平面距离的方法来计算四面体重心坐标的方法,效率还可以。

其中,这里边的有向距离1 / D(a,PLbcd), 1 / D(b,PLacd), 1 / D(c,PLabd), 1 / D(d,PLabc)对于每个四面体来说均是固定的,因而就可以存储到每个体数据中以便加快效率。

空间数据结构的组织

由于常规的Probe分布是由对应的AABB或OBB来进行定位的,这样在查找目标点所对应的邻近Probe时可以直接进行对应。因为一个区域内的Probe一般是在三个方向上均匀分布的,也就相当于一个三维的数组结构,这样给定一个目标点的位置,就可以直接根据Probe的密度、各个方向上的size及step直接定位到其周边的相邻Probe (AABB 的操作最直接,对于OBB则需要做一个局部坐标系的转换,之后就跟AABB的计算相同),因而这种情况下对于整个Probe数据的组织就比较简单。但是使用基于四面体的方式之后,由于原始Probe的无序,因而这里的数据结构组织就较常规的方法有些区别。首先,对于四面体组织的网格,需要知道四面体间的拓扑信息,也即通过一个四面体能够找到其邻接的四面体,如果用ID来对应每个四面体的话那么在每个四面体中就需要添加四个存储其相邻体的ID数组。另外,由于四面体插值的频繁进行,而这里的插值方法又是使用面的方程来进行,因而就可以将每个面的描述信息也进行存储,这样来提高效率。但是四面体的面是可以公用的,虽然一个面最多只能被两个四面体共用,但还是有必要在存储前来删除冗余。这样其实最终的数据结构就可以如下描述:

  • 点:点的位置;关联的Probe的ID或指针;
  • 面:关联的三个点的ID;面方程;
  • 体:关联的四个面的ID

当然,在上述描述的具体实现过程中还会有其它若干细节,比如要注意组成四面体的点与面之间的对应关系,以便正确找到下一个关联的四面体等;不过这些都比较琐碎且也是具体实现相关。

查找与插值的处理

由于在上述数据结构中存储了四面体之间的拓扑结构,因而在进行目标点对应的四面体定位时就可以使用这些拓扑信息。首先,对于点与四面体的关系及其对应的重心坐标可知:如果一个点在四面体内部,那么它对应的重心坐标均属于[0,1];否则,就可以通过重心坐标的越界方式找到下一个其可能位于的四面体,如此进行若干次迭代之后就可以正确定位到其所在的四面体,或是到达所有四面体集合的边缘。为了快速定位一个点对应的四面体,可以有多种方法:

  1. 选择所有四面体中处于较中心位置上的一个四面体作为Spawn点,来进行目标体的查找(Presentation中使用的方法)
  2. 随机选择一个四面体作来初始点,来进行目标体的查找
  3. 使用各种空间分割方法,如BVH等来对四面体集进行空间组织后加速目标体的查找

当然,在使用上述方法的过程中又会有多种优化方式,比如一些信息的Cache,像记录上一次的目标四面体作为下次查询的初始点等。

对于目标点位于四面体集合外侧的情况,使用边界扩展的方法来进行插值计算。如上图所示(以2D情形为例),其中的黑色线条为体集合的外缘,而绿色区域为每个三角面向外侧的扩充;其中的绿色线条方向为交界顶点处的法向量(这其实也相当于计算每个外表面对应的Voronoi区域)。然后,对于每个目标点P通过投影得到其对应的原始三角面中的位置P‘,以P‘计算其对应三角形的重心坐标后用此三角形上的三个点来插值得到P点的最终结果值。但是这种方法会在集合外侧得到与到集合表面距离无关的插值结果,而实际情况中想要的应该是:外侧体面对于目标点的影响应该随着该点到面的距离增大而减弱。不过这个也比较简单,可以对最终的外缘插值结果再增加一个针对距离d的衰减变化即可。

与常规方法的比较

最后,将基本四面体的Probe插值方法与传统的插值方法进行对比。整体来说,这种方法还是不错的,如果引擎中有之前的均匀分布的Probe系统之后,修改到这种基于四面体插值还是比较容易的。由于Probe的均匀分布,因而可以不错助于其它方式(如TetGen)而直接生成其所对应的四面体网格,而对于数据结构的修改也不是很大。对于某一个物体记录四面体Cache之后的查找更新操作也是比较快的。就算不带来效率提升也不至于也不用损失太多的性能(具体数据还木有来得及对比)。不过使用基于四面体的方法之后最大的一个优势就是可以在引擎中将此前以Probe集合为基本单位的Probe系统转化为以单个Probe为基本单位的新系统,Probe的生成与控制方式更加灵活,Unity里应该就是这种方法。

其它的一些优化

  1. 在边界插值时可以将距离变化影响也考虑在内,这样只需针对d施加一个合适的衰减函数即可(线性或非线性的)。但是要注意此函数在d=0点处的值应为1,以保证落在边缘表面上的点的插值结果的正确性。
  2. 可以使用Least Square的方法并结合四面体的插值描述来对整个Probe系统进行优化,这样在给定一定的误差阈值之后,就可以减少Probe的数量。

下述为一些实验效果:其中的Probe是在一个指定的区域范围内以均匀的分布方式随机生成,数量为512个;Probe的球谐值采用球面蒙特卡洛采样方式计算得到;每个Probe球面上采样1024个点,场景采用BVH空间分割来加速求交测试:

其中的黑色线框即为当前角色中心所处于的四面体,从中可以看出:两个邻近不同位置的目标点对应了两个相邻的不同四面体。

转:http://blog.csdn.net/bugrunner/article/details/7485475

时间: 2024-10-29 03:38:11

Tetrahedron based light probe interpolation(基于四面体的Light Probe插值)的相关文章

SQL Standard Based Hive Authorization(基于SQL标准的Hive授权)

说明:该文档翻译/整理于Hive官方文档https://cwiki.apache.org/confluence/display/Hive/SQL+Standard+Based+Hive+Authorization#SQLStandardBasedHiveAuthorization-ObjectPrivilegeCommands. Hive 0.13版本之前的授权现状   Hive默认授权(Default Hive Authorization (Legacy Mode)) 设计目的并不是为了防止恶

基于GDAL的栅格图像空间插值预处理

转自 基于GDAL的栅格图像空间插值预处理——C语言版 基于GDAL的栅格图像预处理 前言 栅格数据和矢量数据构成空间数据的主要来源,怎样以开源方式读取并处理这些空间数据?目前有多种开源支持包,这里只介绍GDAL包.GDAL包的优点是支持库简洁.支持栅格和矢量.与多种开发平台结合.OpenGis方式读取空间数据,有利于自己编写程序进行图像预处理和智能识别等等,比如:遥感影像的降噪.锐化:红外图像的林火识别:工厂监控视频识别等等.本文中利用GDAL包读取高程栅格DEM,并添加气象自动站点的数据,进

基于Unity3D三维模型的动作插值(空间关键帧动画实现)

1.引言 最近在Unity3D中实现一个基于自定义Mesh网格的骨骼动画.存储关键帧信息,然后通过插值形成中间动画.网格GameObject之间存在父子关系.插值动画对模型骨骼的Position.Sclae.Rotation三个部分分别混合插值. 并且注意,一般选取的是子骨骼相对父骨骼的Transform信息,即上述关键帧信息具体应该为Transform.localPosition.localScale.localRotation. 并且这个系统的关键帧是定义在三维空间中的,用户在一系列关键帧点

基于边界的模板匹配的原理及算法实现

最近被Halcon中的基于边缘的模板匹配算法吸引到了,故找到了一点点学习资料,供同行参阅,水平有限,大家多包含.本文算法很初级,做入门了解用.原文是英文,所以把原文copy 过来了,另加了一些中文.算法运行效果如下: [效果还行,只是原理性示意,不要要求太高了哦] Introduction Template matching is an image processing problem to find the location of an object using a template imag

Light Weight CNN模型的分析与总结

本文选择了4个light weight CNN模型,并对它们的设计思路和性能进行了分析与总结,目的在于为在完成图像识别任务时模型的选择与设计方面提供相关的参考资料. 1 简介 自AlexNet[1]在LSVRC-2010 ImageNet[22]图像分类任务上取得突破性进展之后,构建更深更大的convolutional neural networks(CNN)几乎成了一种主要的趋势[2-9].通常,获得state-of-the-art准确率的模型都有成百上千的网路层以及成千上万的中间特征通道,这

基于C++11的call wrapper

要在C++中应用AOP,不像在其他的基于解释器的语言中那么方便,作为一种静态语言,如果给函数或者类的方法造一个wrapper,在wrapper里面嵌入调用前的代码和调用后的代码,也能达到一定程度的代码织入的效果.在C++11之前,要给一个函数或者方法做个能返回调用结果的wrapper并不简单,会比较复杂,而在C++11里面可以使用function模版,以及函数返回类型的推定,通过生成一个内嵌类的对象的构造函数来执行before动作,析构函数来实现after动作,而具体的before和action

【基于url权限管理 shiro(一)】--基础

只要有用户参与的系统一般都要有权限管理,权限管理实现对用户访问系统的控制,按照安全规则或者安全策略控制用户可以访问而且只能访问自己被授权的资源.权限管理包括用户认证和授权两部分.   用户认证 1.概念 用户认证,用户去访问系统,系统要验证用户身份的合法性.最常用的用户身份验证的方法:1.用户名密码方式.2.指纹打卡机.3.基于证书验证方法..系统验证用户身份合法,用户方可访问系统的资源. 2.用户认证流程   3.关键对象 subject:主体,理解为用户,可能是程序,都要去访问系统的资源,系

基于请求的分布式互斥算法

一个悲剧的文章,研究的东西确实比较老,但是因为这些研究,让我对分布式的底层的关系有了更加清晰的认识,也算是不枉此功. 下面贴出来核心的部分. 引言 分布式系统中的一组进程可能会同时访问一个资源或者同时执行一个给定的函数,我们称这些资源或者函数为临界区(Critical Section),若不加控制的话,会造成资源或者环境的不一致的现象.保证任何给定时刻只允许一个进程或者给定的进程去执行临界区的算法称为互斥算法.互斥也可以称为并发控制. 这个问题最早由Dijkstra[1]在1965年提出.互斥可

基于虎书实现LALR(1)分析并生成GLSL编译器前端代码(C#)

基于虎书实现LALR(1)分析并生成GLSL编译器前端代码(C#) 为了完美解析GLSL源码,获取其中的信息(都有哪些in/out/uniform等),我决定做个GLSL编译器的前端(以后简称编译器或FrontEndParser). 以前我做过一个CGCompiler,可以自动生成LL(1)文法的编译器代码(C#语言的).于是我从<The OpenGL ® Shading Language>(以下简称"PDF")找到一个GLSL的文法,就开始试图将他改写为LL(1)文法.等