首页 > 编程语言 > 详细

Unreal Python Sequencer 批量渲染总结

时间:2020-09-16 21:09:53      阅读:49      评论:0      收藏:0      [点我收藏+]
# 本文章转载自 智伤帝的个人博客 - [原文链接](https://blog.l0v0.com/posts/2f3a9b95.html) ## 前言   最近我的学弟找我咨询关于 Unreal Sequencer 渲染输出的问题。   之前没有折腾过这个一块,于是就跟进了一下,顺便学习 Sequencer 的序列输出。   另外最近另一个师弟也研究了差不多的问题,发了一篇 B站专栏 , 在这里推荐一下 [链接](https://www.bilibili.com/read/cv6794860) ## 手动操作   在自动化操作渲染之前,需要先搞清楚怎么手动操作 Sequencer 进行渲染。 ![](https://blog.l0v0.com/post_img/2f3a9b95/01.png)   其实操作起来不难,打开 Unreal 的定序器,点击上面的 Render 图标打开 Render Movie Setting   然后配置好渲染设置就可以点击渲染,就可以将影片批量渲染出来。 ## 自动化操作   下面就是将手动操作转为 Python 的自动操作。   具体的操作脚本其实可以参考官方的脚本,在官方 SequencerScripting 插件里面有渲染相关的 Python 脚本。   安装了 Unreal 引擎之后可以根据地址查找 `\Engine\Plugins\MovieScene\SequencerScripting\Content\Python`   `sequencer_examples` 就有输出的 Python 代码,不需要自己查文档研究怎么搭建代码。   参照 `render_sequence_to_movie` 的代码即可输出。   其中比较坑的点在于 `OnRenderMovieStopped` 的 delegate   接入 Python 回调需要一个 global 函数才可以,否则执行完成的回调函数不会触发。   官方的案例是放到最外层执行的,如果不凑巧回调函数写在函数里面,就需要利用 global 关键字解决这个问题。 ---   官方案例还没能实现一个需求,就是批量将不同 Sequence 同时渲染出来。   然而 render_movie 这个函数是不阻塞的,如果使用 for 循环会一直把所有的 render_movie 持续执行。   所以这里进行渲染需要通过回调来实现逐个渲染的调用。 ## Python 代码 ```python # -*- coding: utf-8 -*- """ 渲染 sequencer 的画面 选择 LevelSequence 批量进行渲染 """ from __future__ import division from __future__ import print_function from __future__ import absolute_import __author__ = ‘timmyliang‘ __email__ = ‘820472580@qq.com‘ __date__ = ‘2020-07-14 21:57:32‘ import unreal import os import subprocess from functools import partial def alert(msg): unreal.SystemLibrary.print_string(None,msg,text_color=[255,255,255,255]) def render(sequence_list,i,output_directory="C:/render",output_format="{sequence}"): # NOTE 如果超出数组则退出执行 if i >= len(sequence_list): # NOTE 输出完成 打开输出文件夹的路径 subprocess.call(["start","",output_directory], creationflags=0x08000000,shell=True) return # NOTE 获取当前渲染序号下的 LevelSequence sequence = sequence_list[i] # NOTE 配置渲染参数 settings = unreal.MovieSceneCaptureSettings() path = unreal.DirectoryPath(output_directory) settings.set_editor_property("output_directory",path) settings.set_editor_property("output_format",output_format) settings.set_editor_property("overwrite_existing",True) settings.set_editor_property("game_mode_override",None) settings.set_editor_property("use_relative_frame_numbers",False) settings.set_editor_property("handle_frames",0) settings.set_editor_property("zero_pad_frame_numbers",4) settings.set_editor_property("use_custom_frame_rate",True) settings.set_editor_property("custom_frame_rate",unreal.FrameRate(24, 1)) # NOTE 渲染大小 w,h = 1280,720 settings.set_editor_property("resolution",unreal.CaptureResolution(w,h)) settings.set_editor_property("enable_texture_streaming",False) settings.set_editor_property("cinematic_engine_scalability",True) settings.set_editor_property("cinematic_mode",True) settings.set_editor_property("allow_movement",False) settings.set_editor_property("allow_turning",False) settings.set_editor_property("show_player",False) settings.set_editor_property("show_hud",False) # NOTE 设置默认的自动渲染参数 option = unreal.AutomatedLevelSequenceCapture() option.set_editor_property("use_separate_process",False) option.set_editor_property("close_editor_when_capture_starts",False) option.set_editor_property("additional_command_line_arguments","-NOSCREENMESSAGES") option.set_editor_property("inherited_command_line_arguments","") option.set_editor_property("use_custom_start_frame",False) option.set_editor_property("use_custom_end_frame",False) option.set_editor_property("warm_up_frame_count",0.0) option.set_editor_property("delay_before_warm_up",0) option.set_editor_property("delay_before_shot_warm_up",0.0) option.set_editor_property("write_edit_decision_list",True) # option.set_editor_property("custom_start_frame",unreal.FrameNumber(0)) # option.set_editor_property("custom_end_frame",unreal.FrameNumber(0)) option.set_editor_property("settings",settings) option.set_editor_property("level_sequence_asset",unreal.SoftObjectPath(sequence.get_path_name())) # NOTE 设置自定义渲染参数 option.set_image_capture_protocol_type(unreal.CompositionGraphCaptureProtocol) protocol = option.get_image_capture_protocol() # NOTE 这里设置 Base Color 渲染 Base Color 通道,可以根据输出的 UI 设置数组名称 passes = unreal.CompositionGraphCapturePasses(["Base Color"]) protocol.set_editor_property("include_render_passes",passes) # protocol.set_editor_property("compression_quality",100) # NOTE 设置全局变量才起作用! global on_finished_callback on_finished_callback = unreal.OnRenderMovieStopped( lambda s:render(sequence_list,i+1,output_directory,output_format)) unreal.SequencerTools.render_movie(option,on_finished_callback) def main(output_directory="C:/render",output_format="{sequence}"): # NOTE 获取当前选择的 LevelSequence sequence_list = [asset for asset in unreal.EditorUtilityLibrary.get_selected_assets() if isinstance(asset,unreal.LevelSequence)] if not sequence_list: alert(u"请选择一个 LevelSequence") return if not os.access(output_directory, os.W_OK): alert(u"当前输出路径非法") return elif not os.path.exists(output_directory): # NOTE 路径不存在则创建文件夹 os.makedirs(output_directory) elif os.path.isfile(output_directory): # NOTE 如果传入文件路径则获取目录 output_directory = os.path.dirname(output_directory) render(sequence_list,0,output_directory,output_format) if __name__ == "__main__": main() ```   选择 Sequencer 执行上面的脚本,就可以自动批量输出 Sequencer 了。 ## 总结   理论上 Python 调用蓝图方法做到的功能, 蓝图应该也可以做到的。   但是经过我的测试,我发现 蓝图 的 `get_image_capture_protocol` 返回值是 基类。   导致无法获取 `CompositionGraphCaptureProtocol` 这个类   也就无法设置 `include_render_passes` 的值了,这样导致蓝图输出会将所有通道输出,而不能实现单一通道的输出。 ---   另外这一次没有制作 GUI ,我还在纠结使用 Qt 还是 Unreal 原生的界面。   Unreal使用 Editor Utility 创建的 UI 是二进制 uasset ,无法向前兼容 Unreal 版本。   UI的功能响应上也没有 Qt 成熟。   但是无论如何,Unreal 的 UMG 是原生体验,嵌入样式各方面都比较舒服的。   虽然 Qt 可以写一套 Qss 来解决样式问题,但是在 Unreal 中实现 Dock 目前还是无解。

Unreal Python Sequencer 批量渲染总结

原文:https://www.cnblogs.com/timmyliang/p/13680838.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!