URP图形入门:Pass绘制指定Object

      自从deepseek开年爆火,我几乎95%时间都是靠它学习和实现盲点功能。博客也不想写了,因为被deepseek降维打击的感觉犹如我在田里面朝黄土背朝天一根一根插秧,突然旁边开来一辆自动插秧机~
      PS:虽然之前一直挂vpn用免费的gpt3.5,但是gpt3.5只能说just so so。我以为AI就那样了,看来还是我自己level low了几个级别。
      言归正传,这段时间基于urp14把开发框架整了一个分支(以前整过一份hdrp分支,因为我工作大部分是pc端),但是今年部门转型ar类项目,运行设备基于pico quest ipad hwpad等设备,所以上urp14了。记一下scriptablerenderpass实现指定object的postprocess渲染(当然也可以用renderobject)
      1.使用CommandBuffer.DrawRenderer

using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;

public class RendererOutputRenderPass : ScriptableRenderPass
{
    private ProfilingSampler profileSampler = new ProfilingSampler("RendererOutput");
    private RTHandle outputHandle;
    private List<Renderer> renderList = new();

    public RendererOutputRenderPass(RenderPassEvent evt)
    {
        renderPassEvent = evt;
    }

    public void SetRenderList(List<Renderer> rdlist)
    {
        renderList = rdlist;
    }
    /// <summary>
    /// outputHandle采样完成后就可以提供给其他pass使用
    /// </summary>
    /// <param name="dest"></param>
    public void SetOutput(ref RTHandle dest)
    {
        outputHandle = dest;
    }

    public override void Configure(CommandBuffer cmd, RenderTextureDescriptor cameraTextureDescripor)
    {
        ConfigureTarget(outputHandle);
    }
    public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
    {
        var cameraData = renderingData.cameraData;
        if (cameraData.camera.cameraType != CameraType.Game)
            return;

        if (renderList == null)
            return;

        //urp中commandBuffer和buildin中差不多用法
        CommandBuffer cmd = CommandBufferPool.Get();
        using (new ProfilingScope(cmd, profileSampler))
        {
            renderList.ForEach(rd =>
            {
                cmd.DrawRenderer(rd, rd.sharedMaterial, 0, 0);
            });
        }
        context.ExecuteCommandBuffer(cmd);
        cmd.Clear();
        CommandBufferPool.Release(cmd);
    }
}

using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;

public class RendererOutputRenderFeature : ScriptableRendererFeature
{
    public RenderPassEvent passEvent = RenderPassEvent.AfterRenderingSkybox;

    private RendererOutputRenderPass renderPass;

    private RTHandle outputHandle;

    public override void Create()
    {
        renderPass = new RendererOutputRenderPass(passEvent);
    }

    public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData)
    {
        if (renderingData.cameraData.cameraType != CameraType.Game)
            return;

        renderer.EnqueuePass(renderPass);
    }

    public override void SetupRenderPasses(ScriptableRenderer renderer, in RenderingData renderingData)
    {
        if (renderingData.cameraData.cameraType != CameraType.Game)
            return;

        var desc = renderingData.cameraData.cameraTargetDescriptor;
        desc.depthBufferBits = 0;
        desc.msaaSamples = 1;
        RenderingUtils.ReAllocateIfNeeded(ref outputHandle, desc, FilterMode.Bilinear, TextureWrapMode.Clamp);

        renderPass.SetOutput(ref outputHandle);

        //测试
        List<Renderer> rdList = new();
        rdList.Add(GameObject.Find("Cube").GetComponent<Renderer>());
        rdList.Add(GameObject.Find("Sphere").GetComponent<Renderer>());
        renderPass.SetRenderList(rdList);
    }

    protected override void Dispose(bool disposing)
    {
        renderPass = null;
        outputHandle?.Release();
    }
}

      效果如下:
在这里插入图片描述

      RendererOutputPass输出了Cube和Sphere的采样结果。

      2.使用FilteringSettings/DrawingSettings

using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;

public class LayerOutputRenderPass : ScriptableRenderPass
{
    private FilteringSettings filterSetting;
    private List<ShaderTagId> shaderTagIdList = new();
    private ProfilingSampler profileSampler = new ProfilingSampler("LayerOutput");
    private RTHandle outputHandle;

    public LayerOutputRenderPass(RenderPassEvent evt)
    {
        renderPassEvent = evt;
        renderPassEvent = RenderPassEvent.BeforeRenderingPostProcessing;
        shaderTagIdList = new List<ShaderTagId>
        {
            new ShaderTagId("UniversalForward"),
            new ShaderTagId("UniversalForwardOnly"),
            new ShaderTagId("LightweightForward"),
            new ShaderTagId("SRPDefaultUnlit")
        };
    }

    public void SetLayer(LayerMask layer)
    {
        filterSetting = new FilteringSettings(RenderQueueRange.opaque, layer);
    }

    public void SetOutput(ref RTHandle dest)
    {
        outputHandle = dest;
    }

    public override void OnCameraSetup(CommandBuffer cmd, ref RenderingData renderingData)
    {
        ConfigureTarget(outputHandle);
    }

    public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
    {
        if (renderingData.cameraData.camera.cameraType != CameraType.Game)
            return;

        CommandBuffer cmd = CommandBufferPool.Get();
        DrawingSettings drawSetting = CreateDrawingSettings(shaderTagIdList, ref renderingData, renderingData.cameraData.defaultOpaqueSortFlags);
        using (new ProfilingScope(cmd, profileSampler))
        {
            context.DrawRenderers(renderingData.cullResults, ref drawSetting, ref filterSetting);
        }
        context.ExecuteCommandBuffer(cmd);
        cmd.Clear();

        CommandBufferPool.Release(cmd);
    }
}

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

public class LayerOutputRenderFeature : ScriptableRendererFeature
{
    public RenderPassEvent passEvent = RenderPassEvent.AfterRenderingSkybox;

    public LayerMask renderLayer;

    private LayerOutputRenderPass renderPass;

    private RTHandle outputHandle;

    public override void Create()
    {
        renderPass = new LayerOutputRenderPass(passEvent);
    }

    public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData)
    {
        if (renderingData.cameraData.cameraType != CameraType.Game)
            return;

        renderer.EnqueuePass(renderPass);
    }

    public override void SetupRenderPasses(ScriptableRenderer renderer, in RenderingData renderingData)
    {
        if (renderingData.cameraData.cameraType != CameraType.Game)
            return;

        var desc = renderingData.cameraData.cameraTargetDescriptor;
        desc.depthBufferBits = 0;
        desc.msaaSamples = 1;
        RenderingUtils.ReAllocateIfNeeded(ref outputHandle, desc, FilterMode.Bilinear, TextureWrapMode.Clamp);

        renderPass.SetOutput(ref outputHandle);
        renderPass.SetLayer(renderLayer);
    }

    protected override void Dispose(bool disposing)
    {
        renderPass = null;
        outputHandle?.Release();
    }
}

      效果如下:
在这里插入图片描述
      LayerOutputRenderPass输出了Cube1和Sphere1的采样结果。
      这两种Object采样方式是实现很多postprocess效果的基础。
      好,就到这里,下一次写博客不知道几何~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值