光照贴图的参数化

正如Jon在上一篇文章中所解释的那样,我们在《见证者》中使用了预先计算的全局照明,而我的首要任务之一就是开发该系统。

我开发了一些有趣的技术来计算自动参数化,以一种可以轻松映射到 GPU 的方式制定照明计算,并通过使用辐照度缓存来加速它们以较低频率执行。 这些东西都不是非常前沿的,但我遇到了一些通常在文献中被忽视的有趣问题,并提出了一些我认为值得分享的创造性解决方案。 然而,回想起来,我认为我也犯了一些错误,但我希望诚实地对待这些错误可以帮助我在未来避免这些错误。

在第一篇文章中,我将描述我已经实现的光照贴图参数化算法,在接下来的几篇文章中,我将介绍我们的照明系统的其他细节,例如我们使用半立方体执行最终聚集的方法以及我们的辐照度缓存的实现。

为了使用预先计算的照明,我们需要一种将这些照明计算映射到表面的方法。 一种可能性是按顶点存储它们,但在许多情况下,这不能提供足够的分辨率,并且照明的插值使网格的三角剖分相当明显。 许多游戏通过用高纹理和法线贴图细节来补偿光照细节的缺乏来解决这个问题,但这与Jon想要实现的图形风格不太相符。 因此,我们决定创建对象的完整参数化,以便将预先计算的光照存储到光照贴图纹理中。

NSDT工具推荐: Three.js AI纹理开发包 - YOLO合成数据生成器 - GLTF/GLB在线编辑 - 3D模型格式在线转换 - 可编程3D场景编辑器 - REVIT导出3D模型插件 - 3D模型语义搜索引擎 

手动创建这些参数化是可能的,但这很耗时,我宁愿让我们的艺术家做一些更有趣的事情。 因此,我们决定自动创建参数化。 然而,迄今为止我所犯的最大错误是没有更仔细地研究实现这一目标的可用解决方案。 我已经有了一些实现的部分,并且我高估了将它们组合在一起并产生可靠结果所需的工作量。 在与 GDC 的一些朋友谈论此事时,其中一位问我为什么不使用微软的 UVAtlas 工具,令我沮丧和尴尬的是,我唯一的答案是我没有想到这一点。 我认为这证明了在像我们这样的小团队中对我们的发展持开放态度是多么有价值。

现在我已经解决了这个问题,让我们谈谈技术。 我们仅使用光照贴图来表示间接照明和静态区域灯的直接照明。 因此,我们的期望是光照贴图将相当平滑,并且接缝不会成为大问题。 因此,我们决定不投资保证无缝参数化的解决方案,而是使用相当传统的方法:我们首先将输入几何图形划分为具有磁盘拓扑的图表,单独对它们进行参数化,最后将它们打包到矩形纹理中。

1、分割

将网格划分为图表(charts)是迄今为止该过程中最复杂的步骤。 过去我尝试过使用层次聚类,但没有取得太大成功,所以这一次我决定使用类似于 Lloyd 算法的迭代聚类算法,与多图表几何图像 (MCGI) 论文中使用的算法相同。

与 Lloyd 的聚类算法一样,MCGI 算法在图表增长和重新播种阶段之间进行迭代。 图表的增长由基于法线偏差和面质心之间的距离的度量引导。 在每次图表增长迭代之后,都会选择图表最中心面的新种子,并重复该过程,直到种子位置不再改变。

我的 MCGI 算法实现效果还算不错,但并不总能产生良好的结果。 可以调整种子的数量和位置以获得所需的输出,但这需要一定量的用户干预,而这是不希望的。

部分问题在于,在这种情况下“好”的含义非常主观。 它通常意味着形状优美的图表,非常适合表面,产生几乎没有失真的参数化,具有相当直和凸的边界,并且大小大致相等。

为了使算法适应我们的目的,我做了两件事,修改了引导方法,以便自动选择初始种子数量,并使用指标组合来更好地控制结果。

为了选择初始种子数量,我只需将种子一一插入,并增长相应的图表,直到满足阈值。 此时,我选择一个尚未分配给任何图表的任意面并重复该过程。 当没有面留下时,所有种子并行地重新开始生长过程。

消除对初始条件的敏感性的常见策略是使用最远点启发式。 然而,我没有这样做,而是发现一种行之有效的方法是从已选择的图表中挑选最差的候选面孔作为下一个种子。

该算法的第二个重要变化是使用一组不同的指标。 MCGI 论文提出了一种将法向偏差与面部质心之间的距离结合起来的度量。 我发现使用绝对距离使得算法非常依赖于网格的镶嵌,并且测量距质心的距离有利于具有低纵横比的三角形。

我没有使用面之间的距离,而是只考虑了法线偏差,并将其与类似于 D 图表中提出的其他指标相结合:准可开发网格分割,并且考虑了圆度和直线度。

这些指标也有自己的问题,我必须以各种方式调整它们。 最重要的问题是它们以不受欢迎的方式限制了图表的增长。 例如,为了鼓励图表凸性,你可以将高因子与相应的度量相关联,但这会导致大量几乎凸的图表,一旦发现凸配置,就无法将其他面添加到图表中。 因此,我不使用这些指标来限制增长,而是仅使用它们来支持凸图或直线边界; 这使得图表可以自由生长,但仍然保留尽可能最凸和最直的形状。

在许多情况下有帮助的技巧是吸收艺术家的一些意见,但不会给他们带来任何额外的负担。 一种简单的方法是考虑网格的现有参数化。 我们的对象已经具有用于纹理的参数化,并且艺术家倾向于将纹理接缝放置在不容易看到的位置。 将图表的边界与现有的接缝对齐不仅减少了接缝的总数,而且还导致图表以更好地匹配艺术家手动完成的方式演变。

我独立考虑了纹理和正常接缝。 由于我们的参数化用于照明,因此我更严格地遵循法线接缝并与其角度成比例,不这样做会导致拐角显得不太明确或更模糊。 这也有助于该过程在具有许多硬边缘的架构网格中更快地收敛。

最后,我没有施加任何图表拓扑限制。 我特别希望只要指标低于所需的阈值,图表就会围绕网格中的孔生长。 我很想使用更好的代理拟合指标而不是正常偏差指标,但这会生成必须切割的圆柱形或圆锥形图表,而我不想处理这个问题。 关闭另一侧的洞相当容易,只需检测边界并关闭所有边界,但最长的一个。

2、参数化

对于图表参数化算法,我们只需使用最小二乘保形映射,因为我已经有一个可用的实现。 我的实现基于 SIGGRAPH 2007 网格参数化课程笔记中的算法描述,我发现它比原始论文中的更容易理解。 特别有用的是关于数值优化的章节,尽管如果我必须再次编写一个稀疏矩阵求解器,我可能会使用 OpenNL,因为它现在已经在自由 BSD 许可证下发布。

LSCM 并不是最好的参数化算法。 它在大多数情况下工作得很好,尽管在一些罕见的情况下它会导致小的自我重叠。 这发生在两种情况下:

  • 输入中的零面积三角形有时会在参数化中翻转。
  • 具有复杂边界的图表,在参数化时会自相交。

第一种情况是由输入网格中的 T 形接头引起的,这些 T 形接头被检测为孔并填充有退化三角形。 在实践中,参数化中的小重叠并不是真正的问题,因此我们不修复输入,而是计划将这些问题报告给导出器中的美工人员,并让他修复它们(如果事实证明这会导致伪影)。

在第二种情况下,增加聚类过程中使用的凸性度量的权重使我们能够防止这些错误。 所以,我并没有真正采取任何措施来解决这个问题,但到目前为止这还不是一个问题。

即使在那之后,我们仍然存在一些有问题的案例。 我注意到 Blender 中的实现没有遇到同样的问题,并且可以更优雅地处理这些情况。 因此,我询问了 Brecht Van Lommel,他建议使用基于 LSCM 的 ABF 公式的替代矩阵权重,这似乎消除了剩余的问题。

虽然 LSCM 非常容易实现,但它绝对不是最好的参数化方法。 如果我要实现更好的东西,我可能会考虑 LinABF 或拟合引导梯度场。 然而,由于单个图表的参数化是目前最快的步骤,因此考虑更昂贵的变形分析方法可能是有意义的。

3、打包

我们的打包(packing)算法相当简单。 与许多其他实现一样,我们首先按参数区域对图表进行排序,旋转它们以将图表与其最适合的矩形对齐,然后将它们一一引入到图集中。 理想情况下,我应该测试所有 4 个可能的方向,但目前我只是随机选择其中一个方向。

我没有使用类似俄罗斯方块的方案来找到每个图表的最佳位置,而是使用了一种更强力的方法,其中考虑了所有可能的位置。 我使用保守的光栅化器来实现这一点,该光栅化器标记图表所触及的所有纹素,再加上一个用于填充的额外纹素。 随着新图表的插入,我逐渐增加纹理范围。 如果找到当前范围内的位置,则自动接受图表,否则将评估度量以确定增加地图集范围最少的位置。 由于我使用贪婪算法,最小化面积会导致地图集具有非常高的纵横比。 因此,我反而最小化了结合范围和周长的度量,并产生了大部分方形地图集。

以下是一些结果示例:

一旦我们使用光照贴图压缩,将图表与 DXT 块边界对齐以防止渗色伪影可能是有意义的。

4、未来的改进

这是我认为有很大改进空间的领域之一,但与此同时,花费更多时间来改进结果并没有太多!。 尽管尚未在生产中进行测试,但我认为我们当前的解决方案运行得相当好。 如果有更大的图表,失真更少或接缝数量更少,那就太好了,我肯定会很乐意做这件事。 然而,这并不会让游戏运行得更快或者看起来更好。 我们计划在某个时候发布这些算法的源代码,所以我希望随着其他人采用它并改进它以满足他们的需求,实现会逐渐变得更好。

也就是说,如果我认为有一个领域值得投资,那就是信号专用参数化的使用。 关于该主题的研究论文(信号专用参数化和分段线性重建的信号专用参数化)在我们的设置中可能有点过分了,而且我不确定它们是否能很好地处理我们的低分辨率网格。

《半条命 2》通过使用艺术家为每个表面指定的采样率来实现这一点,但我认为使用类似于 Bungie 提出的方法自动实现这一点是值得的,该方法看起来相当简单,并且提供了更复杂的方法所获得的大部分收益给我们。

我的期望是,除了一些小的调整和轻微的调整以处理将来可能出现的问题案例之外,当前的实施不会发生重大变化。 如果有人对此类算法有任何经验,我很想听听。 我特别想知道你是否会采取不同的做法,或者是否有任何我可能忽略的优化或改进,而你认为值得考虑。


原文链接:光照贴图参数化 - BimAnt

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/590616.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【如何选择Mysql服务器的CPU核数及内存大小】

文章目录 🔊博主介绍🥤本文内容📢文章总结📥博主目标 🔊博主介绍 🌟我是廖志伟,一名Java开发工程师、Java领域优质创作者、CSDN博客专家、51CTO专家博主、阿里云专家博主、清华大学出版社签约作…

Codeium在IDEA里的3个坑

转载自Codeium在IDEA里的3个坑:无法log in,downloading language server和中文乱码_downloading codeium language server...-CSDN博客文章浏览阅读1.7w次,点赞26次,收藏47次。Codeium安装IDEA插件的3个常见坑_downloading codeiu…

4-2. AOP细节

1 AOP细节 1.1 切入点表达式 1.1.1 作用 通过表达式的方式定位一个或多个具体的连接点。 1.1.2 语法细节 1)切入点表达式的语法格式 execution([权限修饰符] [返回值类型] [简单类名/全类名] 方法名) 2) 举例说明 3)在AspectJ中,切入…

通过国家网络风险管理方法提供安全的网络环境

印度尼西亚通过讨论网络安全法草案启动了其战略举措。不过,政府和议会尚未就该法案的多项内容达成一致。另一方面,制定战略性、全面的网络安全方法的紧迫性从未像今天这样重要。 其政府官方网站遭受了多起网络攻击,引发了人们对国家网络安全…

小肥柴慢慢手写数据结构(C篇)(5-2 AVL树)

小肥柴慢慢学习数据结构笔记(C篇)(5-2 AVL树 目录5-5 AVL出现的原因5-5-1 平衡树5-5-2 平衡二叉树的具体案例 5-6 AVL平衡策略的讨论5-7 不使用平衡因子的实现(黑皮书,训练思维)5-8 使用平衡因子的实现&…

普中STM32-PZ6806L开发板(USART2 串口 + HI-LINK-V20离线语音模块控制LED灯)

简介 买了HI-LINK-V20型号的离线语音识别模块, 为了后面可以做有意思的东西, 现在先来用用, 使用USART2 串口 接收来自我在HI-LINK-V20中预设的动作, 当识别到词条时发送对应的指令到串口, HI-LINK串口接的就是STM32F03ZET6的USART2, 且往下看。 电路原理图 连线图 连线引脚表…

Linux:/proc/sys/vm/目录各文件详解

目录 前言一、/proc/sys/vm/目录各文件二、相关功能的API函数 前言 /proc/sys/vm/ 目录是 Linux 系统中的一个特殊目录,它包含了与虚拟内存子系统相关的系统内核参数。这些参数可以用来配置系统的虚拟内存管理策略,包括内存分配、页面置换、内存压缩、NU…

数据结构【线性表篇】(四)

数据结构【线性表篇】(四) 文章目录 数据结构【线性表篇】(四)前言为什么突然想学算法了?为什么选择码蹄集作为刷题软件? 目录一、栈(一)、栈的顺序存储(二)、栈的链式存储(三)、共享栈 二、队列(一)、队列的顺序存储(二)、队列的…

Nginx 不同源Https请求Http 报strict-origin-when-cross-origin

原因: nginx代理配置url指向只开放了/* 而我/*/*多了一层路径 成功:

2024新版塔罗占卜网站源码风水起名附带搭建视频及文本教程

附带文本教学及视频教程安装方法以linux为例: 1、建议在服务器上面安装宝塔面板,以便操作,高逼格技术员可以忽略这步操作。 2、把安装包文件解压到根目录,同时建立数据库,把数据文件导入数据库 3、修改核心文件conf…

python多环境管理工具——pyenv-win安装与使用教程

目录 pyenv-win简介 pyenv-win安装 配置环境变量 pyenv的基本命令 pyenv安装py环境 pyenv安装遇到问题 pycharm测试 pyenv-win简介 什么是pyenv-win: 是一个在windows系统上管理python版本的工具。它是pyenv的windows版本,旨在提供类似于unix/li…

cargo设置国内源 windows+linux

cargo默认的源比pip的源好多了,但是有时候速度还是很慢 一、部分国内源(排名不分先后) 这些源的格式用在具体的配置文件中 中国科学技术大学 [source.crates-io] replace-with ustc[source.ustc] registry "git://mirrors.ustc.ed…

Redis Cluster集群模式学习

Redis Cluster集群模式 Redis哨兵模式:https://blog.csdn.net/liwenyang1992/article/details/133956200 Redis Cluster集群模式示意图: Cluster模式是Redis3.0开始推出采用无中心结构,每个节点保存数据和整个集群状态,每个节点都…

[C#]OpenCvSharp结合yolov8-face实现L2CS-Net眼睛注视方向估计或者人脸朝向估计

源码地址: github地址:https://github.com/Ahmednull/L2CS-Net L2CS-Net介绍: 眼睛注视(eye gaze) 是在各种应用中使用的基本线索之一。 它表示用户在人机交互和开放对话系统中的参与程度。此外,它还被用…

C/C++面向对象(OOP)编程-回调函数详解(回调函数、C/C++异步回调、函数指针)

本文主要介绍回调函数的使用,包括函数指针、异步回调编程、主要通过详细的例子来指导在异步编程和事件编程中如何使用回调函数来实现。 🎬个人简介:一个全栈工程师的升级之路! 📋个人专栏:C/C精进之路 &…

再见2023,你好2024!

大家好,我是老三,本来今天晚上打算出去转一转,陆家嘴打车实在太艰难了,一公里多的路,司机走了四十分钟,还没到,再加上身体不适,咳嗽地比较厉害,所以还是宅在酒店里&#…

用通俗易懂的方式讲解大模型:使用 Docker 部署大模型的训练环境

之前给大家介绍了主机安装方式——如何在 Ubuntu 操作系统下安装部署 AI 环境,但随着容器化技术的普及,越来越多的程序以容器的形式进行部署,通过容器的方式不仅可以简化部署流程,还可以随时切换不同的环境。 实际上很多云服务厂…

Java ArrayList在遍历时删除元素

文章目录 1. Arrays.asList()获取到的ArrayList只能遍历,不能增加或删除元素2. java.util.ArrayList.SubList有实现add()、remove()方法3. 遍历集合时对元素重新赋值、对元素中的属性赋值、删除元素、新增元素3.1 普通for循环3.2 增强for循环3.3 forEach循环3.4 str…

目标检测-Two Stage-Mask RCNN

文章目录 前言一、Mask RCNN的网络结构和流程二、Mask RCNN的创新点总结 前言 前文目标检测-Two Stage-Faster RCNN提到了Faster RCNN主要缺点是: ROI Pooling有两次量化操作,会引入误差影响精度 Mask RCNN针对这一缺点做了改进,此外Mask …

数据结构——顺序栈与链式栈的实现

目录 一、概念 1、栈的定义 2、栈顶 3、栈底 二、接口 1、可写接口 1)数据入栈 2)数据出栈 3)清空栈 2、只读接口 1)获取栈顶数据 2)获取栈元素个数 3)栈的判空 三、栈的基本运算 四、顺序栈&…