前言
最近接到了一个需求,又是熟悉的 拍屏工具。
其实老早之前我就有写过类似的需求,只是表现形式各不相同。
这里打算将不同的拍屏方案汇总到一起,这样大家可以挑选一个合适的情景的方式完成这个任务。
拍屏方案汇总
最早在华强实习的时候,就写过将 Arnold 渲染的界面合成并打开 RV 进行预览。
背后主要用 renderWindowEditor 命令导出。
https://github.com/FXTD-ODYSSEY/MayaViewportCapture
后来进入腾讯前,我写了 Maya Viewport Capture 工具。
那个时候写的比较粗糙,我通过 UI 可以定义几个相机的位置,然后规定进行拍屏。
当时研究用 Maya 或者 Qt 的 API 将 Viewport 的画面截取下来。
背后主要用 Maya API M3dView 的 readColorBuffer
Qt 部分其实也是在拿到 Maya 的 MImage 之后转成 QImage 而已。
后来正式工作之后,发现前辈用的是 ogsRender 命令将 Maya Hardware 2.0 输出来。
相较于 renderWindowEditor 命令不需要打开渲染窗口。
实现拍屏有太多的方案,当然最为基础的方法就是使用 playblast 命令。
建议安装上 QuickTime 这样可以极大压缩 Maya 拍屏的文件大小,同时提升 Maya 拍屏的质量。
playblast 命令既可以直接生成视频也可以拍屏序列帧。
拍屏需求汇总
上面提供四种拍屏方案,最常用的时 playblast 方案,因为可以直接输出视频。
如果是图片序列还需要借助 ffmpeg 等命令行工具将图片序列合成为视频。
拍屏的需求千变万化,但是有一些点其实大差不差。
- 拍屏信息
- 镜头角度
比较常见的信息有 时间,影片的归属名字(比如动画的某一段),影片负责人 等等。
添加这些信息可以用 headsUpMessage 将相关信息叠加到 Viewport 上。
但是 headsUpMessage 非常难用,而且字体大小等各种非常不方便自定义。
要解决这个问题可以用 插件,它通过 OpenMaya API 扩展了 headsUpMessage 的功能。
作者是 zurbrigg ,只可惜它之前免费的工具现在变成付费了。
劲爆羊工具盒 里面有拍屏王,它就是通过 ZShotmask VP2 插件,将各种信息贴到屏幕上。
具体可以在劲爆羊工具盒
里面找到脚本resource\tools\MSTools\MST_DATA\plug-ins\zshotmask.py
当然它是一个 Maya Python 插件,注册之后提供了一个节点,只要设置节点的属性就可以了。
这个方式可以结合 playblast 解决大部分拍屏的问题。
但有些情况并不能很好解决,比如我遇到的问题就是,每一帧都要重新矫正一下镜头的位置。
而且这个矫正还不能单纯使用约束,需要每一帧单独进行计算。
所以我只能改用 ogsRender 的方式,在后台进行拍屏。
Maya ogsRender 输出序列帧
使用
ogsRender
输出序列帧只能输出到默认工程 images 文件夹的路径。
因此要控制ogsRender
输出的位置只能通过修改工程位置
1 | import contextlib |
我写了一个函数,可以修改输出位置,在修改回去。
这样我可以输出到任意路径。
Python ThreadPool 多线程后处理
上面拍屏生成的图片,可以放到 imagemagick 进行图片后处理。
imagemagick 是 maya 自带的命令行图形处理库。
在 Maya 2022 之前叫做imconvert.exe
, 2022 之后叫做magick.exe
imagemagick 用 C 和 C++ 编写的,非常小巧,而且运行速度很快~
这里我没有使用 ZShotmask VP2 直接拍屏输出我要的信息,因为有些信息想要通过 imagemagick 叠加到图片上。
于是我想到可以利用 Pool 线程池的方式多线程后台调用命令行。
其中
from multiprocessing.dummy import Pool
可以导入 Python 隐藏的线程池。
这个用起来比起使用threading
库要简单方便很多。
注:from multiprocessing import Pool
导入进程池, Maya 不太支持这个。
下面来个实例演示一下多线程调度后处理函数的好处。
1 | from multiprocessing.dummy import Pool |
执行上面的代码
1 | [sequence_run] elapsed time: 2.201172351837158 |
最后会得到用线程池的方式可以比直接执行快1倍。
而且这个代码是 py2 兼容的。
通过这个方式可以在 Maya 拍屏的时候用多线程调用 imagemagick 来对生成的图像进行处理。
这样用户几乎感受不到图像后处理的时间。
总结
以上就是 Maya 各种拍屏方案汇总,使用序列帧的自由度比较高,但是需要 ffmpeg 和 imagemagick 等依赖进行处理。
简单的需求可以直接用 playblast 加上 ZShotmask VP2 完成。