Version: Unity 6.0 (6000.0)
语言 : 中文
升级 URP
升级到 URP 16 (Unity 2023.2)

升级到 URP 17 (Unity 6)

本页面介绍如何从旧版本的通用渲染管线 (URP) 升级到 URP 17 (Unity 6)。

如需了解如何将针对内置渲染管线项目制作的资源转换为与 URP 兼容的资源,请参阅渲染管线转换器页面。

从 URP 15 或 URP 16(Unity 2023.1、Unity 2023.2)升级

渲染图系统

URP 17 引入了渲染图系统,自定义渲染通道的编写方式有重大变化。

如果项目包含自定义渲染通道,请使用渲染图 API 重写通道。有关渲染图的更多信息,请参阅渲染图系统部分。

以下页面提供可编程渲染器功能的完整示例,该功能具有使用渲染图 API 的渲染通道:

注意:Unity 不再开发或改进不使用渲染图 API 的渲染路径。

默认情况下,在新 URP 项目中会启用 Render graph。

出于兼容性目的,Unity 6 提供了禁用渲染图系统并使用以前 URP 版本渲染 API 的选项。要禁用渲染图,请启用以下复选框:

  • 项目设置 (Project Settings) > 图形 (Graphics) > 渲染图 (Render Graph) > 兼容性模式(已禁用渲染图形)(Compatibility Mode (Render Graph Disabled))

如果打开使用不带渲染图的 URP 版本创建的现有项目,Unity 会在使用 Unity 6 打开项目后自动启用兼容模式。

为了更好地了解渲染图的实现,请使用 Render Graph Viewer

体积框架

创建覆盖 VolumeComponent.Override(VolumeComponent state, float interpFactor) 方法的自定义 Volume 组件类时,无论何时更改 VolumeParameter 值,您的实现都必须将 VolumeParameter.overrideState 属性设置为 true。这可确保 Volume 框架将各参数重置为正确的默认值。这使得框架每帧使用更少的资源,从而提高性能。

从 URP 13 (Unity 2022.1) 升级

删除了两个着色器定义

删除了 SHADER_QUALITY_LOW/MEDIUM/HIGHSHADER_HINT_NICE_QUALITY 着色器定义。如果在自定义着色器中使用了这些定义,请考虑使用 SHADER_API_MOBILESHADER_API_GLES 定义来替换 SHADER_QUALITY_LOW/MEDIUM/HIGH

从 URP 12 (Unity 2021.2) 升级

对 ScriptableRenderer API 行为的更改

现在,当 ScriptableRendererFeature 实例在 ScriptableRenderer 类分配渲染目标之前尝试访问渲染目标时,Unity 会发出错误。

ScriptableRendererFeature 类有一个新的虚拟函数 SetupRenderPasses,当渲染目标被分配并准备使用时会调用该函数。

如果您的代码使用 ScriptableRenderer.cameraColorTargetAddRenderPasses 方法覆盖中的 ScriptableRenderer.cameraDepthTarget 属性,则应将该实现移到 ScriptableRendererFeature.SetupRenderPasses 方法。

ScriptableRenderer.EnqueuePass 方法的调用仍将在 AddRenderPasses 方法中发生。

以下示例演示如何更改代码以使用新的 API。

使用旧 API 的代码:

public override void AddRenderPasses(ScriptableRenderer renderer,
                                    ref RenderingData renderingData)
{
    // The target is used before allocation
    m_CustomPass.Setup(renderer.cameraColorTarget);
     // Letting the renderer know which passes are used before allocation
    renderer.EnqueuePass(m_ScriptablePass);
}

使用新 API 的代码:

public override void AddRenderPasses(ScriptableRenderer renderer,
                                        ref RenderingData renderingData)
{
    // Letting the renderer know which passes are used before allocation
    renderer.EnqueuePass(m_ScriptablePass);
}

public override void SetupRenderPasses(ScriptableRenderer renderer,
                                          in RenderingData renderingData)
{
    // The target is used after allocation
    m_CustomPass.Setup(renderer.cameraColorTarget);
}

通用渲染器现在使用 RTHandle 系统

通用渲染器现在对其内部目标及其内部通道使用 RTHandle 系统

RenderTargetHandle 结构的所有用法都被设置为过时,并且该结构将在将来被删除。

公共接口 ScriptableRenderer.cameraColorTargetScriptableRenderer.cameraDepthTarget 标记为已过时。将二者分别替换为 ScriptableRenderer.cameraColorTargetHandleScriptableRenderer.cameraDepthTargetHandle

RTHandle 目标不使用 CommandBuffer.GetTemporaryRT 方法,并且会持续比 RenderTargetIdentifier 结构更多的帧。无法分配将属性 GraphicsFormatDepthBufferBits 设置为除 0 以外的任何值的 RTHandle 目标。cameraDepthTarget 属性必须与 cameraColorTarget 属性分开。

以下辅助函数允许您通过 RTHandle 系统创建和使用临时渲染目标,其方式与之前的 GetTemporaryRT 方法类似:

  • RenderingUtils.ReAllocateIfNeeded

  • ShadowUtils.ShadowRTReAllocateIfNeeded

如果渲染目标在应用程序的生命周期内没有更改,请使用 RTHandles.Alloc 方法分配 RTHandle 目标。此方法非常高效,因为代码不必检查是否应在每个帧上分配渲染目标。

如果渲染目标是全屏纹理,这意味着其分辨率与屏幕分辨率匹配或者是屏幕分辨率的一小部分,请使用 Vector2D.one 等缩放因子来支持动态缩放。

以下示例演示如何更改使用 RenderTargetHandle API 的代码以使用新的 API。

使用旧 API 的代码:

public class CustomPass : ScriptableRenderPass
{
    RenderTargetHandle m_Handle;
    // With the old API, RenderTargetIdentifier might combine color and depth
    RenderTargetIdentifier m_Destination;

    public CustomPass()
    {
        m_Handle.Init("_CustomPassHandle");
    }

    public override void OnCameraSetup(CommandBuffer cmd, ref RenderingData renderingData)
    {
        var desc = renderingData.cameraData.cameraTargetDescriptor;
        cmd.GetTemporaryRT(m_Handle.id, desc, FilterMode.Point);
    }

    public override void OnCameraCleanup(CommandBuffer cmd)
    {
        cmd.ReleaseTemporaryRT(m_Handle.id);
    }

    public void Setup(RenderTargetIdentifier destination)
    {
        m_Destination = destination;
    }

    public override void Execute(ScriptableRenderContext context,
                                    ref RenderingData renderingData)
    {
        CommandBuffer cmd = CommandBufferPool.Get();
        // Set the same target for color and depth
        ScriptableRenderer.SetRenderTarget(cmd, m_Destination, m_Destination, clearFlag,
                                              clearColor);
        context.ExecuteCommandBuffer(cmd);
        CommandBufferPool.Release(cmd);
    }
}

使用新 API 的代码:

public class CustomPass : ScriptableRenderPass
{
    RTHandle m_Handle;
    // Then using RTHandles, the color and the depth properties must be separate
    RTHandle m_DestinationColor;
    RTHandle m_DestinationDepth;

    void Dispose()
    {
        m_Handle?.Release();
    }

    public override void OnCameraSetup(CommandBuffer cmd, ref RenderingData renderingData)
    {
        var desc = renderingData.cameraData.cameraTargetDescriptor;
        // Then using RTHandles, the color and the depth properties must be separate
        desc.depthBufferBits = 0;
        RenderingUtils.ReAllocateIfNeeded(ref m_Handle, desc, FilterMode.Point,
                                         TextureWrapMode.Clamp, name: "_CustomPassHandle");
    }

    public override void OnCameraCleanup(CommandBuffer cmd)
    {
        m_DestinationColor = null;
        m_DestinationDepth = null;
    }

    public void Setup(RTHandle destinationColor, RTHandle destinationDepth)
    {
        m_DestinationColor = destinationColor;
        m_DestinationDepth = destinationDepth;
    }

    public override void Execute(ScriptableRenderContext context,
                                    ref RenderingData renderingData)
    {
        CommandBuffer cmd = CommandBufferPool.Get();
        ScriptableRenderer.SetRenderTarget(cmd, m_DestinationColor, m_DestinationDepth,
                                              clearFlag, clearColor);
        context.ExecuteCommandBuffer(cmd);
        CommandBufferPool.Release(cmd);
    }
}

从 URP 11.x.x 升级

  • 前向渲染器 (Forward Renderer) 资源更名为通用渲染器 (Universal Renderer) 资源。在包含 URP 12 的 Unity 编辑器中打开现有项目时,Unity 会将现有的前向渲染器资源更新为通用渲染器资源。

  • 通用渲染器资源包含 Rendering Path 属性,允许选择 Forward 或 Deferred Rendering Path。

  • ClearFlag.Depth 方法不再隐式清除模板缓冲区。使用新方法 ClearFlag.Stencil

  • URP 12 及更高版本实现了渲染管线转换器功能。此功能取代了以前在编辑 (Edit) > 渲染管道 (Render Pipeline) > 通用渲染管道 (Universal Render Pipeline) > 升级 (Upgrade)… 中提供的资源升级功能

从 URP 10.0.x–10.2.x 升级

  1. 以下 Shader Graph 着色器的文件名已重命名。新文件名称没有空格:
    Autodesk Interactive
    Autodesk Interactive Masked
    Autodesk Interactive Transparent

    如果代码中使用 Shader.Find() 方法来搜索着色器,请从着色器名称中移除空格,例如 Shader.Find("AutodeskInteractive)

从 URP 7.2.x 及更高版本升级

  1. URP 12.x.x 不支持 Post-Processing Stack v2 包。如果项目使用 Post-Processing Stack v2 包,请先迁移使用这个包的效果。

DepthNormals Pass

从 10.0.x 版开始,URP 可以生成名为 _CameraNormalsTexture 的法线纹理。要在自定义着色器中渲染到此纹理,请添加名为 DepthNormals 的通道。有关示例,请查看 Lit.shader 中的实现。

Screen Space Ambient Occlusion (SSAO)

URP 10.0.x 实现了屏幕空间环境光遮挡 (Screen Space Ambient Occlusion, SSAO) 效果。

如果打算将 SSAO 效果与自定义着色器一起使用,请考虑以下与 SSAO 相关的实体:

  • _SCREEN_SPACE_OCCLUSION 关键字

  • Input.hlslInputData 结构中包含新的声明float2 normalizedScreenSpaceUV

  • Lighting.hlsl 包含 AmbientOcclusionFactor 结构,其中包含用于计算间接和直接遮挡的变量:

    struct AmbientOcclusionFactor
    {
        half indirectAmbientOcclusion;
        half directAmbientOcclusion;
    };
    
  • Lighting.hlsl 包含以下用于对 SSAO 纹理进行采样的函数:

    half SampleAmbientOcclusion(float2 normalizedScreenSpaceUV)
    
  • Lighting.hlsl 包含以下函数:

    AmbientOcclusionFactor GetScreenSpaceAmbientOcclusion(float2
    normalizedScreenSpaceUV)
    

要在自定义着色器中支持 SSAO,请在着色器中添加 DepthNormals 通道和 _SCREEN_SPACE_OCCLUSION 关键字。有关示例,请查看 Lit.shader

如果您的自定义着色器实现了自定义光照函数,请使用函数 GetScreenSpaceAmbientOcclusion(float2 normalizedScreenSpaceUV) 获取用于光照计算的 AmbientOcclusionFactor 值。

阴影法线偏差

在 11.0.x 中,用于应用阴影法线偏差的公式已稍作修正,以便更好地处理精准光源。因此,为了精确匹配早期版本的阴影轮廓,可能需要在某些场景中调整参数。对于方向光,使用 1.4(而非 1.0)通常就足够了。

Intermediate Texture

在以前的 URP 版本中,如果渲染器具有任何活动的渲染器功能,URP 将通过中间渲染器执行渲染。在某些平台上,这会对性能产生重大影响。在此版本中,URP 通过以下方式缓解了该问题:URP 期望渲染器功能使用 ScriptableRenderPass.ConfigureInput 方法声明其输入。该方法提供 URP 使用的信息来自动确定是否需要通过 intermediate texture 进行渲染。

出于兼容性目的,通用渲染器中有一个新属性 Intermediate Texture。如果您在属性中选择 Always,URP 将使用 intermediate texture。选择 Auto 启用新行为。仅当渲染器功能未使用 ScriptableRenderPass.ConfigureInput 方法声明其输入时,才使用 Always 选项。

为了确保现有项目正常工作,使用任何渲染器功能(不包括 URP 中包含的功能)的所有现有通用渲染器资源都必须在 Intermediate Texture 属性中选择 Always 选项。任何新创建的通用渲染器资源都已选择 Auto 选项。

从 URP 7.0.x–7.1.x 升级

  1. 先升级到 URP 7.2.0。请参阅升级到通用渲染管线 7.2.0 版

  2. URP 8.x.x 不支持 Post-Processing Stack v2 包。如果项目使用 Post-Processing Stack v2 包,请先迁移使用这个包的效果。

从 LWRP 升级到 12.x.x

  • 从 LWRP 到 URP 12.x.x 没有直接的升级路径。按照步骤先将 LWRP 升级到 URP 11.x.x,然后从 URP 11.x.x 升级到 URP 12.x.x。
升级 URP
升级到 URP 16 (Unity 2023.2)