在上一篇了解了光照以及光照贴图的一些相关属性后,在这篇具体讲讲相关的使用,以及自己预见的一些坑。

首先还是在上一篇的场景基础上,我们隐藏Realtime和Mixed光源,只留Baked的光源用来进行场景的烘焙。在Lighting设置中,只勾选Baked GI选项,Lighting Mode选择Subtractive。取消自动烘焙Auto Generate的勾选,点击Generate Lighting,手动生成Lightmap。同时Unity会在.scene文件同级目录下生成一个和scene名相同名称的文件夹,用于存放lightmap数据。相比自动生成的情况,在Baked Lightmaps中会多出一个Lighting Data Asset的参数,对应的LightingData.asset文件用于存放一些Lighting数据。

生成好之后运行Unity,修改Baked光源发现不影响场景的显示,一切都正常。

但是,当我们把静态场景存为Prefab的时候,就会出现一些问题了。而在实际的开发中,很多情况下会把静态的场景存为Prefab用于动态的加载。

我们将测试场景的物体放在同一个根目录下,然后将其转变为Prefab,点击运行。你会发现动态物体(胶囊体)也受到了baked光源的影响,变成了红色。关闭baked光源你会发现整个场景的物体都变黑了,baked的光源效果变成了realtime。

我们随便点击一个静态物体会发现其MeshRenderer中的Lightmapping属性关联的Lightmap不见了。造成这一现象的原因是,我们生成Lightmap的时候,其对应的信息都是和场景中GameObject的唯一ID相关联。当我们将这些GameObject变为Prefab时(包括后期加载该Prefab到场景中),唯一ID发生了变化,导致信息无法正确的关联起来。

有一个解决方案是,我们创建一个组件,挂载Prefab上。在烘焙完成后,这个组件会遍历该节点下所有静态物体的MeshRenderer,存储对应的Lightmap信息。当加载该Prefab的时候,将对应的Lightmap信息重新关联到对应的MeshRenderer上,代码如下:

注:由于很多时候美术可能会在一个新的场景中设置地图,然后会设置一些环境光,Fog等信息,我们程序在别的场景加载的时候,除了对应的地图Prefab外,这些信息也应该对应的设置,所以同Lightmap一起写在了脚本中。

注:由于Terrain比较特殊,如果地图中用到的话,需要单独读取信息。

using UnityEngine;
using System.Collections.Generic;
using UnityEngine.Rendering;/// <summary>
/// 渲染信息
/// </summary>
[System.Serializable]
public struct RendererInfo
{public Renderer renderer;public int LightmapIndex;public Vector4 LightmapOffsetScale;
}[System.Serializable]
public class SettingProperty
{[SerializeField]public Material Skybox;[SerializeField]public LightmapsMode Mode;[SerializeField]public Texture2D[] LightmapsColor;[SerializeField]public Texture2D[] LightmapsDir;[SerializeField]public Texture2D[] ShadowMask;[SerializeField]public LightProbes Probes;[SerializeField]public Color AmbientColor;[SerializeField]public AmbientMode AmbientMode;[SerializeField]public Color SkyColor;[SerializeField]public Color EquatorColor;[SerializeField]public Color GroundColor;[SerializeField]public bool UseFog;[SerializeField]public Color FogColor;[SerializeField]public FogMode FogMode = FogMode.Linear;[SerializeField]public float FogDensity;[SerializeField]public float LinearFogStartDistance = 0;[SerializeField]public float LinearFogEndDistance = 300;[SerializeField]public RendererInfo[] RendererInfos;[SerializeField]public RendererInfo TerrainRendererInfo;
}public class LightmapConfig: MonoBehaviour
{static LightmapConfig _instance;public static LightmapConfig sInstance { get { return _instance; } }public SettingProperty Setting;private SettingProperty OriginalSetting;private static Stack<LightmapConfig> sConfigStack = new Stack<LightmapConfig>();void Awake(){_instance = this;SwichLightmapConfig();sConfigStack.Push(this);}void OnDestroy(){if (sConfigStack.Count > 0){sConfigStack.Pop();if (sConfigStack.Count > 0){_instance = sConfigStack.Peek();_instance.SwichLightmapConfig();}}}public void StoreCurrentConfig(){Setting = new SettingProperty();StoreSettings(ref Setting);}//读取信息public virtual void StoreSettings(ref SettingProperty prop){prop.Skybox = RenderSettings.skybox;prop.AmbientColor = RenderSettings.ambientLight;prop.AmbientMode = RenderSettings.ambientMode;prop.SkyColor = RenderSettings.ambientSkyColor;prop.EquatorColor = RenderSettings.ambientEquatorColor;prop.GroundColor = RenderSettings.ambientGroundColor;prop.UseFog = RenderSettings.fog;prop.FogColor = RenderSettings.fogColor;prop.FogMode = RenderSettings.fogMode;prop.FogDensity = RenderSettings.fogDensity;prop.LinearFogStartDistance = RenderSettings.fogStartDistance;prop.LinearFogEndDistance = RenderSettings.fogEndDistance;prop.LightmapsColor = new Texture2D[LightmapSettings.lightmaps.Length];prop.LightmapsDir = new Texture2D[LightmapSettings.lightmaps.Length];prop.ShadowMask = new Texture2D[LightmapSettings.lightmaps.Length];for (int i = 0; i < LightmapSettings.lightmaps.Length; i++){prop.LightmapsColor[i] = LightmapSettings.lightmaps[i].lightmapColor;prop.LightmapsDir[i] = LightmapSettings.lightmaps[i].lightmapDir;prop.ShadowMask[i] = LightmapSettings.lightmaps[i].shadowMask;}List<RendererInfo> renderers = new List<RendererInfo>();MeshRenderer[] subRenderers = GetComponentsInChildren<MeshRenderer>();foreach (MeshRenderer meshRenderer in subRenderers){if (meshRenderer.lightmapIndex == -1) continue;RendererInfo renderInfo = new RendererInfo();renderInfo.renderer = meshRenderer;renderInfo.LightmapIndex = meshRenderer.lightmapIndex;renderInfo.LightmapOffsetScale = meshRenderer.lightmapScaleOffset;renderers.Add(renderInfo);}prop.RendererInfos = renderers.ToArray();Terrain terrain = GetComponentInChildren<Terrain>();if (terrain != null){prop.TerrainRendererInfo = new RendererInfo();prop.TerrainRendererInfo.LightmapIndex = terrain.lightmapIndex;prop.TerrainRendererInfo.LightmapOffsetScale = terrain.lightmapScaleOffset;}}//重新设置public virtual void ApplyConfig(SettingProperty prop){RenderSettings.skybox = prop.Skybox;RenderSettings.ambientLight = prop.AmbientColor;RenderSettings.fog = prop.UseFog;RenderSettings.fogColor = prop.FogColor;RenderSettings.fogMode = prop.FogMode;RenderSettings.fogDensity = prop.FogDensity;RenderSettings.fogStartDistance = prop.LinearFogStartDistance;RenderSettings.fogEndDistance = prop.LinearFogEndDistance;RenderSettings.ambientMode = prop.AmbientMode;RenderSettings.ambientSkyColor = prop.SkyColor;RenderSettings.ambientEquatorColor = prop.EquatorColor;RenderSettings.ambientGroundColor = prop.GroundColor;if (prop.LightmapsColor != null && prop.LightmapsColor.Length > 0){LightmapData[] lds = new LightmapData[prop.LightmapsColor.Length];for (int i = 0; i < prop.LightmapsColor.Length; i++){lds[i] = new LightmapData();lds[i].lightmapColor = prop.LightmapsColor[i];lds[i].lightmapDir = prop.LightmapsDir[i];lds[i].shadowMask = prop.ShadowMask[i];}LightmapSettings.lightmaps = lds;}else{LightmapSettings.lightmaps = null;}for (int i = 0; i < prop.RendererInfos.Length; i++){RendererInfo info = prop.RendererInfos[i];info.renderer.lightmapIndex = info.LightmapIndex;info.renderer.lightmapScaleOffset = info.LightmapOffsetScale;}Terrain terrain = GetComponentInChildren<Terrain>();if (terrain != null){terrain.lightmapIndex = prop.TerrainRendererInfo.LightmapIndex;terrain.lightmapScaleOffset = prop.TerrainRendererInfo.LightmapOffsetScale;}}void RestoreLightmapConfig(){if (OriginalSetting != null){ApplyConfig(OriginalSetting);}}public void SwichLightmapConfig(){if (Setting != null){OriginalSetting = new SettingProperty();StoreSettings(ref OriginalSetting);ApplyConfig(Setting);}}
}

然后我们在Editor目录下创建一个脚本,如下,功能是该组件在Inspector添加一个按钮,点击后保存信息。

using UnityEditor;
using UnityEngine;
using System.Collections;[CustomEditor(typeof(LightmapConfig))]
public class LightmapConfigInspector : Editor
{public override void OnInspectorGUI(){GUI.changed = false;LightmapConfig config = target as LightmapConfig;Undo.RecordObject(config, "ModifyLightmapConfig");if(GUILayout.Button("Store Current Setting")){config.StoreCurrentConfig();}base.OnInspectorGUI();if (GUI.changed){EditorUtility.SetDirty(config);}}
}

脚本搞好之后,我们在父节点上挂载LightmapConfig组件,然后重新烘焙后,点击Store Current Setting按钮,即可保存好Lightmap等信息。

然后运行Unity,会发现静态物体的Lightmap信息都关联上了。但是Baked的光源还是起到了realtime的效果,只有关闭了baked光源才正常。

针对烘焙光源全是Baked的话,我们可以在运行的时候取消这些光源,达到正确的效果。但是如果有mixed的光源,依旧还是会存在问题(即,mixed光源对静态物体进行烘焙,但是运行后还是产生影响,但是mixed光源不能像baked光源一样取消,因为它还需要对动态物体产生效果)

所以最终还是建议使用多场景的方式来处理。即在程序的Scene中,加载美术烘焙好的地图Scene(UnityEngine.SceneManagement.LoadSceneMode.Additive)

注:在Unity2018.2.3中,若不设置Map Scene为ActiveScene会出现花屏的现象,在2019中则正常。

unity 烘焙 光照贴图 以及一些灯光的相关问题(二)相关推荐

  1. unity 烘焙 光照贴图 以及一些灯光的相关问题(一)

    在做游戏场景的时候,由于一般场景大部分的物体都是静止不动的(static),如果这些物体使用实时光照的话,会有很大的性能开销,比如物体的阴影.但是由于很多情况下,场景中大部分物体的位置不会在游戏运行的 ...

  2. 关于unity2019.3.11.f在烘焙光照贴图时闪退的问题

    在用unity2019版本的项目时一直有个问题困扰着我,就是勾选lighttingSetting中Auto Generate后,unity开始烘焙光照贴图时大概率立马闪退且没有任何报错信息. 为何说是 ...

  3. unity android光照贴图格式,光照贴图参数

    Lightmapping Quickstart 光照贴图定向模式 光照贴图参数 The Lightmap Parameters Asset is used to store a set of valu ...

  4. Unity教程||Unity 渐进式光照贴图烘焙详解

    随着各大计算平台的算力稳步增长,特别是GPU技术的不断进化,原先可望而不可及的技术比如实时光线追踪技术开始逐步走入玩家的视野.一些先锋厂商甚至已经超出Demo的范畴,开始正式推出支持实时光追的游戏. ...

  5. Unity 5光照贴图烘焙课程分享

    今天简单地跟大家分享一下Unity5.0里面的光照贴图烘焙技术.由于时间只有20分钟,所以只能给大家一些概要性的介绍,没有办法深入,等到Unity5.0版本正式推出之后,我会给大家一些更详细的介绍. ...

  6. Unity 5光照贴图烘焙

    1. 简介 2. 常用术语 1)  Light Probes:灯光探测器 光照贴图让场景变得很真实,但是有一个缺点,即场景中的非静态物体渲染时不太真实,结果看起来与场景脱节.虽然无法实时计算移动物体的 ...

  7. 【Unity】光照贴图动态加载

    一般情况下对场景进行烘焙后,其实不用关心光照贴图的加载问题,Unity会自动帮我们处理好的,比如这个测试场景,烘焙结束后,关掉烘焙灯光,运行,直接运行得到的效果就是预期这样,没有写任何代码,光照贴图就 ...

  8. Unity—GI光照贴图

    参考转载来源,unity全球官方网站&麦子学院魏知晓&Json_c: 什么是全局光照--Global Illumination/GI? 什么是光照贴图--LightMap? 什么是光照 ...

  9. unity android光照贴图格式,Unity3D-光照贴图技术

    概念 Lightmapping光照贴图技术是一种增强静态场景光照效果的技术,其优点是可以通过较少的性能消耗使静态场景看上去更加真实,丰富,更加具有立体感:缺点是不能用来实时地处理动态光照.当游戏场景包 ...

最新文章

  1. lib和dll文件的区别和联系(集合了几个博客的内容)
  2. python 编程一日一练-Python一日一练02----诗词生成器
  3. 微软出资10亿美元研究AGI,意与谷歌竞争?
  4. python 中set集合类型(去重、成员运算)
  5. SpringCloud系列七:使用Ribbon实现客户端侧负载均衡
  6. RFC的远程调用-异步
  7. ECMall插件——余额支付
  8. Qt Quick综合实例之文件查看器
  9. Mac和Windows中常见中文字体的英文名称
  10. 软件测试面试的自我介绍
  11. excel表格自动填充为汉字拼音首字母
  12. Mstar 光机遥控器适配
  13. 【Linux】动静态库及gdb的使用
  14. 22考研初试410数一145上岸上海交通大学819经验分享
  15. 毕业设计——基于小程序云开发的校园二手交易平台(附源码)
  16. C/C++使用ODBC连接MSSQL数据库
  17. RHCSA——第四天
  18. Xshell的安装与使用
  19. unity3d音频系统
  20. 行业应用 |从实践中读懂银行的敏感数据安全防护思路

热门文章

  1. 东方财富函数 量化交易 第001记录 量价研究的开始
  2. 斯坦福锁相放大器SR860 DSP技术特点
  3. 城商行牵手流量平台,开启信用卡合作新模式
  4. 一级建造师报名条件 (附网课)
  5. 如何在Spring Boot中使用TDD写出高质量的接口
  6. Linux下NTP时间同步服务器搭建
  7. 国外整理的一套在线渗透测试资源合集
  8. php增减库存,拼多多后台库存增减怎么设置?
  9. 生日祝福python代码
  10. local service system账户_Local System/Network Service/Local Service权限详解