聊聊LightProbe原理实现以及对LightProbe数据的修改

原文链接https://www.cnblogs.com/murongxiaopifu/p/8997720.html

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

当然,这里只是抛砖引玉,欢迎大家来讨论。
相关的脚本,可以在这里获取:
https://github.com/chenjd/LightProbeEditor

ref:

https://en.wikipedia.org/wiki/Delaunay_triangulation
https://www.gdcvault.com/play/1015312/Light-Probe-Interpolation-Using-Tetrahedral
https://en.wikipedia.org/wiki/Spherical_harmonics

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

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

相关文章

3D游戏的照明设计理论,第3部分:三点照明法的异端与误区

https://zhuanlan.zhihu.com/p/87997570 这是有关如何处理游戏照明的系列文章的一部分。第一部分是关于灯具,第二部分是关于光的形式材料。 在第一部分中,我们首先从文化角度考虑了灯光-灯光在整个历史上对不同的人意味着不同的事物,并且在照…

3D游戏的照明设计理论,第4部分:如何在游戏引擎中照亮游戏世界

从更一般和更概念的角度来看,这是有关我如何处理游戏照明的系列文章的一部分。我在Unity中构建了大部分示例,但这通常适用于任何3D游戏引擎,其中大多数具有类似的照明工具。 我们开始思考了有关光照的文化和概念,在第一部分。在第…

ProjectorShadow 和 ShadowMap对比

https://blog.csdn.net/aceyan0718/article/details/52279594

unity shader 变种(多重编译 multi_compile)

一、定义 在unity中我们可以通过使用#pragma multi_compile或#pragma shader_feature指令来为shader创建多个稍微有点区别的shader变体。这个Shader被称为宏着色器(mega shader)或者超着色器(uber shader)。实现原理:…

AndroidStudio导出aar文件给Unity使用

AndroidStudio导出aar文件给Unity使用 本文参考 :http://www.devacg.com/?post548 Demo地址:https://github.com/JulyNine/AndroidToUnity 一、用Android Studio创建个空工程 注意:包名要与Unity中工程的包名不一致,不然打包时…

Unity C# Job System介绍(一) Job System总览和多线程

C# Job System 总览 Unity的C# Job System使用户可以编写与Unity其他部件交互的多线程代码,同时让编写正确的代码变得更容易。 编写多线程代码可以提供更好的性能表现。这包括非常明显的帧数提升。C# job协同Burst编译器可以提升代码生成的质量,这也会…

Unity C# Job System介绍(二) 安全性系统和NativeContainer

C# Job System中的安全性系统 https://docs.unity3d.com/Manual/JobSystemSafetySystem.html​docs.unity3d.com 资源竞争 当我们编写多线程代码时,经常会有产生资源竞争的风险。资源竞争会在一项操作的输出依赖于另一项它掌控之外的操作时发生。 资源竞争并不总…

Unity C# Job System介绍(三) Job的创建和调度

创建Jobs Unity - Manual: Creating jobs​docs.unity3d.com 为了在Unity中创建一个job你需要实现IJOb接口。IJob允许你调度一个job,和其他jobs并发执行。Unity - Manual: Creating jobs为了在Unity中创建一个job你需要实现IJOb接口。IJob允许你调度一个job&#…

Unity C# Job System介绍(四) 并行化Job和故障排除(完结)

并行化job ParallelFor jobs​docs.unity3d.com 当调度Jobs时,只能有一个job来进行一项任务。在游戏中,非常常见的情况是在一个庞大数量的对象上执行一个相同的操作。这里有一个独立的job类型叫做IJobParallelFor来处理此类问题。ParallelFor jobs当调…

C# Job System

概述 设计目的:简单安全地使用多线程,随便就能写出高性能代码 收益:FPS更高,电池消耗更低(Burst编译器) 并行性:C# Job System和Unity Native Job System共享工作线程worker threads&#xf…

Unity游戏开发——C#特性Attribute与自动化

这篇文章主要讲一下C#里面Attribute的使用方法及其可能的应用场景。 比如你把玩家的血量、攻击、防御等属性写到枚举里面。然后界面可能有很多地方要根据这个枚举获取属性的描述文本。 比如你做网络框架的时候,一个协议号对应一个类的处理或者一个方法。 比如你做…

Unity c#中Attribute用法详解

举两个例子,在变量上使用[SerializeFiled]属性,可以强制让变量进行序列化,可以在Unity的Editor上进行赋值。 在Class上使用[RequireComponent]属性,就会在Class的GameObject上自动追加所需的Component。 以下是Unity官网文档中找…

attribute的用法--C#

一直以来都没理解attribute是个什么东西,也没怎么用,但是看msdn或者git上源码使用的还是蛮频繁的,今天好好整理了下,写下自己的理解和例子: attribute主要用来说明代码段的的信息,标志等;可以一…

走进LWRP(Universal RP)的世界

走进LWRP(Universal RP)的世界 原文:https://connect.unity.com/p/zou-jin-lwrp-universal-rp-de-shi-jie LWRP自Unity2018发布以来,进入大家视野已经有一段时间了,不过对于广大Unity开发者来说,依然相对…

Unity Fine Prued Tiled Light (FPTL)

Fine Prued Tiled Light Lists 视频讲解:https://www.bilibili.com/video/av90517615 FPT是在Tile裁剪的基础上在进行一次剔除 可用于Forward Render和Deferred Shading两种渲染管线 利用了并行架构进行优化 将线程分为线程组再分为多个线程,Thread Gro…

Unity 2017 Game Optimization 读书笔记(1)Scripting Strategies Part 1

1.Obtain Components using the fastest method Unity有多种Getcomponet的方法&#xff1a; GetComponent(string), GetComponent<T>() GetComponent(typeof(T)) 哪种效率最高会跟随Unity版本的变化而变化&#xff0c;对于Unity 2017&#xff0c;本书作者的测试是Ge…

C# 多态相关的文章

一 C# 多态的实现 封装、继承、多态&#xff0c;面向对象的三大特性&#xff0c;前两项理解相对容易&#xff0c;但要理解多态&#xff0c;特别是深入的了解&#xff0c;对于初学者而言可能就会有一定困难了。我一直认为学习OO的最好方法就是结合实践&#xff0c;封装、继承在…

C++ 虚函数和虚表

几篇写的不错的文章&#xff0c;本文是整合了这几篇文章&#xff0c;感谢这些大佬 https://www.jianshu.com/p/00dc0d939119 https://www.cnblogs.com/hushpa/p/5707475.html https://www.jianshu.com/p/91227e99dfd7 多态: 多态是面相对象语言一个重要的特性,多态即让同一…

Unity 2017 Game Optimization 读书笔记(2)Scripting Strategies Part 2

1. Share calculation output 和上一个Tip很像&#xff0c;可以缓存计算结果或者各种信息&#xff0c;避免多次重复的计算&#xff0c;例如在场景里查找一个物体&#xff0c;从文件读取数据&#xff0c;解析Json等等。 容易忽略的点是常常在基类了实现了某个方法&#xff0c;在…

Unity 2017 Game Optimization 读书笔记(3)Scripting Strategies Part 3

1.Avoid retrieving string properties from GameObjects 通常来讲&#xff0c;从C#的object中获取string 属性没有额外的内存开销&#xff0c;但是从Unity中的Gameobject获取string属性不一样&#xff0c;这会产生上一篇讲到的 Native-Managed Bridge&#xff08;Native内存和…