版本:Unity 6 (6000.0)
语言:English
URP 中的兼容模式
URP 兼容模式下完整可脚本化渲染功能的示例

在 URP 的兼容模式中编写可脚本化的渲染通道

注意:Unity 不再开发或改进不使用 渲染图 API 的渲染路径。开发新的图形功能时,请使用渲染图 API。要使用本页上的说明,请在 URP 图形设置(项目设置 > 图形)中启用兼容模式(渲染图禁用)

以下示例是一个 ScriptableRenderPass 实例,它执行以下步骤

  1. 使用 RenderTextureDescriptor API 创建一个临时的 渲染纹理一种特殊的纹理类型,在运行时创建和更新。要使用它们,首先创建一个新的 Render Texture 并指定其中一个相机渲染到其中。然后,您可以在材质中像使用普通纹理一样使用 Render Texture。 更多信息
    请参阅 词汇表
  2. 使用 RTHandleBlit API 将 自定义着色器 的两个通道应用到 相机一个组件,它创建场景中特定视点的图像。输出要么绘制到屏幕上,要么作为纹理捕获。 更多信息
    请参阅 词汇表
    输出。

编写可脚本化渲染通道后,您可以使用以下方法之一注入渲染通道

创建可脚本化的渲染通道

本节演示如何创建可脚本化的渲染通道。

  1. 创建一个新的 C# 脚本,并将其命名为 RedTintRenderPass.cs

  2. 在脚本中,删除 Unity 在 RedTintRenderPass 类中插入的代码。添加以下 using 指令

    using UnityEngine.Rendering;
    using UnityEngine.Rendering.Universal;
    
  3. 创建继承自 ScriptableRenderPass 类的 RedTintRenderPass 类。

    public class RedTintRenderPass : ScriptableRenderPass
    
  4. 向类添加 Execute 方法。Unity 每帧调用一次此方法,每个相机调用一次。此方法允许您实现可脚本化渲染通道的渲染逻辑。

    public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
    { }
    

以下是本节中 RedTintRenderPass.cs 文件的完整代码。

using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;

public class RedTintRenderPass : ScriptableRenderPass
{
    public override void Execute(ScriptableRenderContext context,
        ref RenderingData renderingData)
    {
        
    }
}

实现自定义渲染通道的设置

  1. 添加一个材质字段,以及使用该字段的构造函数。

    private Material material;
    
    public RedTintRenderPass(Material material)
    {
        this.material = material;
    }
    
  2. 添加 RenderTextureDescriptor 字段,并在构造函数中对其进行初始化

    using UnityEngine;
    
    private RenderTextureDescriptor textureDescriptor;
    
    public RedTintRenderPass(Material material)
    {
        this.material = material;
    
        textureDescriptor = new RenderTextureDescriptor(Screen.width,
            Screen.height, RenderTextureFormat.Default, 0);
    }
    
  3. 声明 RTHandle 字段以存储对临时红色色调纹理的引用。

    private RTHandle textureHandle;
    
  4. 实现 Configure 方法。Unity 在执行渲染通道之前调用此方法。

    public override void Configure(CommandBuffer cmd,
        RenderTextureDescriptor cameraTextureDescriptor)
    {
        //Set the red tint texture size to be the same as the camera target size.
        textureDescriptor.width = cameraTextureDescriptor.width;
        textureDescriptor.height = cameraTextureDescriptor.height;
    
        //Check if the descriptor has changed, and reallocate the RTHandle if necessary.
        RenderingUtils.ReAllocateIfNeeded(ref textureHandle, textureDescriptor);
    }
    
  5. 使用 Blit“位块传输”的简写。Blit 操作是从内存中的一个位置将数据块传输到另一个位置的过程。
    请参阅 词汇表
    方法将来自自定义 着色器在 GPU 上运行的程序。 更多信息
    请参阅 词汇表
    的两个渲染通道应用到相机输出。

    public override void Execute(ScriptableRenderContext context,
        ref RenderingData renderingData)
    {
        //Get a CommandBuffer from pool.
        CommandBuffer cmd = CommandBufferPool.Get();
    
        RTHandle cameraTargetHandle =
            renderingData.cameraData.renderer.cameraColorTargetHandle;
    
        // Blit from the camera target to the temporary render texture,
        // using the first shader pass.
        Blit(cmd, cameraTargetHandle, textureHandle, material, 0);
        // Blit from the temporary render texture to the camera target,
        // using the second shader pass.
        Blit(cmd, textureHandle, cameraTargetHandle, material, 1);
    
        //Execute the command buffer and release it back to the pool.
        context.ExecuteCommandBuffer(cmd);
        CommandBufferPool.Release(cmd);
    }
    
  6. 实现 Dispose 方法,该方法在渲染通道执行后销毁材质和临时渲染纹理。

    public void Dispose()
    {
        #if UNITY_EDITOR
                if (EditorApplication.isPlaying)
                {
                    Object.Destroy(material);
                }
                else
                {
                    Object.DestroyImmediate(material);
                }
        #else
                Object.Destroy(material);
        #endif
            
        if (textureHandle != null) textureHandle.Release();
    }
    

自定义渲染通道代码

以下是自定义渲染通道脚本的完整代码。

using UnityEditor;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;

public class RedTintRenderPass : ScriptableRenderPass
{
    private Material material;

    private RenderTextureDescriptor textureDescriptor;
    private RTHandle textureHandle;

    public RedTintRenderPass(Material material)
    {
        this.material = material;

        textureDescriptor = new RenderTextureDescriptor(Screen.width,
            Screen.height, RenderTextureFormat.Default, 0);
    }

    public override void Configure(CommandBuffer cmd,
        RenderTextureDescriptor cameraTextureDescriptor)
    {
        // Set the texture size to be the same as the camera target size.
        textureDescriptor.width = cameraTextureDescriptor.width;
        textureDescriptor.height = cameraTextureDescriptor.height;

        // Check if the descriptor has changed, and reallocate the RTHandle if necessary
        RenderingUtils.ReAllocateIfNeeded(ref textureHandle, textureDescriptor);
    }

    public override void Execute(ScriptableRenderContext context,
        ref RenderingData renderingData)
    {
        //Get a CommandBuffer from pool.
        CommandBuffer cmd = CommandBufferPool.Get();

        RTHandle cameraTargetHandle =
            renderingData.cameraData.renderer.cameraColorTargetHandle;

        // Blit from the camera target to the temporary render texture,
        // using the first shader pass.
        Blit(cmd, cameraTargetHandle, textureHandle, material, 0);
        // Blit from the temporary render texture to the camera target,
        // using the second shader pass.
        Blit(cmd, textureHandle, cameraTargetHandle, material, 1);

        //Execute the command buffer and release it back to the pool.
        context.ExecuteCommandBuffer(cmd);
        CommandBufferPool.Release(cmd);
    }

    public void Dispose()
    {
    #if UNITY_EDITOR
        if (EditorApplication.isPlaying)
        {
            Object.Destroy(material);
        }
        else
        {
            Object.DestroyImmediate(material);
        }
    #else
            Object.Destroy(material);
    #endif

        if (textureHandle != null) textureHandle.Release();
    }
}

红色色调效果的自定义着色器

本节包含实现红色色调效果的自定义着色器的代码。

Shader "CustomEffects/RedTint"
{
    HLSLINCLUDE
    
        #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
        // The Blit.hlsl file provides the vertex shader (Vert),
        // the input structure (Attributes), and the output structure (Varyings)
        #include "Packages/com.unity.render-pipelines.core/Runtime/Utilities/Blit.hlsl"

    
        float4 RedTint (Varyings input) : SV_Target
        {
            float3 color = SAMPLE_TEXTURE2D(_BlitTexture, sampler_LinearClamp, input.texcoord).rgb;
            return float4(1, color.gb, 1);
        }

        float4 SimpleBlit (Varyings input) : SV_Target
        {
            float3 color = SAMPLE_TEXTURE2D(_BlitTexture, sampler_LinearClamp, input.texcoord).rgb;
            return float4(color.rgb, 1);
        }
    
    ENDHLSL
    
    SubShader
    {
        Tags { "RenderType"="Opaque" "RenderPipeline" = "UniversalPipeline"}
        LOD 100
        ZTest Always ZWrite Off Cull Off
        Pass
        {
            Name "RedTint"

            HLSLPROGRAM
            
            #pragma vertex Vert
            #pragma fragment RedTint
            
            ENDHLSL
        }
        
        Pass
        {
            Name "SimpleBlit"

            HLSLPROGRAM
            
            #pragma vertex Vert
            #pragma fragment SimpleBlit
            
            ENDHLSL
        }
    }
}
URP 中的兼容模式
URP 兼容模式下完整可脚本化渲染功能的示例