文章目录
- 环境
- 原因
- 解决
- CSharp 脚本
- 效果预览 - Light.shadowCustomResolution
- 效果预览 - Using Quality Settings
 
- 应用
- ControlLightShadowResolution.cs Component
- Tools Batching add the Component to all Light
 
- References
环境
Unity : 2020.3.37f1
 Pipeline : BRP
原因
(好久没搬砖了,偶尔健身一下,顺便将这些无技术含量的内容,记到 blog,不要记在脑子)
最近给项目做优化的过程中
 发现 BRP 管线下的 Shadow Resolution 只能在 Project Settings/Quality/Shadow Resolution 去设置
 而且发现
 Shadow Resolution 的一些枚举为:
- Low Resolution - 1K
- Medium Resolution - 2K
- High Resolution - 4K
- Very High Resolution - 4K (这个可能因硬件不同而不同)


解决
但是如果想要设置更小的 shadow resolution 的话,这步就没辙了?
 还好我去公司中台请教了 TA 专家,他说 BRP 中一样是可以设置的

CSharp 脚本
// jave.lin 2023/03/06 custom shadow resolution
// refer to : https://docs.unity3d.com/Manual/shadow-mapping.html
using UnityEngine;
public enum eCustomShadowResolution
{
    UsingQualitySettings = 0,
    Low = 128,
    Medium = 256,
    High = 512,
    VeryHigh = 1024,
}
[ExecuteInEditMode]
public class LightCustomShadowResolution : MonoBehaviour
{
    public bool runInUpdate = true;
    public eCustomShadowResolution shadowSize = eCustomShadowResolution.High;
    private Light lightComp;
    private void Update()
    {
        if (runInUpdate)
        {
            if (lightComp == null)
            {
                lightComp = GetComponent<Light>();
            }
            if (lightComp == null)
            {
                return;
            }
            lightComp.shadowCustomResolution = (int)shadowSize;
        }
    }
}
效果预览 - Light.shadowCustomResolution
Light.shadowCustomResolution = val
- 这个 val不等于 0 的话,就是自定义设置,这个val会自动 mostest NPOT == Mostest Next Power Of Tow
- 这个 val等于 0 的话,就是使用 Quality Settings 的全局配置
  
效果预览 - Using Quality Settings

应用
只需要编写工具,批量对项目中的 Scene、Prefab,遍历其下所有 Light 的 GameObject 添加 改组件即可
ControlLightShadowResolution.cs Component
// jave.lin 2023/03/06 control light shadow resolution, [attach to light]
using UnityEditor.SearchService;
using UnityEngine;
using War.Script;
[ExecuteInEditMode]
public class ControlLightShadowResolution : MonoBehaviour
{
    public eLightShadowResolutionFollowQualitySetting followQualitySetting;
    public int shadowSize;
#if UNITY_EDITOR
    public bool runInUpdate = true;
#endif
    private Light lightComp;
    private void Start()
    {
        int level = UIInterface.GetCsharpEventCenterLevel();
        OnQualityLevelChanged(level);
        // TODO: xxx 修改为对应的时间名
        EventMgr.Instance.RemoveEvent<int>("xxx", OnQualityLevelChanged);
        EventMgr.Instance.AddEvent<int>("xxx", OnQualityLevelChanged);
    }
    private void OnDestroy()
    {
        // TODO: xxx 修改为对应的时间名
        EventMgr.Instance.RemoveEvent<int>("xxx", OnQualityLevelChanged);
    }
#if UNITY_EDITOR
    private void Update()
    {
        if (runInUpdate)
        {
            ApplyChanged();
        }
    }
#endif
    private void OnQualityLevelChanged(int lv)
    {
        if (followQualitySetting == eLightShadowResolutionFollowQualitySetting.On)
        {
            shadowSize = 0;
        }
        else
        {
            eQualityLevel level = (eQualityLevel)lv;
            switch (level)
            {
                case eQualityLevel.VeryLow:
                    shadowSize = (int)eLightCustomShadowResolutionSize.VeryLow;
                    break;
                case eQualityLevel.Low:
                    shadowSize = (int)eLightCustomShadowResolutionSize.Low;
                    break;
                case eQualityLevel.Medium:
                    shadowSize = (int)eLightCustomShadowResolutionSize.Medium;
                    break;
                case eQualityLevel.High:
                    shadowSize = (int)eLightCustomShadowResolutionSize.High;
                    break;
                default:
                    break;
            }
        }
        ApplyChanged();
    }
    private void ApplyChanged()
    {
        if (lightComp == null)
        {
            lightComp = GetComponent<Light>();
        }
        if (lightComp == null)
        {
            return;
        }
        lightComp.shadowCustomResolution = shadowSize;
    }
}
Tools Batching add the Component to all Light
// 伪代码
var scene = EditorSceneManager.xxxByPath("xxx");
var roots = scene.GetxxxxRoots();
foreach (var root in roots)
{
	var lights = root.GetComponents<Light>();
	// 剩下的同下代码
}
    public static void AddControlLightShadowResolution()
    {
        var lights = GameObject.FindObjectsOfType<Light>();
        foreach (var light in lights)
        {
            if (light == null)
                continue;
            ControlLightShadowResolution comp = light.transform.GetComponent<ControlLightShadowResolution>();
            if (light.lightmapBakeType == LightmapBakeType.Realtime)
            {
                if (comp == null)
                {
                    light.gameObject.AddComponent<ControlDepthMode>();
                }
            }
            else
            {
                if (comp != null)
                {
                    if (Application.isPlaying)
                        GameObject.Destroy(comp);
                    else
                        GameObject.DestroyImmediate(comp);
                }
            }
        }
    }
References
- shadow-mapping - unity 官方 shadow map 文档



















