基于recorder实现在URP中捕获序列帧

为什么需要使用录制序列帧?

常规的影视流程要求美术在DCC中进行建模材质K动画渲染等操作。而渲染出来的PV由于工作流不同会和实时引擎中的效果产生巨大的差异。这个可以通过做在引擎和DCC双端做LOOK DEV的开发来规避。而往往项目并没有这么多的人力来做这方面的工业化。因此在实时引擎中录制timeline并输出颜色和序列帧来辅助在后期软件中的制作。而UNITY本身有提供这一需求的解决方案,就是recorder。但recorder对URP的支持非常有限,仅限于颜色的序列帧,例如后期中刚需的深度和objects id, motion vector等等都没有支持。
个人理解,一方面原因是因为URP是一个高度自定义的管线,其渲染流程相较于HDRP是不确定的(延迟原生带一些所需的rt,例如屏幕空间法线,diffuse, specular等)。另一方面则是为了照顾到全平台通用的特性,比较难以实现,因此项目应该基于自己的渲染流程来定制recorder用以实现不同的需求。

Recorder

什么是recorder?Recorder是unity自带的一款能够录制实时游戏序列帧并输出成EXR等序列帧后期软件支持的格式的官方插件。在HDRP中,Recorder的支持比较全面,基本覆盖了后期所需的全部功能。
如下图所示:
HDRP中的AOV

而URP这边的AOV是不支持的。(代码中做了判断)

Capture pass

URP中的序列帧输出主要依赖于管线中的capture pass

if (renderingData.cameraData.captureActions != null)
{
    m_CapturePass.Setup(sourceForFinalPass);
    EnqueuePass(m_CapturePass);
}

这段代码在URP12的universalrenderer.cs中,当我们注册了一个capture actions回调函数时,URP会执行capture pass来捕获序列帧。
那么在哪里注册这个capture action呢?

Input Strategy

注册这个capture actions需要我们自己来实现一个input stragty,他需要继承于CaptureCallbackSRPInputStrategy,在这个类中有一个实现一个add capture commands的函数,来自定义自己的capture action。

注册回调函数

这里可以参考recorder3.03中自带的camerainput类:

protected virtual void AddCaptureCommands(RenderTargetIdentifier source, CommandBuffer cb)
{
    if (source == BuiltinRenderTextureType.CurrentActive)
    {
        var tid = Shader.PropertyToID("_MainTex");
        cb.GetTemporaryRT(tid, m_RenderTexture.width, m_RenderTexture.height, 0, FilterMode.Bilinear);
        cb.Blit(source, tid);
        cb.Blit(tid, m_RenderTexture, copyMaterial);
        cb.ReleaseTemporaryRT(tid);
    }
    else
        cb.Blit(source, m_RenderTexture, copyMaterial);
}

从这里就可以看出执行的逻辑,实际就是一个blit函数把当前屏幕的颜色输出到所需的RT上。
有了这个参考,我们就可以根据需求实现自己的AOV,类似这样:

protected override void AddCaptureCommands(RenderTargetIdentifier source, CommandBuffer cb)
{
    if (source == BuiltinRenderTextureType.CurrentActive)
    {
        //....
    }
    else
    {
        switch (m_AOVType)
        {
            case AOVType.Depth:
                cb.Blit(source, m_RenderTexture, aovMaterial, AOVType.Depth);
                break;
            case AOVType.ObjectsId:
                cb.Blit(source, m_RenderTexture, aovMaterial, AOVType.ObjectsId);
                break;
            //......
        }

    }
}

之后在对应的shader中实现所需的功能,例如绘制objects id, motion vector等。
capture pass

成功输出之后就可以在对应的文件夹中看到序列帧:

设置对应的RT格式

Inupt strategy中同样也支持根据对应的AOV来设置对应的RT格式来满足后期软件中对于精度的需求。
主要在于实现自己的prepFrameRenderTexture,直接给出一个示例实现:

protected override void PrepFrameRenderTexture(RecordingSession session)
{
    if (OutputRenderTexture != null)
    {
        if (OutputRenderTexture.IsCreated() && OutputRenderTexture.width == OutputWidth && OutputRenderTexture.height == OutputHeight)
            return;

        ReleaseBuffer();
    }

    AOVImageRecorderSettings aovImageRecorderSettings = session.settings as AOVImageRecorderSettings;
    if (aovImageRecorderSettings == null) return;
    var fmtRW = RenderTextureReadWrite.Default;
    var fmt = RenderTextureFormat.ARGB32;

    switch (aovImageRecorderSettings.AOVType)
    {
        case AOVType.Depth:
            fmtRW = RenderTextureReadWrite.Linear;
            fmt = RenderTextureFormat.RFloat;
            break;
        case AOVType.ObjectsId:
            fmtRW = RenderTextureReadWrite.Linear;
            fmt = RenderTextureFormat.ARGB32;
            break;
            //......
    }

这里还引出了几个额外需要实现的类,例如aovImageRecorderSettings是一个继承于scriptableObject的类,主要用来存储参数。

UI

为了以Recorder规范的UI显示我们的参数,还需要实现一个aovImageRecorderSettingsEditor用来绘制,这部分完全可以参考recorder中已经实现的一些功能。需要指出,recordSettings是一个中继类,他用以让我们和input类进行沟通,便于我们将设置的参数最终传递到input类中来进行RT的录制。
在这里插入图片描述

总结

说的比较融通,主要讲一些大概思路。当然完全可以按照自己的思路来实现。但recorder中实现了各种导出序列帧的工具代码,自己来实现未免周期比较长。利用recorder已有的架构来实现自己的需求是一个不错的方案。

参考资料

https://docs.unity3d.com/Packages/com.unity.recorder@2.0/manual/index.html

### 解决PyCharm无法加载Conda虚拟环境的方法 #### 配置设置 为了使 PyCharm 能够成功识别并使用 Conda 创建的虚拟环境,需确保 Anaconda 的路径已正确添加至系统的环境变量中[^1]。这一步骤至关重要,因为只有当 Python 解释器及其关联工具被加入 PATH 后,IDE 才能顺利找到它们。 对于 Windows 用户而言,在安装 Anaconda 时,默认情况下会询问是否将它添加到系统路径里;如果当时选择了否,则现在应该手动完成此操作。具体做法是在“高级系统设置”的“环境变量”选项内编辑 `Path` 变量,追加 Anaconda 安装目录下的 Scripts 文件夹位置。 另外,建议每次新建项目前都通过命令行先激活目标 conda env: ```bash conda activate myenvname ``` 接着再启动 IDE 进入工作区,这样有助于减少兼容性方面的问题发生概率。 #### 常见错误及修复方法 ##### 错误一:未发现任何解释器 症状表现为打开 PyCharm 新建工程向导页面找不到由 Conda 构建出来的 interpreter 列表项。此时应前往 Preferences/Settings -> Project:...->Python Interpreter 下方点击齿轮图标选择 Add...按钮来指定自定义的位置。按照提示浏览定位到对应版本 python.exe 的绝对地址即可解决问题。 ##### 错误二:权限不足导致 DLL 加载失败 有时即使指定了正确的解释器路径,仍可能遇到由于缺乏适当的操作系统级许可而引发的功能缺失现象。特别是涉及到调用某些特定类型的动态链接库 (Dynamic Link Library, .dll) 时尤为明显。因此拥有管理员身份执行相关动作显得尤为重要——无论是从终端还是图形界面触发创建新 venv 流程均如此处理能够有效规避此类隐患。 ##### 错误三:网络连接异常引起依赖下载超时 部分开发者反馈过因网速慢或者其他因素造成 pip install 操作中途断开进而影响整个项目的初始化进度条卡住的情况。对此可尝试调整镜像源加速获取速度或是离线模式预先准备好所需资源包后再继续后续步骤。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值