Unity(四十五):光照烘焙

运行时更换烘焙贴图 及 环境光照颜色对静态对象和非静态对象的影响

效果

在这里插入图片描述

勾选静态对象属性

在这里插入图片描述

属性: 功能:
Nothing 对于任何系统,都不将游戏对象包含在预计算中。
Everything 对于下方的任何系统,都将游戏对象包含在预计算中。
Contribute GI 如果启用此属性,Unity 在全局光照计算中包含目标网格渲染器。这些计算是在烘焙时预计算光照数据时进行的。ContributeGI 属性公开 ReceiveGI 属性。ContributeGI 属性仅在对目标场景启用全局光照设置(如 Baked Global Illumination 或 Realtime Global Illumination 时生效。关于使用光照探针进行静态光照的 Unity 博客文章提供使用此标志的指南。有关其他上下文,请参阅 Unity 中的内置渲染管线和照明的设置教程。
Occluder Static 在遮挡剔除系统中,将游戏对象标记为静态遮挡物。有关更多信息,请参阅有关遮挡剔除系统的文档。
Occludee Static 在遮挡剔除系统中,将游戏对象标记为静态被遮挡物。有关更多信息,请参阅有关遮挡剔除系统的文档。
Batching Static 将游戏对象的网格与其他符合条件的网格组合起来,有可能降低运行时渲染成本。有关更多信息,请参阅有关静态批处理的文档。
Navigation Static 在预计算导航数据时包含游戏对象。有关更多信息,请参阅有关导航系统的文档。
Off Mesh Link Generation 在预计算导航数据时,尝试生成一个从该游戏对象开始的网格外链接。有关更多信息,请参阅有关自动构建网格外链接的文档。
Reflection Probe 为 Type 属性设置为 Baked 的反射探针预计算数据时,包含此游戏对象。有关更多信息,请参阅有关反射探针的文档。

配置光照模式为烘焙模式

在这里插入图片描述

变量 描述
Realtime 光源是实时光源。没有贡献将在光照贴图或光照探针中烘焙。
Mixed 光源是混合光源。混合光源根据光照窗口中的全局光照模式设置进行解释。
Baked 光源是完全烘焙光源,没有实时组件。
Unknown 烘焙后端应忽略光源。

烘焙场景

Window ---> Rendering ---> Lighting

在这里插入图片描述

查看静态游戏对象

在这里插入图片描述

多次烘焙保存其中的烘焙好的贴图并在运行时配置烘焙贴图

在这里插入图片描述

更换贴图脚本

using UnityEngine;
using UnityEngine.Rendering;

public class BakeMap : MonoBehaviour
{
    
    
    // LightmapData 光照贴图的数据
    //      lightmapColor   存储入射光颜色的光照贴图。
    //      lightmapDir	    存储入射光主要方向的光照贴图。
    //      shadowMask	    存储每个光源的遮挡遮罩的纹理(ShadowMask,最多四个光源)。
    private LightmapData _data;

    public Color color;

    public Texture2D lightmapColor1;
    public Texture2D lightmapColor2;
    public Texture2D lightmapDir;

    private void Start()
    {
    
    
        _data = new LightmapData();
    }

    private void Update()
    {
    
    
        // RenderSettings 渲染设置包含场景中一系列视觉元素的值,例如雾效和环境光。
        //      ambientMode     环境光照模式
        //              Skybox      基于天空盒的环境光照或自定义环境光照。
        //              Trilight    Trilight 环境光照。
        //              Flat	    平面环境光照。
        //              Custom	    环境光照是由自定义立方体贴图定义的。
        //      ambientLight	平面环境光照颜色
        RenderSettings.ambientMode = AmbientMode.Flat;
        RenderSettings.ambientLight = color;
    }

    private void OnGUI()
    {
    
    
        // LightmapSettings.lightmaps 光照贴图数组。

        if (GUILayout.Button("lightmapColor 1"))
        {
    
    
            _data.lightmapColor = lightmapColor1;
            _data.lightmapDir = lightmapDir;
            LightmapSettings.lightmaps = new[] {
    
     _data };
        }

        if (GUILayout.Button("lightmapColor 2"))
        {
    
    
            _data.lightmapColor = lightmapColor2;
            _data.lightmapDir = lightmapDir;
            LightmapSettings.lightmaps = new[] {
    
     _data };
        }
    }
}

将带有光照贴图的游戏对象保存为预设体

直接将带有光照贴图的游戏对象保存为预设体时光照贴图并不会直接保存,必须要重新烘焙才行
解决方案:用脚本保存烘焙信息,当游戏运行时将烘焙信息赋值到渲染组件上

未接受烘焙游戏对象保存为预设体的效果

在这里插入图片描述

接受烘焙游戏对象保存为预设体的效果

在这里插入图片描述

脚本

using System;
using UnityEditor;
using UnityEngine;

public class PrefabLightmap : MonoBehaviour
{
    
    
    public int lightmapIndex;
    public Vector4 lightmapScaleOffset;

    private void Awake()
    {
    
    
        Renderer rendererComponent = GetComponent<Renderer>();

        if (rendererComponent)
        {
    
    
            // 应用到该渲染器的烘焙光照贴图的索引。默认值为 -1 (0xFFFF),表示未指定任何光照贴图
            rendererComponent.lightmapIndex = lightmapIndex;
            // 用于光照贴图的 UV 缩放和偏移。
            rendererComponent.lightmapScaleOffset = lightmapScaleOffset;
        }
    }

#if UNITY_EDITOR
    [MenuItem("GameObject/Light/ToPrefab")]
    public static void ToPrefab()
    {
    
    
        // Selection.activeTransform 返回当前点击的场景游戏物体.选择多个则返回第一个选择的,未选择相应的则返回null
        if (Selection.activeTransform)
        {
    
    
            Renderer renderer = Selection.activeTransform.GetComponent<Renderer>();

            if (renderer)
            {
    
    
                // 获取脚本
                PrefabLightmap prefabLightmap = Selection.activeTransform.GetComponent<PrefabLightmap>();
                // 脚本不存在 并且 存在光照贴图
                if (!prefabLightmap && renderer.lightmapIndex != -1)
                {
    
    
                    prefabLightmap = Selection.activeTransform.gameObject.AddComponent<PrefabLightmap>();
                    // 配置脚本的变量
                    prefabLightmap.lightmapIndex = renderer.lightmapIndex;
                    prefabLightmap.lightmapScaleOffset = renderer.lightmapScaleOffset;
                }

                Debug.Log(PrefabUtility.IsPartOfAnyPrefab(Selection.activeTransform)); // 如果给定对象是任何种类的预制件的一部分,则返回 true。
                Debug.Log(PrefabUtility.IsPartOfPrefabAsset(Selection.activeTransform)); // 如果给定对象是预制件资源的一部分,则返回 true。
                Debug.Log(PrefabUtility.IsPartOfPrefabInstance(Selection.activeTransform)); // 如果给定对象是预制件实例的一部分,则返回 true。

                bool isPrefab = PrefabUtility.IsPartOfPrefabInstance(Selection.activeTransform);

                if (isPrefab)
                {
    
    
                    // ApplyPrefabInstance 将预制件实例上的所有重载应用于其预制件资源。
                    PrefabUtility.ApplyPrefabInstance(Selection.activeTransform.gameObject, InteractionMode.UserAction);
                }
                else
                {
    
    
                    // SaveAsPrefabAsset
                    //      使用该函数,在给定路径上,从给定的游戏对象创建一个预制件资源(包括场景中的任何子项),而不修改输入对象。
                    // SaveAsPrefabAssetAndConnect
                    //      使用该函数,在给定路径上,从给定的游戏对象创建一个预制件资源(包括场景中的任何子项),同时让给定游戏对象进入新预制件的实例。

                    // InteractionMode 调用 API 方法时使用的交互模式(用户模式或自动模式)。
                    // 如果要创建执行编辑器操作的编辑器工具或自动化流程,这非常有用。
                    //      AutomatedAction	    使用此设置可防止方法向用户显示对话框,并防止其记录到撤消历史记录中。
                    //      UserAction	        使用此设置可允许方法向用户显示对话框,并允许其记录到撤消历史记录中。
                    string path = $"Assets/Prefabs/{
      
      Selection.activeTransform.name}.prefab";
                    PrefabUtility.SaveAsPrefabAsset(Selection.activeTransform.gameObject, path);
                    // PrefabUtility.SaveAsPrefabAssetAndConnect(Selection.activeTransform.gameObject, path, InteractionMode.UserAction);
                }
            }
        }
    }
#endif
}
#if UNITY_EDITOR
[CustomEditor(typeof(PrefabLightmap))]
class PrefabLightmapEditor : Editor
{
    
    
    public override void OnInspectorGUI()
    {
    
     
        base.OnInspectorGUI();

        // 自动烘焙

        // if (GUILayout.Button("烘焙"))
        {
    
    
            PrefabLightmap script = target as PrefabLightmap;

            Renderer render = script.gameObject.GetComponent<Renderer>();

            if (render != null)
            {
    
    
                render.lightmapIndex = script.lightmapIndex;
                render.lightmapScaleOffset = script.lightmapScaleOffset;
            }
        }
    }
}
#endif

猜你喜欢

转载自blog.csdn.net/weixin_43526371/article/details/123991275
今日推荐