[toc]本篇内容零散的记录一些光照方面的知识。 本篇中测试使用的Unity版本为2019.1.0b10。 因为着色计算中少不了光照,所以这方面的知识不要回避为好。女神书上多次提到“排除Lightmap、cookie的情况”,但是对于做项目的人来说,不能总停留在理论或者猜想阶段。 我希望的是,我综合利弊后确认项目中的确不需要考虑某个关键词或者光照烘焙,于是将对应的可能性排除。

Unity中的光照类型

工程很复杂的时候,场景里面有什么光不一定能很快理清,我们应该从一个空的场景开始。 当场景中没有任何光源、环境光、探针时,场景里的物体应该是全黑的。 直接光:Hierarchy中创建的平行光源、点光源、锥形光源,用于直接照亮物体(diffuse)。 间接光:环境光、实时GI、光照探针、折射探针、自发光,用于间接照亮物体(ambient、reflect、refract)和自发光(emission)。 衰减因子:环境光遮蔽、阴影衰减、光照衰减。 每个像素的最终颜色值均通过光照公式计算出来,数据的准备由Unity帮我们完成。 Cubemap Cubemap相当于用6个面组成的正方形,从中心处射出任意射线必定击中一个点,这个过程用于理解Cubemap采样。 当Cubemap作为Skybox时,相当于给相机添加了一个Skybox组件,单纯平移相机时不会修改Cubemap采样的角度。 无光的世界 新建一个scene,创建一个Cube(使用了标准shader),此时Cube是被照亮的。 删除默认的平行光,Cube黑了(没开Auto Generate时),默认的天空还是亮的。 在Lighting Setting中,开启Auto Generate自动烘焙,Cube又亮了,比较灰。 设置Skybox Material为空,Cube变灰,背景变成相机的Background颜色。 此时Source的下拉选项中,skybox作为默认环境光源将不再生效,等同于Color。 设置Ambient Color,此时Cube颜色完全跟着Ambient Color走。 在无光的世界里: FinalColor = Ambient 或者说,构成环境贴图的Cubemap此时由单色的面构成。 Skybox 设置Source为Color,Ambient Color设置为(0,0,0),再恢复默认的天空盒子。 此时环境色不再提供任何光照强度,Cube上依然有微量的光照。 调整Environment Reflections下的Intensity Multiplier,为0时Cube全黑。 FinalColor = Ambient + Reflect(Source) 这里的Reflect描述了物体表面的反射现象,观察方向相对法线的反射方向用于采样,被采样的目标为Source,默认为Skybox。 Intensity Multiplier作为环境反射部分的系数,最大值1表示正常水平。 Bounces表示反射的光照最多会被反射的次数,最小值1表示反射到1个物体以后就不会继续反射了。 将Source设置为Custom后,Cube变为全黑,此时我们可以指定用于环境反射的Cubemap。 反射现象等同于镜面反射、高光,与观察角度有关。 现在我们可以总结一下skybox的意义: 当渲染流水线中Queue低于2500的物体绘制完毕后,开始绘制skybox,没深度记录的片元都去采样一次。 可以作为环境光的Cubemap、环境反射的Cubemap,这两个过程是分别独立的,描述了环境光和反射现象。 至此,光照设置的Environment部分基本完成了。 Realtime/Mixed Lighting Realtime Global Illumination:实时全局照明,控制Realtime光源是否产生间接光(realtime lightmap,这个lightmap会实时更新),个别Realtime光源产生间接光的比率可以通过光源的Indirect Multiplier属性调整。 间接光:这里指光直接照到物体后的反射、折射现象,而折射的光继续参与漫反射、转化为热能、反射(水底)等过程。 间接光的产生必须准守能量守恒,这个任务是由Shader完成的,也就是Unity提供的标准Shader。 而使用自定义的Unlit Shader,需要手动编程进行光照计算。 Baked Global Illumination:烘焙全局照明,控制Mixed/Baked光源是否产生间接光(baked lightmap,这个lightmap不会更新)。 Mixed光源在有烘焙数据时则使用烘焙数据,Baked光源必定使用烘焙数据。 Lighting Mode:指定Mixed光源的工作模式。 substrative:烘焙Mixed光源对静态物体的直接光照,间接光照、阴影。 shadowmask:烘焙Mixed光源对静态物体的间接光照和阴影,实时光照在运行时计算。 baked indirect:仅烘焙Mixed光源对静态物体的间接光照,实时光照和阴影在运行时计算。 Lightmapping Settings 光照映射设置,必须开启烘焙GI才能生效。这里使用默认的Progressive CPU光照系统。 Prioritize View:是否优先烘焙Scene视口中的物体。 Multiple Importance Sampling:环境采样时是否开启Multiple Importance Sampling。 Direct Samples:直接光采样次数。 Indirect Samples:间接光采样次数。 Environment Samples:环境光采样次数。 Bounces:间接光的反弹次数。 Filtering:指定烘焙过程中的减噪方案。 Indirect Resolution:开启Realtime GI后可用。可能是指realtime lightmap的分辨率,无法观察。 Lightmap Resolution:Baked Lightmap中,1个Unit对应的像素数。 Lightmap Padding:Baked Lightmap中,shape之间的像素间隔。 Padding过小或者Lightmap分辨率不够时可能造成”Overlapping UVs”问题。 Lightmap Size:设置整个Lightmap的像素尺寸,一张Lightmap不够时会增加Lightmap数量。 Compress Lightmaps:是否压缩Baked Lightmap,可能产生偏差。 Ambient Occlusion:是否在Bake Lightmap时,模拟环境光遮蔽。 Directional Mode:Directional模式下lightmap存储更多的光照信息帮助标准shader计算 Indirect Intensity:realtime/baked lightmap中间接光的强度系数。 Albedo Boost:增加反照率(漫反射的光量)。 Lightmap Parameters:一整套lightmap参数。 Other Settings Fog:是否在场景中使用雾效。 Halo Texture:指定用于绘制光源周围的光晕的贴图。 Halo Strength:光晕强度。 Flare Fade Speed:光源→相机的lens flare持续时间。 Flare Strength:lens flare的强度。 Spot Cookie:Spot光源的衰减贴图。 Generate Lighting 生成光照,也就是烘焙光照数据。 Baked光源和Mixed光源对Lightmap Static的物体的光照生成对应的Lightmap。 需要展开模型的第二套UV,模型的Import面板中勾选 ‘Generate Lightmap Uvs’。 Cookie Texture 将纹理类型设置为cookie,指定光源类型和Alpha from Grayscale,生成Cubemap。 可作为阴影遮罩,黑色的部分造成阴影。模拟透过窗户的光照。只能有realtime光源可使用。 加快烘焙速度 ①缩放不重要的对象,如变化少的对象、只接受间接光的对象。 ②修改Lightmap Parameters。 An Introduction to Lightmapping in Unity Reducing precompute times from hours to minutes

Light Probes

光照探针。 为什么需要使用光照探针: 当光源分为Realtime、Mixed、Baked三种模式后,场景中的物体也要区分为实时和静态。 静态的物体在烘焙的过程中保存了光照计算的结果,在渲染流水线中只需要采样lightmap即可完成着色。 实时的物体接受Realtime光源提供的光照,参与光照计算进行着色。实时的物体也可以采样lightmap吗? lightmap的采样过程与Cubemap不同,更类似于Tex2D,第二套UV用于lightmap的采样。 一张lightmap上会包含复数物体的多个面的UV展开图+UV着色图。 这种情况下实时物体是找不到在lightmap中的采样坐标的,作为立体物体最好是对Cubemap采样。 一个Light Probe,可以理解为一个对环境采样后的Cubemap。 如何使用光照探针: 在Hieraichy中右键-Light-Light Probe Group,得到Light Probe Group组件,这个组件用于管理场景中的所有Light Probe,其Transform没有意义,重要的是Light Probe的位置。 Edit Light Probes:进入光照探针编辑模式。 Add Probe/Select All/Delete Selected/Duplicate Selected:对复数探针的位置调整。 一个探针相当于一个Cubemap,记录了从周围所有角度射向这个点的Backed Lighting,也就是采光过程,所以光照探针像是一个光源。 采样角度:从物体表面一点到探针的方向/从物体质心到表面一点;不确定,我倾向于后者。 前者只能做到面向探针的那一面有采样角度,且距离探针越远角度越集中,需要多个探针合作才能照亮所有面。 后者只考虑表面上的点在整体的相对位置,可以实现全方位采样,但是忽视了探针的位置因素。 实时物体对lightmap的采样依赖于4个Light Probe构成的封闭空间,越近的Ligh Probe影响比例越大。 观测方式:选中实时物体时可显示正在对其生效的4个Light Probe。 Light Probe效果分析 Light Probe生效的机制并没有考虑到场景中可能存在的阴影突变和颜色突变。 我们通过Cubemap采样得到颜色值,这种模式产生的颜色突变通常是移动过程中切换了采样目标Light Probe造成的。 所以这里考虑2种运动方式:在固定的4面体内移动;质心超出边界时切换一个Light Probe到达新的四面体内。 所以无法反映出明确的阴影边界线或者颜色边界线,只能是切换Light Probe时突然变色。 如何合理放置Light Probe 在整个空间范围内,明暗交替、色调交替处的两边各放置一个Light Probe,通过这样的方式达到模拟颜色突变的效果。

Reflection Probe

为什么要有反射探针 反射是物体的自然现象,表面越光滑的物体反射的光量越多,在标准shader中可以调整材质的Reflective值。 反光色=反光率·(视角方向相对于法线的反射方向对环境的采样) 在自定义shader中,我们可以对环境Cubemap进行采样获得反光色,就像从镜子里面看到周围的物体。 在标准shader中,并不会去采集周围物体的颜色,逐像素计算每个点的反光色是很困难的。 测试:新建场景,Cube使用绿色材质,Sphere的金属度和光滑度设置为最大值1。 观测结果:Sphere的表面完全镜面反射后,依然看不到周围的Cube,显示的默认skybox的颜色。 初步结论:默认的skybox相当于提供了一个默认的反射探针,对反射光的采样目标默认为skybox。 在Hierarchy中右键-Light-Reflection Probe,创建反射探针。 自建反射探针的意义:代替系统默认的反射探针,记录指定的反射内容。 反射探针就像摄像机一样,记录周围的环境,也相当于Cubemap,被其记录下的内容我们称为”记录目标”。 反射探针有一个Bounding Box,对范围内所有标准shader中含有Reflective属性的物体生效。 进入反射探针的编辑模式可以调整Bounding Box的范围。 Type:三种工作模式,Baked/Custom/Realtime,用于指定记录目标;对”哪些物体会受到影响”没有要求。 本例中Sphere采样方向:Sphere质心→表面一点。 当Shpere移动时,反射到的内容不会发生变化,与Shpere和反射探针的相对位置无关,但是要在其范围内。 Baked记录目标:范围内标记为Reflection Probe Static的物体+skybox。 Realtime记录目标:范围内任何物体+skybox,可以在Culling Mask中将不需要记录的物体排除。 Custom:指定的Cubemap。 注:反射探针也可以作为光源。 在无光的世界中,环境光为指定的颜色值,导致反射探针即使在无光的情况下所有面都铺满环境色(r,g,b)。 而自然界中的物体或多或少都有反射属性,可以从反射探针中采样到少量的环境色。

其他

问:Light Probe的被采样方向 问:什么是采样 问:为什么采样需要很多次,是什么原因造成每次采样的结果不同。 问:一次采样与一帧的区别。 渲染流水线中完成后备缓冲后,前后缓冲交换生成下一帧,称为一帧。 一次采样可以理解为一次光照计算,包括后期处理。