zoukankan      html  css  js  c++  java
  • Unity3D研究院之Unity5.x运行时动态更新烘培贴图

    Unity3D研究院之Unity5.x运行时动态更新烘培贴图(八十七)

    前段时间我研究过这个问题,但是没有解决只好作罢。今天刚好有人又问我这个问题,我得空查了一下还是找到了解决办法。另外也感谢问我的人,解答问题的同时也是我学习的过程。

    运行时更新烘培贴图分两种情况

    1、场景的物件没有发生变化(也就是说没有运行时加载在场景上的Prefab)此时可以直接更换烘培贴图。

    usingUnityEngine;
    usingSystem.Collections;
     
    public class NewBehaviourScript : MonoBehaviour {
     
     //烘培烘培贴图1
     public Texture2DgreenLightMap;
     //烘培贴图2
     public Texture2DredLightMap;
     void OnGUI()
     {
     if(GUILayout.Button("green"))
     {
     LightmapDatadata = new LightmapData();
     data.lightmapFar = greenLightMap;
     LightmapSettings.lightmaps = new LightmapData[1]{data};
     }
     
     if(GUILayout.Button("red"))
     {
     LightmapDatadata = new LightmapData();
     data.lightmapFar = redLightMap;
     LightmapSettings.lightmaps = new LightmapData[1]{data};
     }
     }
    }
    

    2.场景的烘培贴图已经更新,但是有些物件prefab想运行时加载进来。如果直接Instance的话 这个Prefab是没有烘培信息的。(灰颜色的)

    解决这个问题我查到了 一篇大大的文章,它带了例子大家可以下载下来。 http://forum.unity3d.com/threads/problems-with-instantiating-baked-prefabs.324514/#post-2177524

    代码在这里,把如下代码挂在GameObject上。当场景烘培结束后,把他保存成prefab,运行的时候直接加载进来就行了。

    usingUnityEngine;
    usingSystem.Collections;
    usingSystem.Collections.Generic;
     
    public class PrefabLightmapData : MonoBehaviour
    {
     [System.Serializable]
     struct RendererInfo
     {
     public Rendererrenderer;
     public int lightmapIndex;
     public Vector4lightmapOffsetScale;
     }
     
     [SerializeField]
     RendererInfo[] m_RendererInfo;
     [SerializeField]
     Texture2D[] m_Lightmaps;
     
     void Awake ()
     {
     if (m_RendererInfo == null || m_RendererInfo.Length == 0)
     return;
     
     var lightmaps = LightmapSettings.lightmaps;
     var combinedLightmaps = new LightmapData[lightmaps.Length + m_Lightmaps.Length];
     
     lightmaps.CopyTo(combinedLightmaps, 0);
     for (int i = 0; i < m_Lightmaps.Length;i++)
     {
     combinedLightmaps[i+lightmaps.Length] = new LightmapData();
     combinedLightmaps[i+lightmaps.Length].lightmapFar = m_Lightmaps[i];
     }
     
     ApplyRendererInfo(m_RendererInfo, lightmaps.Length);
     LightmapSettings.lightmaps = combinedLightmaps;
     }
     
     
     static void ApplyRendererInfo (RendererInfo[] infos, int lightmapOffsetIndex)
     {
     for (int i=0;i<infos.Length;i++)
     {
     var info = infos[i];
     info.renderer.lightmapIndex = info.lightmapIndex + lightmapOffsetIndex;
     info.renderer.lightmapScaleOffset = info.lightmapOffsetScale;
     }
     }
     
    #if UNITY_EDITOR
     [UnityEditor.MenuItem("Assets/Bake Prefab Lightmaps")]
     static void GenerateLightmapInfo ()
     {
     if (UnityEditor.Lightmapping.giWorkflowMode != UnityEditor.Lightmapping.GIWorkflowMode.OnDemand)
     {
     Debug.LogError("ExtractLightmapData requires that you have baked you lightmaps and Auto mode is disabled.");
     return;
     }
     UnityEditor.Lightmapping.Bake();
     
     PrefabLightmapData[] prefabs = FindObjectsOfType<PrefabLightmapData>();
     
     foreach (var instancein prefabs)
     {
     var gameObject = instance.gameObject;
     var rendererInfos = new List<RendererInfo>();
     var lightmaps = new List<Texture2D>();
     
     GenerateLightmapInfo(gameObject, rendererInfos, lightmaps);
     
     instance.m_RendererInfo = rendererInfos.ToArray();
     instance.m_Lightmaps = lightmaps.ToArray();
     
     var targetPrefab = UnityEditor.PrefabUtility.GetPrefabParent(gameObject) as GameObject;
     if (targetPrefab != null)
     {
     //UnityEditor.Prefab
     UnityEditor.PrefabUtility.ReplacePrefab(gameObject, targetPrefab);
     }
     }
     }
     
     static void GenerateLightmapInfo (GameObjectroot, List<RendererInfo> rendererInfos, List<Texture2D> lightmaps)
     {
     var renderers = root.GetComponentsInChildren<MeshRenderer>();
     foreach (MeshRendererrendererin renderers)
     {
     if (renderer.lightmapIndex != -1)
     {
     RendererInfoinfo = new RendererInfo();
     info.renderer = renderer;
     info.lightmapOffsetScale = renderer.lightmapScaleOffset;
     
     Texture2Dlightmap = LightmapSettings.lightmaps[renderer.lightmapIndex].lightmapFar;
     
     info.lightmapIndex = lightmaps.IndexOf(lightmap);
     if (info.lightmapIndex == -1)
     {
     info.lightmapIndex = lightmaps.Count;
     lightmaps.Add(lightmap);
     }
     
     rendererInfos.Add(info);
     }
     }
     }
    #endif
     
    }
    

    点击 Assets/Bake Prefab Lightmaps 进行烘培, 这样它的脚本里会把index 和 offset保存在prefab里。它还会保存上当前烘培场景的Lightmap,如果运行时想更换的话,你可以加一些自己的逻辑进行切换。

    最后欢迎大家测试,欢迎大家提出宝贵意见,我们一起把unity这个坑填了!

  • 相关阅读:
    CSS
    WebStorm快捷键
    每日一题
    周末了周末了
    集合,个人理解
    Linux学习笔记
    Java对象的序列化和反序列化实践
    Android 实现蘑菇街购物车动画效果
    【转】android手势处理揭秘
    【转】android 手势识别和VelocityTracker
  • 原文地址:https://www.cnblogs.com/muyouking/p/6647967.html
Copyright © 2011-2022 走看看