【UNITY】阴影优化小技巧0.3-0.7毫秒性能提升.
有机紫菜
2024年08月29日 20:17

这个技巧是之前卡普空分享过的,其在怪猎世界中的一个提升游戏性能的渲染小技巧.

原理很简单,就是让ShadowMap的生成帧率从每帧变为更长的周期,比如5帧更新一次.或者15帧一次.

这主要针对的是,那些对阴影变化要求不高的物体,比如静态的区域,或者是树叶,人物这些物体.

当然也可以,静态阴影和动态阴影分别调整,但是我没有试过这个.或许可以用层来处理这部分吧.

下面只是简单的,把Unity的Light---直接光的阴影投射帧率改为更长的周期.

改为每3-5帧更新一次.游戏的运行效率大概能提高0.3-0.9毫秒.大概5-8帧左右的提升.而对游戏效果来讲,影响较小,当然针对不同复杂度场景可能会有变化.

下面是使用方法.直接把脚本,放在Light灯光组件下就行了,注意灯光组件的阴影模式要改为

On Demand

代码块
C#
自动换行
复制代码
using UnityEngine.Rendering.HighDefinition;
using UnityEngine;

public class ShadowsCtrl : MonoBehaviour
{
    [Header("需要阴影更新模式改为OnDemand")]
    public HDAdditionalLightData targetLightData; // 指向要控制的光源
    public int shadowRenderFrequency = 5; // 每5帧渲染一次阴影
    private int frameCounter = 0;

//这里用late或者Update应该都可以
    void Update()
    {
        // 检查是否设置了目标光源
        if (targetLightData == null)
        {
            Debug.LogError("No light source assigned to ShadowFrequencyController.");
            return;
        }

        // 更新帧计数器并检查是否应该渲染阴影
        frameCounter = (frameCounter + 1) % shadowRenderFrequency;
        if (frameCounter == 0)
        {
            // 请求渲染阴影贴图
            targetLightData.RequestShadowMapRendering();
        }
    }
}
复制成功

注意.如果使用了Volume中的级联阴影组件.

则需要使用级联版本的控制脚本.

Volume中的级联版本阴影设置.

代码块
C#
自动换行
复制代码
using UnityEngine.Rendering.HighDefinition;
using UnityEngine;

public class CascadesShadowsCtrl : MonoBehaviour
{
    [Header("需要阴影更新模式改为OnDemand")]
    public HDAdditionalLightData targetLightData; // 指向要控制的光源

    public int[] cascadesRefreshWaitFrames = new int[NumberOfCascades];
    private int[] framesCounterCascades = new int[NumberOfCascades];

    private const int NumberOfCascades = 4;

    void Start()
    {
        ResetCounters();
    }
    private void ResetCounters()
    {
        // Initialize the refresh wait frames counters for shadow cascades
        for (int i = 0; i < NumberOfCascades; i++)
        {
            framesCounterCascades[i] = 0;
            //  secondsCounterCascades[i] = 0;
        }

    }
//这里用Late或者Update应该都可以
    void LateUpdate()
    {
        // 检查是否设置了目标光源
        if (targetLightData == null)
        {
            Debug.LogError("No light source assigned to ShadowFrequencyController.");
            return;
        }

        UpdateCascades();
    }

    private void UpdateCascades()
    {
        // Check which counter mode (frames or seconds) is selected

        for (int i = 0; i < framesCounterCascades.Length; i++)
        {
            framesCounterCascades[i]++;

            if (cascadesRefreshWaitFrames[i] > 0 && framesCounterCascades[i] >= cascadesRefreshWaitFrames[i])
            {
                targetLightData.RequestSubShadowMapRendering(i);
                framesCounterCascades[i] = 0;
            }
        }

    }
}
复制成功