Files
project-reset/Assets/Plugins/HTraceSSGI/Scripts/Passes/URP/MotionVectorsURP.cs
2025-12-31 12:44:11 -05:00

346 lines
15 KiB
C#

//pipelinedefine
#define H_URP
using System;
using HTraceSSGI.Scripts.Data.Private;
using HTraceSSGI.Scripts.Extensions;
using HTraceSSGI.Scripts.Globals;
using HTraceSSGI.Scripts.Wrappers;
using UnityEngine;
using UnityEngine.Experimental.Rendering;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;
#if UNITY_2023_3_OR_NEWER
using UnityEngine.Rendering.RenderGraphModule;
#else
using UnityEngine.Experimental.Rendering.RenderGraphModule;
#endif
namespace HTraceSSGI.Scripts.Passes.URP
{
internal class MotionVectorsURP : ScriptableRenderPass
{
// Texture Names
const string _ObjectMotionVectorsColorURP = "_ObjectMotionVectorsColorURP";
const string _ObjectMotionVectorsDepthURP = "_ObjectMotionVectorsDepthURP";
const string _CustomCameraMotionVectorsURP_0 = "_CustomCameraMotionVectorsURP_0";
const string _CustomCameraMotionVectorsURP_1 = "_CustomCameraMotionVectorsURP_1";
const string _MotionVectorsTagID = "MotionVectors";
// Shader Properties
private static readonly int _ObjectMotionVectorsColor = Shader.PropertyToID("_ObjectMotionVectors");
private static readonly int _ObjectMotionVectorsDepth = Shader.PropertyToID("_ObjectMotionVectorsDepth");
private static readonly int _BiasOffset = Shader.PropertyToID("_BiasOffset");
// Textures
internal static RTWrapper[] CustomCameraMotionVectorsURP = new RTWrapper[2] {new RTWrapper(), new RTWrapper()};
internal static RTWrapper ObjectMotionVectorsColorURP = new RTWrapper();
internal static RTWrapper ObjectMotionVectorsDepthURP = new RTWrapper();
// Materials
private static Material MotionVectorsMaterial_URP;
private static ProfilingSampler ObjectMVProfilingSampler = new ProfilingSampler(HNames.HTRACE_OBJECTS_MV_PASS_NAME);
private static ProfilingSampler MVProfilingSampler = new ProfilingSampler(HNames.HTRACE_CAMERA_MV_PASS_NAME);
#region --------------------------- Non Render Graph ---------------------------
private ScriptableRenderer _renderer;
private static int _historyCameraIndex;
protected internal void Initialize(ScriptableRenderer renderer)
{
_renderer = renderer;
}
#if UNITY_2023_3_OR_NEWER
[System.Obsolete]
#endif
public override void OnCameraSetup(CommandBuffer cmd, ref RenderingData renderingData)
{
Setup(renderingData.cameraData.camera, renderingData.cameraData.renderScale, renderingData.cameraData.cameraTargetDescriptor);
}
private static void Setup(Camera camera, float renderScale, RenderTextureDescriptor desc)
{
if (MotionVectorsMaterial_URP == null) MotionVectorsMaterial_URP = new Material(Shader.Find($"Hidden/{HNames.ASSET_NAME}/MotionVectorsURP"));
int width = (int)(camera.scaledPixelWidth * renderScale);
int height = (int)(camera.scaledPixelHeight * renderScale);
if (desc.width != width || desc.height != height)
desc = new RenderTextureDescriptor(width, height);
desc.depthBufferBits = 0; // Color and depth cannot be combined in RTHandles
desc.stencilFormat = GraphicsFormat.None;
desc.depthStencilFormat = GraphicsFormat.None;
desc.msaaSamples = 1;
desc.bindMS = false;
desc.enableRandomWrite = true;
RenderTextureDescriptor depthDesc = desc;
depthDesc.depthBufferBits = 32;
depthDesc.enableRandomWrite = false;
depthDesc.colorFormat = RenderTextureFormat.Depth;
CustomCameraMotionVectorsURP[0].ReAllocateIfNeeded(_CustomCameraMotionVectorsURP_0, ref desc, graphicsFormat: GraphicsFormat.R16G16_SFloat);
CustomCameraMotionVectorsURP[1].ReAllocateIfNeeded(_CustomCameraMotionVectorsURP_1, ref desc, graphicsFormat: GraphicsFormat.R8_SNorm);
ObjectMotionVectorsColorURP.ReAllocateIfNeeded(_ObjectMotionVectorsColorURP, ref desc, graphicsFormat: GraphicsFormat.R16G16_SFloat);
ObjectMotionVectorsDepthURP.ReAllocateIfNeeded(_ObjectMotionVectorsDepthURP, ref depthDesc, enableRandomWrite: false);
}
#if UNITY_2023_3_OR_NEWER
[System.Obsolete]
#endif
public override void Configure(CommandBuffer cmd, RenderTextureDescriptor cameraTextureDescriptor)
{
ConfigureInput(ScriptableRenderPassInput.Motion | ScriptableRenderPassInput.Depth);
}
#if UNITY_2023_3_OR_NEWER
[System.Obsolete]
#endif
public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
{
var cmd = CommandBufferPool.Get(HNames.HTRACE_MV_PASS_NAME);
Camera camera = renderingData.cameraData.camera;
RenderMotionVectorsNonRenderGraph(cmd, camera, ref renderingData, ref context);
context.ExecuteCommandBuffer(cmd);
cmd.Clear();
CommandBufferPool.Release(cmd);
}
private void RenderMotionVectorsNonRenderGraph(CommandBuffer cmd, Camera camera, ref RenderingData renderingData, ref ScriptableRenderContext context)
{
void RenderObjectsMotionVectors(ref RenderingData renderingData, ref ScriptableRenderContext context)
{
#if UNITY_2023_3_OR_NEWER
if (camera.cameraType == CameraType.SceneView)
return;
#endif
CoreUtils.SetRenderTarget(cmd, ObjectMotionVectorsColorURP.rt, ClearFlag.All, Color.clear);
CoreUtils.SetRenderTarget(cmd, ObjectMotionVectorsDepthURP.rt, ClearFlag.All, Color.clear);
#if UNITY_2023_1_OR_NEWER
// We'll write not only to our own Color, but also to our own Depth target to use it later (in Camera MV) to compose per-object mv
CoreUtils.SetRenderTarget(cmd, ObjectMotionVectorsColorURP.rt, ObjectMotionVectorsDepthURP.rt);
#else
// Prior to 2023 camera motion vectors are rendered directly on objects, so we write to both motion mask and motion vectors via MRT
RenderTargetIdentifier[] motionVectorsMRT = { CustomCameraMotionVectorsURP[0].rt, CustomCameraMotionVectorsURP[1].rt,};
CoreUtils.SetRenderTarget(cmd, motionVectorsMRT, ObjectMotionVectorsDepthURP.rt);
#endif // UNITY_2023_1_OR_NEWER
CullingResults cullingResults = renderingData.cullResults;
ShaderTagId[] tags
#if UNITY_2023_1_OR_NEWER
= {new ShaderTagId("MotionVectors")};
#else
= {new ShaderTagId("Meta")};
#endif // UNITY_2023_1_OR_NEWER
var renderList = new UnityEngine.Rendering.RendererUtils.RendererListDesc(tags, cullingResults, camera)
{
rendererConfiguration = PerObjectData.MotionVectors,
renderQueueRange = RenderQueueRange.opaque,
sortingCriteria = SortingCriteria.CommonOpaque,
layerMask = camera.cullingMask,
overrideMaterial
#if UNITY_2023_1_OR_NEWER
= null,
#else
= MotionVectorsMaterial_URP,
overrideMaterialPassIndex = 1,
// If somethingis wrong with our custom shader we can always use the standard one (and ShaderPass = 0) instead
// Material ObjectMotionVectorsMaterial = new Material(Shader.Find("Hidden/Universal Render Pipeline/ObjectMotionVectors"));
// overrideMaterialPassIndex = 0,
#endif //UNITY_2023_1_OR_NEWER
};
CoreUtils.DrawRendererList(context, cmd, context.CreateRendererList(renderList));
#if !UNITY_2023_1_OR_NEWER
// Prior to 2023 camera motion vectors are rendered directly on objects, so we will finish mv calculation here and won't execute camera mv
cmd.SetGlobalTexture(HShaderParams.g_HTraceMotionVectors, CustomCameraMotionVectorsURP[0].rt);
cmd.SetGlobalTexture(HShaderParams.g_HTraceMotionMask, CustomCameraMotionVectorsURP[1].rt);
#endif // UNITY_2023_1_OR_NEWER
}
void RenderCameraMotionVectors()
{
#if UNITY_2023_1_OR_NEWER
float DepthBiasOffset = 0;
#if UNITY_2023_1_OR_NEWER
DepthBiasOffset = 0.00099f;
#endif // UNITY_2023_1_OR_NEWER
#if UNITY_6000_0_OR_NEWER
DepthBiasOffset = 0;
#endif // UNITY_6000_0_OR_NEWER
// Target target[0] is set as a Depth Buffer, just because this method requires Depth, but we don't care for it in the fullscreen pass
RenderTargetIdentifier[] motionVectorsMRT = { CustomCameraMotionVectorsURP[0].rt, CustomCameraMotionVectorsURP[1].rt};
CoreUtils.SetRenderTarget(cmd, motionVectorsMRT, motionVectorsMRT[0]);
MotionVectorsMaterial_URP.SetTexture(_ObjectMotionVectorsColor, ObjectMotionVectorsColorURP.rt);
MotionVectorsMaterial_URP.SetTexture(_ObjectMotionVectorsDepth, ObjectMotionVectorsDepthURP.rt);
MotionVectorsMaterial_URP.SetFloat(_BiasOffset, DepthBiasOffset);
cmd.DrawProcedural(Matrix4x4.identity, MotionVectorsMaterial_URP, 0, MeshTopology.Triangles, 3, 1);
// This restores color camera color target (.SetRenderTarget can be used for Forward + any Depth Priming, but doesn't work in Deferred)
#pragma warning disable CS0618
ConfigureTarget(_renderer.cameraColorTargetHandle);
#pragma warning restore CS0618
cmd.SetGlobalTexture(HShaderParams.g_HTraceMotionVectors, CustomCameraMotionVectorsURP[0].rt);
cmd.SetGlobalTexture(HShaderParams.g_HTraceMotionMask, CustomCameraMotionVectorsURP[1].rt);
#endif // UNITY_2023_1_OR_NEWER
}
RenderObjectsMotionVectors(ref renderingData, ref context);
RenderCameraMotionVectors();
}
#endregion --------------------------- Non Render Graph ---------------------------
#region --------------------------- Render Graph ---------------------------
#if UNITY_2023_3_OR_NEWER
private class ObjectMVPassData
{
public RendererListHandle RendererListHandle;
}
private class CameraMVPassData
{
public TextureHandle ObjectMotionVectorsColor;
public TextureHandle ObjectMotionVectorsDepth;
}
public override void RecordRenderGraph(RenderGraph renderGraph, ContextContainer frameData)
{
UniversalCameraData universalCameraData = frameData.Get<UniversalCameraData>();
ConfigureInput(ScriptableRenderPassInput.Motion | ScriptableRenderPassInput.Depth);
using (IRasterRenderGraphBuilder builder = renderGraph.AddRasterRenderPass<ObjectMVPassData>(HNames.HTRACE_OBJECTS_MV_PASS_NAME, out var passData, ObjectMVProfilingSampler))
{
UniversalResourceData resourceData = frameData.Get<UniversalResourceData>();
UniversalRenderingData universalRenderingData = frameData.Get<UniversalRenderingData>();
builder.AllowGlobalStateModification(true);
builder.AllowPassCulling(false);
TextureHandle depthTexture = resourceData.activeDepthTexture;
TextureHandle motionVectorsTexture = resourceData.motionVectorColor;
if (motionVectorsTexture.IsValid())
builder.UseTexture(motionVectorsTexture, AccessFlags.Read);
AddRendererList(renderGraph, universalCameraData, universalRenderingData, passData, builder);
// This was previously colorTexture.GetDescriptor(renderGraph);
TextureDesc descDepth = depthTexture.GetDescriptor(renderGraph);
descDepth.colorFormat = GraphicsFormat.R16G16_SFloat;
descDepth.name = _ObjectMotionVectorsColorURP;
TextureHandle objectMotionVectorsColorTexHandle = renderGraph.CreateTexture(descDepth);
builder.SetRenderAttachment(objectMotionVectorsColorTexHandle, 0);
builder.SetRenderAttachmentDepth(depthTexture, AccessFlags.ReadWrite);
//if (motionVectorsTexture.IsValid()) //seems to work fine without this
builder.SetGlobalTextureAfterPass(motionVectorsTexture, HShaderParams.g_HTraceMotionVectors);
builder.SetGlobalTextureAfterPass(objectMotionVectorsColorTexHandle, HShaderParams.g_HTraceMotionMask);
builder.SetRenderFunc((ObjectMVPassData data, RasterGraphContext context) =>
{
RasterCommandBuffer cmd = context.cmd;
cmd.ClearRenderTarget(false, true, Color.black);
cmd.DrawRendererList(data.RendererListHandle);
});
}
// Render Graph + Game View - no need to render camera mv, as they are already available to us in this combination
if (universalCameraData.cameraType == CameraType.Game)
return;
using (IRasterRenderGraphBuilder builder = renderGraph.AddRasterRenderPass<CameraMVPassData>(HNames.HTRACE_CAMERA_MV_PASS_NAME, out var passData, MVProfilingSampler))
{
UniversalResourceData resourceData = frameData.Get<UniversalResourceData>();
builder.AllowGlobalStateModification(true);
builder.AllowPassCulling(false);
TextureHandle colorTexture = resourceData.activeColorTexture;
if (MotionVectorsMaterial_URP == null) MotionVectorsMaterial_URP = new Material(Shader.Find($"Hidden/{HNames.ASSET_NAME}/MotionVectorsURP"));
TextureDesc desc = colorTexture.GetDescriptor(renderGraph);
desc.colorFormat = GraphicsFormat.R16G16_SFloat;
desc.name = _CustomCameraMotionVectorsURP_0;
TextureHandle cameraMotionVectorsColorTexHandle = renderGraph.CreateTexture(desc);
builder.SetRenderAttachment(cameraMotionVectorsColorTexHandle, 0);
builder.SetGlobalTextureAfterPass(cameraMotionVectorsColorTexHandle, HShaderParams.g_HTraceMotionVectors);
builder.SetRenderFunc((CameraMVPassData data, RasterGraphContext context) =>
{
RasterCommandBuffer cmd = context.cmd;
MotionVectorsMaterial_URP.SetTexture(_ObjectMotionVectorsColor, context.defaultResources.blackTexture);
MotionVectorsMaterial_URP.SetTexture(_ObjectMotionVectorsDepth, context.defaultResources.whiteTexture);
MotionVectorsMaterial_URP.SetFloat(_BiasOffset, 0);
cmd.DrawProcedural(Matrix4x4.identity, MotionVectorsMaterial_URP, 0, MeshTopology.Triangles, 3, 1);
});
}
}
private static void AddRendererList(RenderGraph renderGraph, UniversalCameraData universalCameraData, UniversalRenderingData universalRenderingData, ObjectMVPassData objectMvPassData, IRasterRenderGraphBuilder builder)
{
RenderStateBlock ForwardGBufferRenderStateBlock = new RenderStateBlock(RenderStateMask.Nothing);
ForwardGBufferRenderStateBlock.depthState = new DepthState(false, CompareFunction.LessEqual); // Probably CompareFunction.Less ?
ForwardGBufferRenderStateBlock.mask |= RenderStateMask.Depth;
ShaderTagId motionVectorsShaderTag = new ShaderTagId(_MotionVectorsTagID);
var renderList = new UnityEngine.Rendering.RendererUtils.RendererListDesc(motionVectorsShaderTag, universalRenderingData.cullResults, universalCameraData.camera)
{
rendererConfiguration = PerObjectData.MotionVectors,
renderQueueRange = RenderQueueRange.opaque,
sortingCriteria = SortingCriteria.CommonOpaque,
stateBlock = ForwardGBufferRenderStateBlock,
};
objectMvPassData.RendererListHandle = renderGraph.CreateRendererList(renderList);
builder.UseRendererList(objectMvPassData.RendererListHandle);
}
#endif
#endregion --------------------------- Render Graph ---------------------------
#region --------------------------- Share ---------------------------
protected internal void Dispose()
{
CustomCameraMotionVectorsURP[0]?.HRelease();
CustomCameraMotionVectorsURP[1]?.HRelease();
ObjectMotionVectorsColorURP?.HRelease();
ObjectMotionVectorsDepthURP?.HRelease();
}
#endregion --------------------------- Share ---------------------------
}
}