Unity 5.6中的混合光照(下)
https://mp.weixin.qq.com/s/DNQFsWpZm-ybIlF3DTAk2A
在《Unity
5.6中的混合光照(上)》中,我们介绍了混合模式,以及Subtractive模式是如何工作的。如果还不熟悉混合光照,请先去了解它背后的原理。
对Shadowmask的支持是新混合光照模式中的一个重要新功能。此外,还有密度与方向性贴图,Unity现在能为所有的光照类型生成Shadowmask了。与Subtractive模式不同,Shadowmask可以将所有光照类型的实时与烘焙阴影无缝混合。这意味着我们可以获得远距离阴影。出于性能考虑,可以在近处使用实时阴影而远处使用烘焙阴影,从而保持更低的Draw
Call数量。与Subtractive模式相反,Shadowmask功能还可以生成高质量的实时镜面高光。除了这些功能外,还对UI做了改进与重构,添加了新的调试模式,以协助你更好的在场景中设置光照。
这个视频展示了使用中的Shadowmask 和Distance Shadowmask。预计算实时GI在这个场景设置中已完全禁用。
现在,我们已说过Subtractive模式就是Unity中旧有的Mixed模式。但除那之外,Lighting Mode菜单中还有两个新的选项: Baked Indirect 和Shadowmask。要重点注意的是,Baked Indirect和Shadowmask不是质量设置。所有模式都有自己独特的功能特性,它们能在不同的使用场景中发挥不同的作用。
Shadowmask的主要功能本质上非常容易理解,它可以解决Subtractive无法完成的事情。Shadowmask不仅能处理方向光,还可以使用点光源和聚光灯混合实时与烘焙阴影,无需增加双重阴影/光照,即可正确合成重叠的阴影。在继续之前,我们需要先定义阴影距离的概念,它与光照模式紧密相关。许多新手用户不知道这个概念,但要正确高效地创作场景,必须要掌握这个知识。否则,很容易就会面对不必要的draw
call和帧率的下降。
阴影距离和阴影投射物的概念
在Unity中,阴影的行为由阴影距离和光照模式决定。查看阴影距离的一种快速方式就是使用Shadow Cascades模式。在场景视图中可以选择Shadow Cascades模式来显示阴影距离。这个参数可以在Quality设置中修改。更改阴影距离的另一个方式是通过API调用,但相关的使用案例相当有限。不过,它在某些极端情况下有些作用(例如,当需要在某些光照模式中为了降低draw
call而减少阴影距离)。
因此,几何体在阴影距离之内还是之外,会影响阴影的行为,并对性能产生直接影响。
实际上,如果打开Quality设置(Edit > Project Settings > Quality),会发现有很多参数可用来调整阴影的设置。很可惜,这是UI中的隐藏部分,大部分用户都不知道它的存在,除非在需要时搜索到这些参数。
尤其是可以在Distance Shadowmask和Shadowmask之间切换的Shadowmask功能选项。默认选中的是Distance Shadowmask选项,下文会讨论这两个模式之间的区别。让我们先从Shadowmask开始。
Shadowmask
在Shadowmask模式中,静态对象通过Shadowmask从其他静态对象接收阴影,不必考虑阴影距离。来自动态对象的阴影仅能通过阴影距离内的阴影贴图获得。动态对象通过阴影距离内的阴影贴图接受来自其他动态对象的阴影。来自静态对象的阴影仅能通过光照探针获得。
现在,当你同时在动态对象和光照贴图静态对象上使用Shadowmask模式时,你首先可能会发现问题就是,动态对象的阴影(阴影贴图)和来自光照贴图静态对象的烘焙阴影之间的不一致。当前(针对5.6),Unity在运行时仅支持简易版本的PCF( Percentage Closer Filtering )阴影,这种阴影很简陋,走近时还可能会出现阴影瑕疵。因此,动态对象是不可能获得软阴影的。与之相比,静态对象则相对较容易获得软阴影。实际上,通常需要增加分辨率以渲染更多静态对象的阴影,因为你需要更多的纹理像素来定义一张光照贴图上的阴影。只有这样,你才能渲染出与来自动态对象的阴影贴图相近的阴影。
你可以看到,使用高分辨率光照贴图,来自静态对象的烘焙阴影与来自动态对象的阴影贴图已十分接近。
使用低分辨率的光照贴图,来自静态对象的烘焙阴影与来自动态对象的阴影贴图明显不同。
关于Shadowmask模式的一个友情提示:动态对象仅会在阴影距离内投射阴影贴图。而静态对象,无论阴影距离是多少,仅会投射烘焙阴影。Shadowmask 和Distance Shadowmask两者均可提供实时镜面高光。
那么进一步的问题来了,什么是Distance Shadowmask?它与Shadowmask有何不同?
Distance Shadowmask
普通的Shadowmask模式要比Distance Shadowmask模式产生更少的Draw Call。为什么呢?
这是因为Distance Shadowmask的行为是由阴影距离决定的。在阴影距离内,动、静态对象都会渲染进阴影贴图,静态对象可以在动态对象上投射锐阴影。超出阴影距离,静态对象会通过预计算Shadowmask接收来自其他静态对象的高质量阴影,而动态对象则通过光照探针与LPPV,接收来自静态对象的低分辨率阴影。
这样应该能解释清楚Distance Shadowmask模式下动、静态对象的阴影投射方式以及为何Shadowmask模式要比Distance Shadowmask模式资源消耗更少了。基本上,阴影贴图的性能消耗要高于烘焙阴影(因为它们在每帧都进行渲染,而烘焙阴影是保存在一个纹理/光照贴图中的)。
在Shadowmask模式下,动态对象仅会在阴影距离内投射阴影贴图。Distance Shadowmask的性能消耗更大,因为静态对象也可以在阴影距离内投射实时阴影贴图,从而使Draw Call增加。这也就是为什么Distance
Shadowmask模式更适合高端PC或游戏主机。而Shadowmask则作为一种更廉价的解决方案,推荐在中低端设备使用。
Shadowmask中的遮蔽
有关Shadowmask的功能,我还想就不同对象类型遮蔽的工作原理进行详细说明。在上一篇文章中,我们谈及了为何光照探针的放置位置对于动态对象接收来自静态对象的阴影如此重要。本质上,动态对象需要光照探针从遮蔽物采样遮蔽数据。因此,Subtractive模式中的探针遮蔽概念同样可以直接适用于Shadowmask和Distance
Shadowmask。
有关对象是如何根据其类型与光照模式接收对应阴影的快速参考可以查看下面的光照模式参考卡片(Lighting Modes Reference Card),甚至可以打印出来以备不时之需。
作为Quality设置的Shadowmask
在Unity 2017.1中,Shadowmask和Distance Shadowmask选项被移到了Quality设置中,这么做的原因有两点。
首先,我们希望用户能对阴影行为能有更多艺术性的控制,所以可以在运行时对模式进行切换。例如,你可以在同一场景中的室内环境使用Shadowmask(比如在机库中实现软阴影),在室外环境时切换到Distance Shadowmask。事实上,我们在《Unity
2017中的混合光照》中已经提及了如何用API来实现这个操作。
其次,可以针对不同的硬件配置设置不同的要求。例如,在一个游戏中,可以在菜单UI上显示一个用户可以调整的设置选项,或者如果你要发布游戏到Steam,可以在低端硬件上使用普通的Shadowmask,在高端PC上使用Distance Shadowmask。
我们之所以能这样随心所欲进行设置,正是因为技术上在Shadowmask 和Distance Shadowmask之间的切换非常简单,唯一的缺点就是Draw Call的数量,但不管怎么说,最后都是取决于用户。
技术限制和调试工具
最后,让我们聊聊Shadowmask功能(Shadowmask 和Distance Shadowmask)的技术限制,以及能帮你在设置过程中进行问题诊断的调试工具。
现在,你已知道如何及为何使用Shadowmask,让我们来聊聊它的限制。由于技术约束,在一个场景中,Unity仅支持4个重叠的混合灯光。如果在相同位置有超过4个的混合灯光,其中之一就会降级为烘焙。通常如果你看到其中有某个灯光突然爆亮,你马上就能发现问题。
好消息是,我们有个可视化调试工具可以帮你解决该问题。如果将场景的visualization模式从“Shaded”切换到“Light Overlap”,你可以看到问题区域显示为红色高亮。
值得一提的是,与点光源或聚光灯不同的是,方向光没有定义的边界,它是全方向的。因此,你在调试重叠的混合灯光时,总要将其考虑在内。在屏幕上,你可能只看到4个重叠灯光,但实际上,方向光可能已在某些位置与之有了交叉。如果在场景中使用了多个方向光来进行照明(例如作为补光),那情况就有点麻烦了,所以好好使用它。
Baked Indirect
目前为止我们已经介绍了Subtractive模式、Distance Shadowmask和Shadowmask功能。还剩一个模式,Baked Indirect。
与Shadowmask复杂的选项相比,Baked Indirect模式相当容易理解。Baked Indirect没有使用任何Shadowmask。所以在这个模式中没有远距离阴影。在阴影距离之内,所有静态和动态的对象都投射 实时阴影贴图。但超出阴影距离后,就没有阴影。
在Baked Indirect中,除了间接照明之外所有的东西都是实时的。这意味着,实时光照、实时阴影以及实时镜面高光,但是反弹的光照信息储存在光照贴图中,是静态的。在这个模式中,你能做的事情有限,但是你可以开动脑筋做些创造性的事情。下面你会看到摇摆的Baked Indirect模式混合聚光灯,是如何伪造实时全局照明的。
你可以看到灯光在变化,亮度忽明忽暗。但是,如果你仔细观察街灯的间接照明,你会发现它并没有变化。所以从技术上来说,你可以移动你的灯光,但不能太多,否则会出现阴影瑕疵。在下面的视频中,你会看到在场景中移动对象时,间接照明是如何导致这种类型阴影瑕疵的:
关于Unity 5.6中的混合光照就介绍到这里,我们还会继续为大家分享Unity相关的技术文章在Unity官方中文社区(unitychina.cn),请保持关注!
Unity 5.6中的混合光照(下)的更多相关文章
- Unity 5.6中的混合光照(上)
https://mp.weixin.qq.com/s/AbWM21sihHw5pFdMzENDPg 在Unity 5中,光照得到了很大的改进.现在,创建高度逼真的游戏已成为可能.但是,出于对性能的考虑 ...
- 浅析Unity中的Enlighten与混合光照
0x00 前言 在Unity的5.6版本之前的5.x中,主要使用了Geomerics公司的Enlighten[1]来提供实时全局照明以及烘焙全局照明,在5.6之后Unity引入了新的Lightmapp ...
- Unity Shader入门精要学习笔记 - 第6章 开始 Unity 中的基础光照
转自冯乐乐的<Unity Shader入门精要> 通常来讲,我们要模拟真实的光照环境来生成一张图像,需要考虑3种物理现象. 首先,光线从光源中被发射出来. 然后,光线和场景中的一些物体相交 ...
- 第五章 Unity中的基础光照(2)
目录 1. Unity中的环境光和自发光 2. 在UnityShader中实现漫反射光照模型 2.1 实践:逐顶点光照 2.2 实践:逐像素光照 2.3 半兰伯特模型 1. Unity中的环境光和自发 ...
- 聊聊Unity2018的LWRP和混合光照
0x00 前言 在这篇文章中,我们选择了过去几周Unity官方社区交流群以及UUG社区群中比较有代表性的几个问题,总结在这里和大家进行分享.主要涵盖了** Scripting.Assetsbundle ...
- 游戏引擎中三大及时光照渲染方法介绍(以unity3d为例)
(转)游戏引擎中三大及时光照渲染方法介绍(以unity3d为例) 重要:在目前市面上常见的游戏引擎中,主要采用以下三种灯光实现方式: 顶点照明渲染路径细节 Vertex Lit Rendering ...
- (转)游戏引擎中三大及时光照渲染方法介绍(以unity3d为例)
重要:在目前市面上常见的游戏引擎中,主要采用以下三种灯光实现方式: 顶点照明渲染路径细节 Vertex Lit Rendering Path Details 正向渲染路径细节 Forward Rend ...
- [转] Draw Call未被批处理?告诉你在Unity 5.6中如何查找原因 [复制链接]
Unity在5.6之前的版本中并未提供很直接的方式来查找Draw Call未被批处理的原因,但Unity 5.6在Frame Debugger中新增了一项功能,帮助开发者查找相关信息.今天这篇文章就为 ...
- 【Unity Shaders】Diffuse Shading——漫反射光照改善技巧
本系列主要参考<Unity Shaders and Effects Cookbook>一书(感谢原书作者),同时会加上一点个人理解或拓展. 这里是本书所有的插图.这里是本书所需的代码和资源 ...
随机推荐
- PYTHON加密解密字符串
依赖包安装部分 安装依赖包: pip install pycryptodome 在你的python环境中的下图红框路径中找到 crypto 将其改成 Crypto 代码部分 #!/usr/bin/en ...
- X86汇编 BT
位操作指令位操作指令包括位测试和位扫描指令,可以直接对一个二进制位进行测试,设置和扫描. 1位测试和设置指令 格式:BT DEST,SRC BTC DEST,SRC BTR DEST,SRC BTS ...
- 【linux】记录一次系统被攻击的处理过程
今天登录zabbix监控网页的时候发现非常卡,登录到系统里面以后,通过top看,CPU已经100%了,有一个叫做httpds的进程占用,第一反映就是系统被入侵了,下面记录了处理过程,仅供各位参考 通过 ...
- 20145239杜文超 《Java程序设计》第8周学习总结
20145239 <Java程序设计>第8周学习总结 教材学习内容总结 通用API 日志API 1.java.util.logging包提供了日志功能相关类与接口,使用日志的起点是logg ...
- 使用gdb调试c/c++代码
转自 http://blog.csdn.net/haoel/article/details/2879 GDB概述———— GDB是GNU开源组织发布的一个强大的UNIX下的程序调试工具.或许,各位比较 ...
- hdu 1042 N!(大数)
题意:求n!(0 ≤ N ≤ 10000) 思路:大数,用数组存储 1.首先要考虑数据N!的位数,因为最大是10000!,可以计算一下大概是5+9000*4+900*3+90*2+10*1=38865 ...
- Custom Database Integration Guide
Introduction This document provides instructions for integrating Openfire authentication, users, and ...
- Go丨语言学习笔记--switch
Java语言与Go语言的switch对比 Go语言 switch str { case "yes" : do something ... case "no" d ...
- (转)C++经典面试题(最全,面中率最高)
1.new.delete.malloc.free关系 delete会调用对象的析构函数,和new对应free只会释放内存,new调用构造函数.malloc与free是C++/C语言的标准库函数,new ...
- Chrome检查更新总失败?安装细则讲解
现在 Google Chrome 的稳定版都已经发布 68.0 版本了,我机上还是 54, 本想在线更新一下,结果点击菜单项中的“关于 Google Chrome”后,进入的界面提示“更新失败(错误: ...