首页 > 其他分享 >Unity6 URP17使用初探

Unity6 URP17使用初探

时间:2024-11-01 12:22:10浏览次数:5  
标签:mMyBlurPass RenderGraph material URP17 rt1 Unity6 初探 new public

1.简介

随着Unity6的发布,URP17也已经可以上手使用,相对旧的版本改动较大的是加入了

RenderGraph、STP、Foveated rendering、GPU Resident Drawer等功能,部分功能只需要开关参数即可使用,

而GRD更像是Gpu driven管线下的SRP Batches升级,RenderGraph相较于HDRP之前使用的版本换了一套API。

最大的不同是,使用URP17编写Feature时,必须依赖于RenderGraph进行编写,接下来就来介绍一下。

 

1.1 相关Demo

目前URP17比较容易找到的学习Demo如下:

2.RenderGraph

打开任意URP的示例场景查看,RenderGraphView上各图标含义如下:

  1. 说明这是一个外部置入的RenderTexture
  2. 红色方块说明存在写入操作
  3. 绿色方块指存在读取操作(红绿方块说明读写操作)
  4. 该图标说明标记了全局RenderTexture

 而顶部表明当前渲染一帧的各个Pass,左侧是各类RT。

 

URP17同时保留了旧的Feature逻辑与RenderGraph逻辑(打开任意pass文件为例):

public class DistortTunnelPass_Tunnel : ScriptableRenderPass
{
    class PassData
    {
        public Renderer tunnelObject;
        public Material tunnelMaterial;
    }


#pragma warning disable 618, 672 // Type or member is obsolete, Member overrides obsolete member

    // Unity calls the Configure method in the Compatibility mode (non-RenderGraph path)
    public override void Configure(CommandBuffer cmd, RenderTextureDescriptor cameraTextureDescripor)
    {
    }

    // Unity calls the Execute method in the Compatibility mode
    public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
    {
    }

#pragma warning restore 618, 672

    // Unity calls the RecordRenderGraph method to add and configure one or more render passes in the render graph system.
    public override void RecordRenderGraph(RenderGraph renderGraph, ContextContainer frameData)
    {
    }
}

参考时忽略掉Configure和Execute的逻辑,执行逻辑关注RecordRenderGraph函数。

 

2.1 操作方式的改变

在RenderGraph中,之前的RTHandle由于不在该系统中托管,进入RenderGraph的材质都需要调用API进行转换,

转换为RendeGraph的RT后,无需考虑释放操作:

RenderTextureDescriptor textureProperties = new RenderTextureDescriptor(Screen.width, Screen.height, RenderTextureFormat.Default, 0);
TextureHandle textureHandle = UniversalRenderer.CreateRenderGraphTexture(renderGraph, textureProperties, "My texture", false);

相关文档:

https://docs.unity3d.com/Manual/urp/render-graph-create-a-texture.html

 

此外RenderGraph对于空调用的pass,也会剔除进行优化,使用者需要手动标记以防止被剔除。

 

2.1 RecordRenderGraph

在该函数内可组织渲染逻辑,pass相关的逻辑需放在对应的代码块中,例如:

using (var builder = renderGraph.AddRasterRenderPass<PassData>(passName, out _))
{
    builder.UseTexture(rt1);
    builder.SetRenderAttachment(resourceData.activeColorTexture, 0);

    builder.SetRenderFunc<PassData>((data, context) =>
    {
        MaterialPropertyBlock materialPropertyBlock = new MaterialPropertyBlock();
        materialPropertyBlock.SetTexture("_BlitTexture", rt1);
        materialPropertyBlock.SetVector("_BlitScaleBias", new Vector4(1, 1, 0, 0));

        context.cmd.DrawProcedural(Matrix4x4.identity, material, 0, MeshTopology.Triangles, 3, 1, materialPropertyBlock);
    });
}

URP提供了多种RenderPass,例如处理光栅化相关逻辑使用RasterRenderPass组织相关逻辑。

在RenderPass的代码块中可使用builder对象配置RenderTarget、标记材质的读写等

而具体的pass绘制逻辑则在SetRenderFunc代码块中。

 

RecordRenderGraph内可以调用多次AddRenderPass,但URP并没有整理旧API的代码和相关工具类,

以至于容易使用旧的API导致报错,这点需要注意。

 

3.编写Feature

3.1 Blit与SetTarget

从前有句俗话“切RT的性能消耗相当于半个pass”,Unity SRP在几个版本的升级都在逐渐强调不切RenderTarget直接绘制,

如Cockpit Demo的屏幕空间描边。

 

3.2 屏幕模糊Demo

下面通过屏幕模糊Demo案例,演示URP17下pass的编写。

 

通过外部EnqueuePass的方式,在场景中通过控制器脚本添加该Pass,

MyBlurSceneController.cs:

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

public class MyBlurSceneController : MonoBehaviour
{
    public Material material;
    [Range(2, 15)] public int blurPasses = 3;
    [Range(0, 4)] public int downSample = 0;
    [Range(0.0f, 10f)] public float offset = 0.2f;

    public RenderPassEvent injectionPoint = RenderPassEvent.BeforeRenderingPostProcessing;
    public int injectionPointOffset = 0;
    public ScriptableRenderPassInput inputRequirements = ScriptableRenderPassInput.Color;
    public CameraType cameraType = CameraType.Game;

    private MyBlurPass mMyBlurPass;


    private void OnEnable()
    {
        SetupPass();

        RenderPipelineManager.beginCameraRendering += OnBeginCamera;
    }

    private void OnDisable()
    {
        RenderPipelineManager.beginCameraRendering -= OnBeginCamera;
    }

    public virtual void SetupPass()
    {
        mMyBlurPass = new MyBlurPass();

        mMyBlurPass.renderPassEvent = injectionPoint + injectionPointOffset;
        mMyBlurPass.material = material;

        mMyBlurPass.ConfigureInput(inputRequirements);
    }

    public virtual void OnBeginCamera(ScriptableRenderContext ctx, Camera cam)
    {
        if (mMyBlurPass == null || material == null)
            return;

        if ((cam.cameraType & cameraType) == 0) return;

        mMyBlurPass.blurPasses = blurPasses;
        mMyBlurPass.downSample = downSample;
        mMyBlurPass.offset = offset;

        cam.GetUniversalAdditionalCameraData().scriptableRenderer.EnqueuePass(mMyBlurPass);
    }
}

 

MyBlurPass.cs:

using UnityEngine;
using UnityEngine.Rendering.RenderGraphModule;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;
using UnityEngine.Rendering.RenderGraphModule.Util;

public class MyBlurPass : ScriptableRenderPass
{
    public class PassData
    {
        public TextureHandle tempRt1;
        public TextureHandle tempRt2;
    }

    public Material material;
    [Range(2, 15)] public int blurPasses = 3;
    [Range(1, 4)] public int downSample = 1;
    [Range(0.0f, 10f)] public float offset = 0.2f;


    public override void RecordRenderGraph(RenderGraph renderGraph, ContextContainer frameData)
    {
        var resourceData = frameData.Get<UniversalResourceData>();
        var passData = new PassData();

        var w = Screen.width >> downSample;
        var h = Screen.height >> downSample;

        RenderTextureDescriptor textureProperties = new RenderTextureDescriptor(w, h, RenderTextureFormat.Default, 0);
        passData.tempRt1 = UniversalRenderer.CreateRenderGraphTexture(renderGraph, textureProperties, "MyBlurPassTempRt1", false);

        textureProperties = new RenderTextureDescriptor(w, h, RenderTextureFormat.Default, 0);
        passData.tempRt2 = UniversalRenderer.CreateRenderGraphTexture(renderGraph, textureProperties, "MyBlurPassTempRt2", false);

        var rt1 = passData.tempRt1;
        var rt2 = passData.tempRt2;

        //将屏幕RT Blit到rt1上
        var para = new RenderGraphUtils.BlitMaterialParameters(resourceData.activeColorTexture, rt1, material, 0);
        renderGraph.AddBlitPass(para, "MyBlurPassBlitFirst");

        material.SetFloat("_SampleOffset", offset);

        //模糊迭代
        for (int i = 0; i < blurPasses - 1; ++i)
        {
            para = new RenderGraphUtils.BlitMaterialParameters(rt1, rt2, material, 0);
            renderGraph.AddBlitPass(para, $"MyBlurPassBlit_{i}");

            var tmp = rt1;
            rt1 = rt2;
            rt2 = tmp;
        }

        //通过直接绘制的方式,将模糊RT绘制到屏幕上
        using (var builder = renderGraph.AddRasterRenderPass<PassData>(passName, out _))
        {
            builder.UseTexture(rt1);
            builder.SetRenderAttachment(resourceData.activeColorTexture, 0);

            builder.SetRenderFunc<PassData>((data, context) =>
            {
                MaterialPropertyBlock materialPropertyBlock = new MaterialPropertyBlock();
                materialPropertyBlock.SetTexture("_BlitTexture", rt1);
                materialPropertyBlock.SetVector("_BlitScaleBias", new Vector4(1, 1, 0, 0));

                context.cmd.DrawProcedural(Matrix4x4.identity, material, 0, MeshTopology.Triangles, 3, 1, materialPropertyBlock);
            });
        }
    }
}

 

接着在ShaderGraph中连出模糊的逻辑,注意Blit对应的参数_BlitTexture、_BlitScaleBias:

 

最后在场景中挂载控制器以及材质球,即可使用该模糊Pass。

 

标签:mMyBlurPass,RenderGraph,material,URP17,rt1,Unity6,初探,new,public
From: https://www.cnblogs.com/hont/p/18515153

相关文章

  • 初探python栈帧逃逸
    前言以前在一些大型比赛就遇到这种题,一直没时间去研究,现在康复训练下:)生成器介绍生成器(Generator)是Python中一种特殊的迭代器,它可以在迭代过程中动态生成值,而不需要一次性将所有值存储在内存中。SimpleDemo这里定义一个生成器函数,生成器使用yield语句来产生值,每次调用生成......
  • 鸿蒙开发初探
    目录引言一、鸿蒙操作系统概述1.微内核架构2.多设备协同二、鸿蒙开发环境搭建1.安装DevEcoStudio2.创建项目3.开发与调试三、鸿蒙应用的开发1.UI设计2.业务逻辑3.分布式能力四、鸿蒙的应用场景1.智能家居2.健康监测3.智能出行五、总结引言 ......
  • [Ansible实践笔记]自动化运维工具Ansible(一):初探ansible&ansible的点对点模式
    文章目录Ansible介绍核心组件任务执行方式实验前的准备更新拓展安装包仓库在ansible主机上配置ip与主机名的对应关系生成密钥对将公钥发送到被管理端,实现免密登录测试一下是否实现免密登录常用工具ansibleansible—docansible—playbook主要配置文件Ansible模块配置......
  • AES初探
    AES为分组密码,每次加密一组数据使用不同长度的密钥,加密的轮数也不同加密公式C=E(K,P)下面介绍加密轮函数的四个操作:字节代换、行位移、列混合、轮密钥加以AES-128为例字节代换字节代换通过S盒进行一个查表映射的方式,将明文字节映射成S盒中的字节映射逻辑是这样的:分别取......
  • USB协议详解第18讲(USB包-初探)
    1.USB传输架构和包的组成本节我们开始对USB包进行深入讲解,USB所有的传输都会被分成包进行传输,不同类型的包里面包含着不同的域(后面一一学习)。传输架构和包的组成如下图。每个包都由SOP(包起始域)、SYNC(同步域)、PacketContent(包内容)、EOP(包结束域)四部分组成,其中SOP、SYNC、EOP为所......
  • 初探AI之got-ocr2.0大模型本地部署与遇到的各种坑处理
    一、环境搭建1.安装cuda,本人使用的是12.1版本,下载地址:https://developer.nvidia.com/cuda-12-1-1-download-archive2.安装conda3,https://blog.csdn.net/m0_73634846/article/details/1363783503.准备代码环境原文:https://mp.weixin.qq.com/s/PQVrlr5FoVb89Mivzi7pLA顺序执......
  • 生成式 AI 初探
    写了一个简单的生成式AI功能根据输入的单词生成一段话(当前训练材料不足,生成词数大约只有\(50\)左右)根据一段材料自训练原理统计累计词频,为词频计入权重统计使用次数(防止循环用词等情况)注意由于当前缺乏什么有效的训练材料,去CF粘了几篇Announcement,导致这货说话......
  • Java小白初探斗地主
    一、前言本人Java小白,一直想做一个斗地主游戏,正好最近学习到了集合。我们都知道集合分为(Collection(单列集合)家族和Map(双列/映射集合)家族)有着长度可变的特性,用来存储斗地主的卡牌再适合不过了。于是今天从下午五点多写到了晚上,主要是中间有几个地方把我卡住了很长时间。二、......
  • 初探Vue2:基础概念与实践指南
    通过记录自己在学习Vue2的过程中的实践经历,复盘项目中的技术应用,巩固Vue2的知识要点,并分享职场中的感悟和心得Vue2简介定义Vue.js,简称Vue,是一个渐进式JavaScript框架,它专注于构建用户界面,易于上手的同时,也能在复杂的应用场景中发挥强大的功能。特点Vue2的核心特点包括:响......
  • 从零开始学机器学习——初探分类器
    首先给大家介绍一个很好用的学习地址:https://cloudstudio.net/columns在上一节中,我们已经完成了对所有经过均衡和清洗的菜品数据的准备工作。接下来,我们将考虑使用多种算法,也就是不同的分类器,来构建模型。我们将利用这个数据集和各种分类器,基于一组特定的配料,预测这些菜品属于哪......