博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
聊聊LightProbe原理实现以及对LightProbe数据的修改
阅读量:5371 次
发布时间:2019-06-15

本文共 2351 字,大约阅读时间需要 7 分钟。

0x00 前言

最近工作比较忙,所以文章已经很久没有更新了。这篇小文的主题也是在出差的高铁上想到,因为最近和一些朋友聊天,发现他们中很多人的项目中都使用了多个实时光源。细问之下主要是某些物体,例如角色,在烘焙后的场景中显得不够突出,为了突出角色所以加入了更多的实时光源。但事实上这可能并非一个很好的选择。

0x01 间接光还是直接光

下面这张图片演示了只有直接光照以及加上了间接光照之后的对比。

GI_comparison_1.png
可以看到,直接光照抵达不到的地方的黑暗的部分要通过间接光照来照亮,而不是为了提高暗部的亮度再加一盏实时灯光。
事实上,如果场景中有大量的灯光——例如如果在上图中为室内增加大量补光来提高室内亮度——
还会造成场景中的明暗对比降低,画面显得更“平”。
这也是很多朋友的项目中场景中存在的一个比较常见的问题,即亮度不够灯光补。补着补着才发现,整个场景已经充斥了太多的灯光了,而场景也因此整体很亮,没有了明暗对比,结果就是视觉效果平的不真实。
相信各位也一定想到了,亮度不够灯光补这个思路的另一个实践——场景内的角色不够亮时也选择使用一个灯光来给角色补光——同样存在着和之前所说的一样的问题。
那么怎么提亮角色才更加合理一些呢?(虽然提亮角色这件事本身就不符合物理规则,但是为了游戏效果显然存在这样的需求)。如上图所示那样,利用间接光来照亮物体是一个不错的思路,不够亮?提高间接光的亮度。
在Unity中如何给动态物体提供间接光?这就引出了下面的主角——LightProbe。

0x02 LightProbe的核心

LightProbe主要解决了如何在动态对象和角色上使用烘焙的照明信息。

其实LightProbe的核心就是球面亮度信号编码和重建。
Light-Probe-Interpolation-Using-Tetrahedral

如果大家了解信号处理方面的知识的话,就会知道只要信号满足一定条件,就可以分解为一系列正弦谐波的和,谐波频率以倍频增长,这就是所谓的傅立叶级数。

而lightprobe也采用了类似的思路,使用了来对该球面上的亮度信号进行编码。

同样的,一个原始的亮度信号也可以分解为一系列带缩放参数的基函数之和,而我们只需要知道这些基函数的缩放系数就可以在运行时快速的重建原始的亮度信号了。

Spherical_Harmonics.png

但是有一个问题,那就是如果要完美的重建原始光照信号的话,显然需要很多很多甚至是无穷项球谐函数。但是好在LightProbe中保存的主要是一些低频的光照信息,换句话说,它没有高频率变化,所以如果我们通过丢弃所有更高的频率来压缩球体上的频域数据,没有人会注意到。所以这里我们可以只取有限的低频谐函数。

在Unity中,烘焙GI的LightProbe采用了3阶球谐函数(9个参数),实时GI中的LightProbe采用了2阶球谐函数(4个参数)。

OK,信号编码的问题解决了,另一个问题即在运行时如何重建亮度信号。其实使用lightprobe的开销很低,因为只需要将缩放系数与其对应的基函数相乘之后再求和的结果就是近似的原始信号。

接下来我来看看一个Unity中的LightProbe中保存了哪些数据吧。

屏幕快照 2018-04-20 下午12.23.56.png

在Unity中,我们可以使用脚本将场景内的LightProbe保存为一个Asset,并且只要保证使用文本格式进行序列化,我们就可以直接查看其数据内容了。

AssetDatabase.CreateAsset(Instantiate(LightmapSettings.lightProbes), "Assets/lightProbe.asset");

首先能够注意到的是“m_Tetrahedra”部分。

屏幕快照 2018-04-21 上午9.27.39.png
这个其实就是在运行时LightProbe插值时需要用到的四面体数据。因为如果要进行插值,显然要知道需要哪几个点来插值,同时还需要知道每个点的权重各是多少。
在Unity中会根据角色所在的位置,选择四面体,然后使用组成四面体的点进行插值,当然还可以确定每个点的权重。
屏幕快照 2018-04-21 上午9.34.55.png

在靠后的位置,我们还可以找到烘焙后的球谐函数的系数。

屏幕快照 2018-04-21 上午9.48.20.png

可以看到9个参数3个通道所以每一个点总共有27个float数据。

综上,可以看到在使用LightProbe时,计算开销并不大,相对来说比较大的开销主要来自对内存的占用。

0x03 修改LightProbe数据 提亮角色

ok,简单介绍了一下LightProbe的原理以及实现。下面我们还是回到最初的问题,那么怎么提亮一个场景内的角色才更加合理一些呢?

事实上我们可以通过修改烘焙后的LightProbe的数据来实现这样的需求。
light1.png
可以看到上图中,角色已经和场景融为了一体。虽然这样更加真实和符合物理规则,但是我想对很多人来说这显然不是一个好的效果。角色还是能更加突出的好。
好在Unity提供了获取烘焙后的LightProbe数据的接口:

var probes = LightmapSettings.lightProbes.bakedProbes;

bakedProbes内保存的是一堆“SphericalHarmonicsL2”对象,只要修改SphericalHarmonicsL2的缩放比例就可以修改LightProbe所提供的亮度了。

除了修改亮度之外,有时我们也会想让角色有不同的环境光效果,以更加突出角色。这时我们就可以通过SphericalHarmonicsL2中定义的AddAmbientLight方法来实现了:

probe.AddAmbientLight(color);

提亮和修改环境色之后,我们的角色在场景中就成了下面这样。比实时光更加自然和开销更低。

light2.png

当然,这里只是抛砖引玉,欢迎大家来讨论。

相关的脚本,可以在这里获取:

ref:

转载于:https://www.cnblogs.com/murongxiaopifu/p/8997720.html

你可能感兴趣的文章
ASP.NET MVC 教程-MVC简介
查看>>
SQL Server索引 - 聚集索引、非聚集索引、非聚集唯一索引 <第八篇>
查看>>
转载:详解SAP TPM解决方案在快速消费品行业中的应用
查看>>
Android OpenGL ES 开发(N): OpenGL ES 2.0 机型兼容问题整理
查看>>
项目中用到的技术及工具汇总(持续更新)
查看>>
【算法】各种排序算法测试代码
查看>>
HDU 5776 Sum
查看>>
201521123044 《Java程序设计》第9周学习总结
查看>>
winfrom 图片等比例压缩
查看>>
人工智能实验报告一
查看>>
用LR12录制app,用LR11跑场景,无并发数限制,已试验过,可行!
查看>>
python 多线程就这么简单(转)
查看>>
oracle 简述
查看>>
ajax如何向后台传递数组,在后台该如何接收的问题(项目积累)
查看>>
Solr之java实现增删查操作
查看>>
httpClient连接工具类实测可用
查看>>
CDOJ 1965 连通域统计【DFS】
查看>>
飞机大战3-我的飞机
查看>>
c#接口
查看>>
MyEclipse部署Jboss出现java.lang.OutOfMemoryError: PermGen space
查看>>