多帧渲染和累积
一些渲染技术(例如路径追踪和累积运动模糊)将来自多个中间子帧的信息组合起来,从而创建最终的“融合”帧。每个中间子帧可对应一个稍微不同的时间点,从而有效计算基于物理的累积运动模糊,这种模糊会正确考虑对象的旋转、变形、材质或光照变化。
高清渲染管线 (High Definition Render Pipeline, HDRP) 提供了脚本 API,可用于控制子帧的创建以及多帧渲染效果的融合。尤其是,此 API 可以控制中间子帧(样本)的数量以及与每个子帧对应的时间点。此外,可以使用快门配置模式来控制每个子帧的权重。快门配置模式描述物理摄像机打开和关闭快门的速度。
此 API 尤其适合用于录制路径追踪电影。通常,编辑场景时,每次场景变化都会重新启动路径追踪融合,从而为美术师提供交互式编辑工作流程,使他们可以快速直观地查看自己进行的更改。但是,在录制期间,并不希望进行此类行为。
下图显示了使用多帧录制 API 来录制的具有路径追踪和累积运动模糊效果的旋转游戏对象。
API 概述
录制 API 在 HDRP 中可用,并具有以下三种调用:
- BeginRecording:需要开始多帧渲染时进行此调用。
- PrepareNewSubFrame:在渲染新子帧之前进行此调用。
- EndRecording:需要停止多帧渲染时进行此调用。
唯一接受参数的调用是 BeginRecording。以下是这些参数的说明:
参数 | 描述 |
---|---|
Samples | 要累积的子帧的数量。此参数将覆盖体积中的路径追踪样本数。 |
ShutterInterval | 两个后续帧之间快门打开的时间长度。值为 0 会产生即时快门(无运动模糊)。值为 1 表示两个后续帧之间没有(时间)间隔。 |
ShutterProfile | 一种动画曲线,可指定快门间隔期间的快门位置。此外,还可以提供快门完全打开的时间;并指明快门何时开始关闭。 |
以下示例脚本演示了如何使用这些 API 调用。
脚本 API 示例
以下示例演示了如何在脚本中使用多帧渲染 API 来正确录制具有路径追踪和/或累积运动模糊的聚合动画序列。要使用此 API,请将脚本附加到场景中的摄像机,然后在组件的上下文菜单中单击“Start Recording”和“Stop Recording”操作。
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.HighDefinition;
public class FrameManager : MonoBehaviour
{
// 用于累积的样本数。
public int samples = 128;
[Range(0.0f, 1.0f)]
public float shutterInterval = 1.0f;
// 快门间隔时间内快门完全打开时的时间。
[Range(0.0f, 1.0f)]
public float shutterFullyOpen = 0.25f;
// 快门间隔时间内快门开始关闭时的时间。
[Range(0.0f, 1.0f)]
public float shutterBeginsClosing = 0.75f;
bool m_Recording = false;
int m_Iteration = 0;
int m_RecordedFrames = 0;
[ContextMenu("Start Recording")]
void BeginMultiframeRendering()
{
RenderPipelineManager.beginFrameRendering += PrepareSubFrameCallBack;
HDRenderPipeline renderPipeline = RenderPipelineManager.currentPipeline as HDRenderPipeline;
renderPipeline.BeginRecording(samples, shutterInterval, shutterFullyOpen, shutterBeginsClosing);
m_Recording = true;
m_Iteration = 0;
m_RecordedFrames = 0;
}
[ContextMenu("Stop Recording")]
void StopMultiframeRendering()
{
RenderPipelineManager.beginFrameRendering -= PrepareSubFrameCallBack;
HDRenderPipeline renderPipeline = RenderPipelineManager.currentPipeline as HDRenderPipeline;
renderPipeline?.EndRecording();
m_Recording = false;
}
void PrepareSubFrameCallBack(ScriptableRenderContext cntx, Camera[] cams)
{
HDRenderPipeline renderPipeline = RenderPipelineManager.currentPipeline as HDRenderPipeline;
if (renderPipeline != null && m_Recording)
{
renderPipeline.PrepareNewSubFrame();
m_Iteration++;
}
if (m_Recording && m_Iteration % samples == 0)
{
ScreenCapture.CaptureScreenshot($"frame_{m_RecordedFrames++}.png");
}
}
void OnDestroy()
{
if (m_Recording)
{
StopMultiframeRendering();
}
}
void OnValidate()
{
// 确保快门在完全打开之后(而不是在此之前)的某个时间开始关闭
shutterBeginsClosing = Mathf.Max(shutterFullyOpen, shutterBeginsClosing);
}
}
快门配置模式
BeginRecording 调用可指定摄像机快门的打开和关闭速度。摄像机快门的速度定义了所谓的“快门配置模式”。下图演示了不同的快门配置模式如何影响从左向右移动的蓝色球体上的运动模糊效果。
在所有情况下,球体速度均相同。唯一的变化是快门配置模式。配置模式图的横轴对应于时间,纵轴对应于快门的打开。
将打开和关闭参数分别设置为 (0,1)、(1,1) 和 (0.25, 0.75),即可在不使用动画曲线的情况下轻松定义前三个配置模式。最后一个配置模式需要使用动画曲线。
在此示例中,可以看到缓慢打开的配置模式可以为运动模糊创建运动轨迹外观,这可能是美术师更想要的效果。另一方面,与缓慢打开或均匀的配置模式相比,平滑打开和关闭的配置模式可创建更平滑的动画。
限制
多帧渲染 API 会在内部更改场景的 Time.timeScale
。这意味着:
- 每个摄像机不能具有不同的累积运动模糊参数。
- 已在每帧修改此参数的项目不兼容此功能。