402 lines
18 KiB
C#

//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<PassData>(HNames.HTRACE_MV_PASS_NAME, out var passData, new ProfilingSampler(HNames.HTRACE_MV_PASS_NAME)))
{
UniversalResourceData resourceData = frameData.Get<UniversalResourceData>();
UniversalCameraData universalCameraData = frameData.Get<UniversalCameraData>();
UniversalRenderingData universalRenderingData = frameData.Get<UniversalRenderingData>();
UniversalLightData lightData = frameData.Get<UniversalLightData>();
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 ---------------------------
}
}