166 lines
7.9 KiB
C#
166 lines
7.9 KiB
C#
using System;
|
|
using UnityEngine.Rendering.RenderGraphModule;
|
|
using System.Runtime.CompilerServices; // AggressiveInlining
|
|
|
|
namespace UnityEngine.Rendering.Universal
|
|
{
|
|
internal sealed class MotionBlurPostProcessPass : PostProcessPass
|
|
{
|
|
public const string k_TargetName = "_MotionBlurTarget";
|
|
|
|
Material m_Material;
|
|
bool m_IsValid;
|
|
|
|
public MotionBlurPostProcessPass(Shader shader)
|
|
{
|
|
this.renderPassEvent = RenderPassEvent.AfterRenderingPostProcessing - 1;
|
|
this.profilingSampler = null;
|
|
|
|
m_Material = PostProcessUtils.LoadShader(shader, passName);
|
|
m_IsValid = m_Material != null;
|
|
}
|
|
|
|
public override void Dispose()
|
|
{
|
|
CoreUtils.Destroy(m_Material);
|
|
m_IsValid = false;
|
|
}
|
|
|
|
private class MotionBlurPassData
|
|
{
|
|
internal TextureHandle sourceTexture;
|
|
internal Material material;
|
|
internal int passIndex;
|
|
internal Camera camera;
|
|
internal Experimental.Rendering.XRPass xr;
|
|
internal float intensity;
|
|
internal float clamp;
|
|
internal bool enableAlphaOutput;
|
|
}
|
|
public override void RecordRenderGraph(RenderGraph renderGraph, ContextContainer frameData)
|
|
{
|
|
if(!m_IsValid)
|
|
return;
|
|
|
|
var motionBlur = volumeStack.GetComponent<MotionBlur>();
|
|
|
|
UniversalCameraData cameraData = frameData.Get<UniversalCameraData>();
|
|
UniversalResourceData resourceData = frameData.Get<UniversalResourceData>();
|
|
|
|
var sourceTexture = resourceData.cameraColor;
|
|
var destinationTexture = PostProcessUtils.CreateCompatibleTexture(renderGraph, sourceTexture, k_TargetName, true, FilterMode.Bilinear);
|
|
|
|
TextureHandle motionVectorColor = resourceData.motionVectorColor;
|
|
TextureHandle cameraDepthTexture = resourceData.cameraDepthTexture;
|
|
|
|
var mode = motionBlur.mode.value;
|
|
int passIndex = (int)motionBlur.quality.value;
|
|
passIndex += (mode == MotionBlurMode.CameraAndObjects) ? ShaderPass.k_CameraAndObjectMotionBlurLow : ShaderPass.k_CameraMotionBlurLow;
|
|
|
|
using (var builder = renderGraph.AddRasterRenderPass<MotionBlurPassData>("Motion Blur", out var passData, ProfilingSampler.Get(URPProfileId.RG_MotionBlur)))
|
|
{
|
|
builder.SetRenderAttachment(destinationTexture, 0, AccessFlags.Write);
|
|
passData.sourceTexture = sourceTexture;
|
|
builder.UseTexture(sourceTexture, AccessFlags.Read);
|
|
|
|
if (mode == MotionBlurMode.CameraAndObjects)
|
|
{
|
|
Debug.Assert(ScriptableRenderer.current.SupportsMotionVectors(), "Current renderer does not support motion vectors.");
|
|
Debug.Assert(motionVectorColor.IsValid(), "Motion vectors are invalid. Per-object motion blur requires a motion vector texture.");
|
|
|
|
builder.UseTexture(motionVectorColor, AccessFlags.Read);
|
|
}
|
|
|
|
Debug.Assert(cameraDepthTexture.IsValid(), "Camera depth texture is invalid. Per-camera motion blur requires a depth texture.");
|
|
builder.UseTexture(cameraDepthTexture, AccessFlags.Read);
|
|
passData.material = m_Material;
|
|
passData.passIndex = passIndex;
|
|
passData.camera = cameraData.camera;
|
|
passData.xr = cameraData.xr;
|
|
passData.enableAlphaOutput = cameraData.isAlphaOutputEnabled;
|
|
passData.intensity = motionBlur.intensity.value;
|
|
passData.clamp = motionBlur.clamp.value;
|
|
builder.SetRenderFunc(static (MotionBlurPassData data, RasterGraphContext context) =>
|
|
{
|
|
var cmd = context.cmd;
|
|
RTHandle sourceTextureHdl = data.sourceTexture;
|
|
|
|
UpdateMotionBlurMatrices(data.material, data.camera, data.xr);
|
|
|
|
var sourceSize = PostProcessUtils.CalcShaderSourceSize(sourceTextureHdl);
|
|
data.material.SetVector(ShaderConstants._SourceSize, sourceSize);
|
|
data.material.SetFloat(ShaderConstants._Intensity, data.intensity);
|
|
data.material.SetFloat(ShaderConstants._Clamp, data.clamp);
|
|
CoreUtils.SetKeyword(data.material, ShaderKeywordStrings._ENABLE_ALPHA_OUTPUT, data.enableAlphaOutput);
|
|
|
|
Vector2 viewportScale = sourceTextureHdl.useScaling ? new Vector2(sourceTextureHdl.rtHandleProperties.rtHandleScale.x, sourceTextureHdl.rtHandleProperties.rtHandleScale.y) : Vector2.one;
|
|
Blitter.BlitTexture(cmd, sourceTextureHdl, viewportScale, data.material, data.passIndex);
|
|
});
|
|
}
|
|
|
|
resourceData.cameraColor = destinationTexture;
|
|
}
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
public static void UpdateMotionBlurMatrices(Material material, Camera camera, Experimental.Rendering.XRPass xr)
|
|
{
|
|
MotionVectorsPersistentData motionData = null;
|
|
|
|
if(camera.TryGetComponent<UniversalAdditionalCameraData>(out var additionalCameraData))
|
|
motionData = additionalCameraData.motionVectorsPersistentData;
|
|
|
|
if (motionData == null)
|
|
return;
|
|
|
|
#if ENABLE_VR && ENABLE_XR_MODULE
|
|
if (xr.enabled && xr.singlePassEnabled)
|
|
{
|
|
// pass maximum of 2 matrices per pass. Need to access into the matrix array
|
|
var viewStartIndex = xr.viewCount * xr.multipassId;
|
|
// Using motionData.stagingMatrixStereo as staging buffer to avoid allocation
|
|
Array.Copy(motionData.previousViewProjectionStereo, viewStartIndex, motionData.stagingMatrixStereo, 0, xr.viewCount);
|
|
material.SetMatrixArray(ShaderConstants._PrevViewProjMStereo, motionData.stagingMatrixStereo);
|
|
Array.Copy(motionData.viewProjectionStereo, viewStartIndex, motionData.stagingMatrixStereo, 0, xr.viewCount);
|
|
material.SetMatrixArray(ShaderConstants._ViewProjMStereo, motionData.stagingMatrixStereo);
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
int viewProjMIdx = 0;
|
|
#if ENABLE_VR && ENABLE_XR_MODULE
|
|
if (xr.enabled)
|
|
viewProjMIdx = xr.multipassId * xr.viewCount;
|
|
#endif
|
|
|
|
// TODO: These should be part of URP main matrix set. For now, we set them here for motion vector rendering.
|
|
material.SetMatrix(ShaderConstants._PrevViewProjM, motionData.previousViewProjectionStereo[viewProjMIdx]);
|
|
material.SetMatrix(ShaderConstants._ViewProjM, motionData.viewProjectionStereo[viewProjMIdx]);
|
|
}
|
|
}
|
|
|
|
|
|
// Precomputed shader ids to same some CPU cycles (mostly affects mobile)
|
|
public static class ShaderConstants
|
|
{
|
|
public static readonly int _ViewProjM = Shader.PropertyToID("_ViewProjM");
|
|
public static readonly int _PrevViewProjM = Shader.PropertyToID("_PrevViewProjM");
|
|
public static readonly int _ViewProjMStereo = Shader.PropertyToID("_ViewProjMStereo");
|
|
public static readonly int _PrevViewProjMStereo = Shader.PropertyToID("_PrevViewProjMStereo");
|
|
|
|
public static readonly int _Intensity = Shader.PropertyToID("_Intensity");
|
|
public static readonly int _Clamp = Shader.PropertyToID("_Clamp");
|
|
public static readonly int _SourceSize = Shader.PropertyToID("_SourceSize");
|
|
}
|
|
|
|
public static class ShaderPass
|
|
{
|
|
public const int k_CameraMotionBlurLow = 0;
|
|
public const int k_CameraMotionBlurMedium = 1;
|
|
public const int k_CameraMotionBlurHigh = 2;
|
|
public const int k_CameraAndObjectMotionBlurLow = 3;
|
|
public const int k_CameraAndObjectMotionBlurMedium = 4;
|
|
public const int k_CameraAndObjectMotionBlurHigh = 5;
|
|
}
|
|
}
|
|
}
|