自从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效果的基础。
好,就到这里,下一次写博客不知道几何~