//pipelinedefine #define H_URP using System; using HTraceWSGI.Scripts.Data.Private; using HTraceWSGI.Scripts.Extensions; using HTraceWSGI.Scripts.Globals; 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 HTraceWSGI.Scripts.Passes.URP { internal class MotionVectorsPassURP : 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 MotionVectors = "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 RTHandle[] CustomCameraMotionVectorsURP = new RTHandle[2]; internal static RTHandle ObjectMotionVectorsColorURP; internal static RTHandle ObjectMotionVectorsDepthURP; // Materials private static Material MotionVectorsMaterial_URP; internal static TextureHandle DebugMotionVectorsTextureRG; internal static TextureHandle DebugMotionMaskTextureRG; #region --------------------------- Non Render Graph --------------------------- #if !UNITY_6000_4_OR_NEWER private ScriptableRenderer _renderer; 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) { //renderingData.cameraData.cameraTargetDescriptor // if (MotionVectorsMaterial_URP == null) MotionVectorsMaterial_URP = new Material(Shader.Find($"Hidden/{HNames.ASSET_NAME}/MotionVectorsURP")); // // int width = (int)(renderingData.cameraData.camera.scaledPixelWidth * renderingData.cameraData.renderScale); // int height = (int)(renderingData.cameraData.camera.scaledPixelHeight * renderingData.cameraData.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; // // ExtensionsURP.ReAllocateIfNeeded(_CustomCameraMotionVectorsURP_0, ref CustomCameraMotionVectorsURP[0], ref desc, graphicsFormat: GraphicsFormat.R16G16_SFloat); // ExtensionsURP.ReAllocateIfNeeded(_CustomCameraMotionVectorsURP_1, ref CustomCameraMotionVectorsURP[1], ref desc, graphicsFormat: GraphicsFormat.R8_SNorm); // ExtensionsURP.ReAllocateIfNeeded(_ObjectMotionVectorsColorURP, ref ObjectMotionVectorsColorURP, ref desc, graphicsFormat: GraphicsFormat.R16G16_SFloat); // ExtensionsURP.ReAllocateIfNeeded(_ObjectMotionVectorsDepthURP, ref 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); } #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 }; #if UNITY_6000_3_OR_NEWER CoreUtils.DrawRendererList(cmd, context.CreateRendererList(renderList)); #else CoreUtils.DrawRendererList(context, cmd, context.CreateRendererList(renderList)); #endif #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], CustomCameraMotionVectorsURP[1]}; CoreUtils.SetRenderTarget(cmd, motionVectorsMRT, motionVectorsMRT[0]); MotionVectorsMaterial_URP.SetTexture(ObjectMotionVectorsColor, ObjectMotionVectorsColorURP); MotionVectorsMaterial_URP.SetTexture(ObjectMotionVectorsDepth, ObjectMotionVectorsDepthURP); 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]); cmd.SetGlobalTexture(HShaderParams.g_HTraceMotionMask, CustomCameraMotionVectorsURP[1]); #endif // UNITY_2023_1_OR_NEWER } RenderObjectsMotionVectors(ref renderingData, ref context); RenderCameraMotionVectors(); } #endif #endregion --------------------------- Non Render Graph --------------------------- #region --------------------------- Render Graph --------------------------- #if UNITY_2023_3_OR_NEWER private class PassData { public RendererListHandle RendererListHandle; public TextureHandle ColorTexture; public TextureHandle DepthTexture; public TextureHandle MotionVectorsTexture; public UniversalCameraData UniversalCameraData; public TextureHandle[] CustomCameraMotionVectors = new TextureHandle[2]; public TextureHandle ObjectMotionVectorsColor; public TextureHandle ObjectMotionVectorsDepth; } public override void RecordRenderGraph(RenderGraph renderGraph, ContextContainer frameData) { DebugMotionVectorsTextureRG = default(TextureHandle); DebugMotionMaskTextureRG = default(TextureHandle); using (var builder = renderGraph.AddUnsafePass(HNames.HTRACE_MV_PASS_NAME, out var passData, new ProfilingSampler(HNames.HTRACE_MV_PASS_NAME))) { UniversalResourceData resourceData = frameData.Get(); UniversalCameraData universalCameraData = frameData.Get(); UniversalRenderingData universalRenderingData = frameData.Get(); UniversalLightData lightData = frameData.Get(); ConfigureInput(ScriptableRenderPassInput.Motion); builder.AllowGlobalStateModification(true); builder.AllowPassCulling(false); TextureHandle colorTexture = universalRenderingData.renderingMode == RenderingMode.Deferred #if UNITY_6000_1_OR_NEWER || universalRenderingData.renderingMode == RenderingMode.DeferredPlus #endif ? resourceData.activeColorTexture : resourceData.cameraColor; TextureHandle depthTexture = universalRenderingData.renderingMode == RenderingMode.Deferred #if UNITY_6000_1_OR_NEWER || universalRenderingData.renderingMode == RenderingMode.DeferredPlus #endif ? resourceData.activeDepthTexture : resourceData.cameraDepth; TextureHandle mvTexture = resourceData.motionVectorColor; builder.UseTexture(colorTexture, AccessFlags.Read); builder.UseTexture(depthTexture, AccessFlags.Read); builder.UseTexture(mvTexture, AccessFlags.Read); passData.ColorTexture = colorTexture; passData.DepthTexture = depthTexture; passData.MotionVectorsTexture = mvTexture; passData.UniversalCameraData = universalCameraData; AddRendererList(renderGraph, universalCameraData, universalRenderingData, lightData, passData, builder); if (MotionVectorsMaterial_URP == null) MotionVectorsMaterial_URP = new Material(Shader.Find($"Hidden/{HNames.ASSET_NAME}/MotionVectorsURP")); int width = (int)(universalCameraData.camera.scaledPixelWidth * universalCameraData.renderScale); int height = (int)(universalCameraData.camera.scaledPixelHeight * universalCameraData.renderScale); TextureHandle colorTextureHandle = resourceData.cameraColor; TextureDesc desc = colorTextureHandle.GetDescriptor(renderGraph); TextureHandle depthTextureHandle = resourceData.cameraDepthTexture; TextureDesc descDepth = depthTextureHandle.GetDescriptor(renderGraph); desc.clearBuffer = false; descDepth.clearBuffer = false; passData.CustomCameraMotionVectors[0] = ExtensionsURP.CreateTexture(_CustomCameraMotionVectorsURP_0, renderGraph, ref desc, format: GraphicsFormat.R16G16_SFloat); passData.CustomCameraMotionVectors[1] = ExtensionsURP.CreateTexture(_CustomCameraMotionVectorsURP_1, renderGraph, ref desc, format: GraphicsFormat.R8_SNorm); passData.ObjectMotionVectorsColor = ExtensionsURP.CreateTexture(_ObjectMotionVectorsColorURP, renderGraph, ref desc, format: GraphicsFormat.R16G16_SFloat); passData.ObjectMotionVectorsDepth = ExtensionsURP.CreateTexture(_ObjectMotionVectorsDepthURP, renderGraph, ref descDepth, GraphicsFormat.None, depthBufferBits: DepthBits.Depth32, enableRandomWrite: false); builder.UseTexture(passData.CustomCameraMotionVectors[0], AccessFlags.Write); builder.UseTexture(passData.CustomCameraMotionVectors[1], AccessFlags.Write); builder.UseTexture(passData.ObjectMotionVectorsColor, AccessFlags.Write); builder.UseTexture(passData.ObjectMotionVectorsDepth, AccessFlags.Write); DebugMotionMaskTextureRG = passData.ObjectMotionVectorsColor; DebugMotionVectorsTextureRG = universalCameraData.cameraType == CameraType.Game ? mvTexture : passData.CustomCameraMotionVectors[0]; if (universalCameraData.cameraType != CameraType.Game) DebugMotionMaskTextureRG = passData.CustomCameraMotionVectors[1]; builder.SetRenderFunc((PassData data, UnsafeGraphContext context) => ExecutePass(data, context)); } } private static void AddRendererList(RenderGraph renderGraph, UniversalCameraData universalCameraData, UniversalRenderingData universalRenderingData, UniversalLightData lightData, PassData passData, IUnsafeRenderGraphBuilder builder) { SortingCriteria sortFlags = universalCameraData.defaultOpaqueSortFlags; RenderQueueRange renderQueueRange = RenderQueueRange.opaque; FilteringSettings filterSettings = new FilteringSettings(renderQueueRange, ~0); // Redraw only objects that have their LightMode tag set to UniversalForward ShaderTagId shadersToOverride = new ShaderTagId(MotionVectors); // Create drawing settings DrawingSettings drawSettings = RenderingUtils.CreateDrawingSettings(shadersToOverride, universalRenderingData, universalCameraData, lightData, sortFlags); drawSettings.perObjectData = PerObjectData.MotionVectors; // Add the override material to the drawing settings //drawSettings.overrideMaterial = materialToUse; // Create the list of objects to draw var rendererListParameters = new RendererListParams(universalRenderingData.cullResults, drawSettings, filterSettings); // Convert the list to a list handle that the render graph system can use passData.RendererListHandle = renderGraph.CreateRendererList(rendererListParameters); // Set the render target as the color and depth textures of the active camera texture builder.UseRendererList(passData.RendererListHandle); } private static void ExecutePass(PassData data, UnsafeGraphContext rgContext) { var cmd = CommandBufferHelpers.GetNativeCommandBuffer(rgContext.cmd); Camera camera = data.UniversalCameraData.camera; RenderMotionVectorsRenderGraph(cmd, data); } private static void RenderMotionVectorsRenderGraph(CommandBuffer cmd, PassData data) { void RenderObjectMotionVectors() { // Object motion vectors can't be rendered in Scene View anyway if (data.UniversalCameraData.cameraType == CameraType.SceneView) { return; } cmd.SetRenderTarget(data.ObjectMotionVectorsColor, data.DepthTexture); cmd.ClearRenderTarget(false, true, Color.black); cmd.DrawRendererList(data.RendererListHandle); cmd.SetGlobalTexture(HShaderParams.g_HTraceMotionVectors, data.MotionVectorsTexture); cmd.SetGlobalTexture(HShaderParams.g_HTraceMotionMask, data.ObjectMotionVectorsColor); } void RenderCameraMotionVectors() { // Render Graph + Game View - no need to render camera mv, as they are already available to us in this combination if (data.UniversalCameraData.cameraType == CameraType.Game) { return; } float DepthBiasOffset = 0; // 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 = { data.CustomCameraMotionVectors[0], data.CustomCameraMotionVectors[1],}; CoreUtils.SetRenderTarget(cmd, motionVectorsMRT, motionVectorsMRT[0]); MotionVectorsMaterial_URP.SetTexture(ObjectMotionVectorsColor, data.ObjectMotionVectorsColor); MotionVectorsMaterial_URP.SetTexture(ObjectMotionVectorsDepth, data.ObjectMotionVectorsDepth); 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) cmd.SetRenderTarget(data.ColorTexture); cmd.SetGlobalTexture(HShaderParams.g_HTraceMotionVectors, data.CustomCameraMotionVectors[0]); cmd.SetGlobalTexture(HShaderParams.g_HTraceMotionMask, data.CustomCameraMotionVectors[1]); } RenderObjectMotionVectors(); RenderCameraMotionVectors(); } #endif #endregion --------------------------- Render Graph --------------------------- #region --------------------------- Share --------------------------- protected internal void Dispose() { // Not Render Graph CustomCameraMotionVectorsURP[0]?.Release(); CustomCameraMotionVectorsURP[1]?.Release(); ObjectMotionVectorsColorURP?.Release(); ObjectMotionVectorsDepthURP?.Release(); } #endregion --------------------------- Share --------------------------- } }