文章目录
- 环境
- 原因
- 解决
- 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 文档