分享点有意思的 Python 小技巧,帮助你将工做中的一部分交给计算机自动化运行,没有程序经验也能学会,否则就不叫小技巧了!node
举个栗子,咱们用 Gooseberry 项目的尽头1.2.1为例,这是由 Hjalti 制做的一个片断python
感谢 Blender 的库和连接系统,这可使得我在为场景设计灯光等工做的同时,不受 Hjalti 对场景或人物作任何修改后的影响,我只须要从新更新一下个人 blend 文件,或者从新打开一次,已经在 SVN 上提交后的最新文件就会自动在个人场景文件中更新了。不过若是你不知道什么是 SVN,我能够试着去以前的开源电影博客中找找相似的介绍文章,不过你也能试试搜索一下,网上有不少关于 SVN 的介绍。不过到后面等 Lukas 完成了新的资源管理系统开发,这种协同方式可能会有所调整,不过将来还将来,咱们先看看如今能够作些什么吧。程序员
当咱们完成了高模场景、完整的光照设计、渲染须要的雾效或各类随机生成的石块等网格物体,还包含 Victor 和 Franck 的动做文件,他们在被连接至合成 .comp 文件以后,属性都将被锁定起来,仅能在源文件中编辑修改,可是当咱们在测试渲染时,须要临时改动大量的属性,就可能须要对各个物体进行单独调整。个人意思 是,这一步你能够手工完成,固然,也能够靠脚原本批量化执行,很明显这是脚本最能体现其价值和优点的地方啦!express
有了脚本,如下这些工做只须要动动鼠标按键就能够了:apache
开启/关闭各种设置中的属性开关app
为各种设置中的数值属性从新赋值socket
隐藏一些不须要显示的粒子系统,或者修改他们的粒子树和随机因子(这些修改绝对不会影响源文件的设置)编辑器
重写 Victor 的一些关键属性,例如将他的头变大两倍!ide
删除掉导入至视频编辑器中的一些无用参考视频(将来的 BAM 系统将不会调用这些未使用到的片断,不过如今不行)wordpress
开启并添加一些渲染印章信息,包括采样数、渲染时间和渲染农场的节点名称等,通通都打印出来
其实还有不少啦!
好吧,如今开始正题。
我接下来会在Blender 的文本编辑器中新建两个文件,分别以下(Shift + F11):
settings.py – 这个脚本将用于修改渲染设置、用户参数,以及场景或视图中可优化的属性,单击菜单上的 “Run Script”便可运行。
startup.py – 这个脚本将用于修改粒子系统的显示,以及一些渲染印章的信息,这个脚本在每次打开 .blend 文件后将自动运行(主要用于渲染农场),因此这个脚本必须开启注册选项,即 ‘Register’ 须要被选中。
settings.py 能够命名为任意名称,由于他是一个自行执行的文件,但 startup.py 必须以 .py 结尾,不然将没法被执行注册执行(实际上,只有当文件以 .py 结尾, “Register” 选项才会显示为可开启的状态,不然为灰色)。
文章最后你能够下载到完整的脚本。
这里再加一个小提示,那就是 Pablo 的 Amaranth 脚本是一个至关不错的生产优化插件,点击这里查看器完整的功能列表。我最喜欢的其中一个功能,就是场景的调试选项,能够帮你找到丢失的贴图等。Amaranth 能够由你自行编译,也能够在 Blender 的自动编译版本中下载。
好了,接下来咱们就分别看看这两个脚本是如何编写的。
我喜欢在脚本的前面将一些我经常使用的参数作一个定义并赋值,这样在脚本中直接调用这些变量便可,而不是满屏幕的处处找这些属性而后分别修改参数。脚本的注释以 # 开头,因此随便写什么都不会印象代码的运行。
专业的脚本都会有一些注释规范,不过这篇文章不是写给程序员的,因此你们就随意吧
____ _ / ___| ___ ___ ___ ___| |__ ___ _ __ _ __ _ _ | | _ / _ \ / _ \/ __|/ _ \ '_ \ / _ \ '__| '__| | | | | |_| | (_) | (_) \__ \ __/ |_) | __/ | | | | |_| | \____|\___/ \___/|___/\___|_.__/ \___|_| |_| \__, | |___/
##############################################################
#
# SETTINGS
Samples = 50
Depth_of_field = 0.006
|
开头的符号文字能够在右侧连接中生成: ASCII 生成器。
脚本开头要这么写就好了:
##############################################################
#
# SCRIPT
import bpy
Scene = bpy.context.scene
|
咱们在本文中涉及到的大部分代码和方法均可以在 Blender 的界面上找到,你只须要将鼠标移动到某个参数上面,就会看到下图中得相似提示,虽然你看到的也许根本就不是最后实际调用的方法,但至少能够给你一些编写提示:
接着单击 Shift + F4 进入 Python 控制台,而后敲入:bpy.data.sce… 并单击组合键 CTRL + Space 来获取代码自动提示,再按一次进入下一个提示。若是要清除当前输入,能够单击 Shift + Enter。咱们能够试试 bpy.data.scenes[‘Scene’].render.use_simplify 而后再按回车,控制台就会根据当前系统设置显示出对应的结果,若是咱们但愿对参数作出修改,能够先单击方向上键调出上一次输入的代码,而后在后面跟上 “= True” (或者是 1),回车后看看面板上参数的变化吧!
看到了吧,已经被脚本修改了,漂亮!
这样,咱们就已经大体找到了用脚本控制参数的方法,剩下的事情就简单了,你只须要按照相似方式书写便可:
Scene.render.use_simplify = True
Scene.render.simplify_subdivision = 0
Scene.use_unsimplify_render = True
|
完成编辑后,单击 ‘Run Script’ 按钮便可运行当前脚本,并且是批量执行的哦!
学会了吧,咱们继续。
# Render Display Mode:
Scene.render.display_mode = ‘SCREEN’
Scene.render.use_lock_interface = True
# Uncheck Post Processing:
Scene.render.use_compositing = False
Scene.render.use_sequencer = False
|
你能够看到场景的命名 ‘SCREEN’ 实际上是你能够手动在页面布局菜单上设置的,固然也可使用脚原本批量统一重命名,使用下面的命名能够查看当前激活场景的名称:
变量 Depth_of_field 在脚本的最开头已经作了赋值,因此这里直接调用便可。
# Camera settings:
Scene.camera.data.cycles.aperture_size = Depth_of_field
Scene.camera.data.cycles.aperture_ratio = 2
Scene.camera.data.show_name = True
|
这里的代码是可使用脚原本为渲染添加一个驱动,让每一帧的采样均可以不一样(固然你能够手动为某一帧添加采样因子)。
注意:这里咱们假定场景中没有其余的渲染驱动(场景等级和角色的骨骼驱动不算),因此咱们使用的代码是默认从0开始 Scene.animation_data.drivers[0],若是你场景中有现成的驱动,那么就须要根据状况增长驱动树字,例如 Scene: [1], [2], 等等。
# Sampling seed to “#frame”:
Scene.cycles.driver_add(‘seed’)
Scene.animation_data.drivers[0].driver.expression = ‘frame’
|
我常用 JPEG 来保存个人测试渲染,可是在发送到渲染农场 Flamenco以后,我但愿渲染输出为 PNG 格式。
# Output to JPEG 100% (for easy test render saving):
Scene.render.image_settings.file_format = ‘JPEG’
Scene.render.image_settings.quality = 100
|
渲染的印章数据通常会被写入到图片的元数据中,因此咱们其实并不须要开启渲染结果的印章显示(但印章参数依然须要被激活)。在另一个 startup.py 脚本中,咱们再定义这些参数的输出格式(例如渲染农场中的节点名称,或者是采样数等等)
若是你但愿将这些参数打印出来,只须要激活 use_stamp 的值便可,参考阅读 《如何配置渲染图章的显示》
# Disable burned-in stamp:
Scene.render.use_stamp = False
# Enable needed stamp values for metadata:
Scene.render.use_stamp_time = True
Scene.render.use_stamp_date = True
Scene.render.use_stamp_render_time = True
Scene.render.use_stamp_frame = True
Scene.render.use_stamp_camera = True
Scene.render.use_stamp_lens = True
Scene.render.use_stamp_filename = True
Scene.render.use_stamp_marker = True
Scene.render.use_stamp_note = True
|
这些设置对咱们颇有用,但未必适合大家,例如在 Gooseberry 中得洗衣房场景中,洗衣机上有大量的反射材质,这在室内看上去效果很棒,可是若是场景切换至海岛上,这些反光效果基本上不可能被注意到了,因此为了节约资源咱们选择关掉。
# Use Preview Range OFF:
Scene.use_preview_range = False
# Sampling:
Scene.cycles.samples = Samples
Scene.cycles.sample_clamp_direct = 11
Scene.cycles.sample_clamp_indirect = 5
Scene.cycles.volume_step_size = 1
Scene.cycles.volume_max_steps = 1024
# Light Paths:
Scene.cycles.transparent_max_bounces = 8
Scene.cycles.transparent_min_bounces = 8
Scene.cycles.max_bounces = 2
Scene.cycles.min_bounces = 1
Scene.cycles.diffuse_bounces = 2
Scene.cycles.glossy_bounces = 2
Scene.cycles.transmission_bounces = 2
Scene.cycles.volume_bounces = 1
Scene.cycles.caustics_reflective = False
Scene.cycles.caustics_refractive = False
Scene.cycles.blur_glossy = 2
|
这里经过调整 Cycles 的毛发细分参数来控制关联的毛发对象,而且设置是基于整个场景的,因此不会影响到导入的源文件自己。咱们能够根据镜头来分别调整,让他们在近景时看上去更茂密,可是在远镜头的时候就适当减小细分等级,优化渲染时间。
# Hair settings:
Scene.cycles_curves[‘primitive’] = 2
Scene.cycles_curves.subdivisions = 4
Scene.cycles_curves[‘shape’] = 0
|
我说实话我也不知道为何他们会出如今这里,由于一旦导入以后,就会自动加载到序列编辑器上,咱们须要手动进入全选而后删除掉。这对于小文件来讲没 什么,可是咱们须要将这些文件发送到渲染农场,那么系统会将这些文件也一块儿打包传上去,那么问题就大了,由于文件会增大不少,不事后面的 BAM 系统将优化这一块的功能。
若是你但愿完成更多功能的脚本,那么我建议你能够到问答社区 Blender Stack Exchange 中看看,或者找找你周围有没有相似 Pablo 这样优秀脾气又好的程序员帮忙吧。
# Remove Sequencer Strips:
class SequencerStripSlayer(bpy.types.Operator):
“””Delete All Strips”””
bl_idname = “sequencer.strip_slayer”
bl_label = “Sequencer Strip Slayer”
def execute(self, context):
# Save which editor are we in when we run the operator
where = bpy.context.area.type
# Temporary switch to the Sequencer to get context data
bpy.context.area.type = ‘SEQUENCE_EDITOR’
# Build the context to override
override = {
“window”: bpy.context.window,
“screen”: bpy.context.screen,
“scene”: context.scene,
“area”: bpy.context.area,
“region”: bpy.context.area.regions[0],
“blend_data”: context.blend_data}
# Check if we have sequences at all
if context.scene.sequence_editor and context.scene.sequence_editor.sequences_all:
i = 0
# loop through all the strips
for s in context.scene.sequence_editor.sequences_all:
# select them!
s.select = True
# this is just to count them (for the report message)
i += 1
# DIE DIE DIE!
bpy.ops.sequencer.delete(override)
# Report, if we have more than 0
if i != 0:
self.report({“INFO”}, “BAM! {0} Strips Destroyed!”.format(i))
else:
self.report({“INFO”}, “No strips to murder”)
else:
self.report({“INFO”}, “No sequences”)
# Go back to the area we were before
bpy.context.area.type = where
return {‘FINISHED’}
|
下面的代码将做为整个脚本的结尾,用于实现注册,若是你要加什么新功能,请务必加载如下代码以前。
def register():
bpy.utils.register_class(SequencerStripSlayer)
def unregister():
bpy.utils.unregister_class(SequencerStripSlayer)
if __name__ == “__main__”:
register()
# Now actually run the operator. By commenting this line below, the delete operator will not run, but it will be registered. So you can find it via Space bar search and use it when needed.
bpy.ops.sequencer.strip_slayer()
|
##############################################################
#
# SETTINGS
# Define some names to the stamp note:
Animator = ‘Hjalti’
Compositor = ‘Manu’
|
这里的命名尽可能不要和选项中的名称相同,不然你本身均可能分不出哪一个是变量哪一个是属性了。
##############################################################
#
# SCRIPT
import bpy
import socket
|
接口主要用于检测渲染结点的名称,方便后面打印到元数据中。
肯定脚本中使用最佳参数的方法,就是在控制台中一边调,一边在视图中查看效果啦:
你能够看到,在这个例子中,咱们刻意向你展现了,若是粒子系统没有作合理命名,那么在脚本调用中,查找对应的粒子是多么的痛苦。因此对于粒子的相关 设置,务必要有一个良好的命名规范,包括粒子的修改器等。将来若是粒子的系统引擎得意优化以后,整个粒子的调用应该会更简单,不过这不是我说了算,仍是先 看看如今该怎么作吧。
这个范例中的代码并不是通用,而是彻底根据你的文件结构来实现,因此你也许还须要打开源文件来一一对比查找(在 Amaranth 中却是十分的轻松),方法和以前 settings.py 中提到的相似。
# Particle systems:
bpy.data.objects[‘GEO-cliff_ground_high’].modifiers[‘ParticleSystem 3′].show_viewport = 1
bpy.data.particles[‘cliff_grass.001′].count = 12000
bpy.data.particles[‘cliff_grass.001′].hair_length = 200
|
如下代码是用于关闭某些粒子系统的渲染输出,以及修改一些粒子的随机因子参数(其实就是用来调整效果啦):
bpy.data.objects[‘GEO-cliff_ground_high’].modifiers[‘ParticleSystem 3′].show_render = 0
bpy.data.objects[‘GEO-cliff_ground_high’].particle_systems[‘island_plants_small_dead’].seed = 16
|
下面你能够找到用于自定义输出渲染印章的元数据代码,它们在 Blender 运行的开始就将收集所须要的信息,例如渲染节点的名称。
另外,印章数据还能够包含采样数,摄像机的景深参数,Blender 的版本号以及谁在修改当前源文件(这个在脚本的开始已经作了定义)
当渲染启动以后,你就可使用一个专用软件来查看完整信息,我用的是 XnView MP 以及 ExifTool ,咱们的 gooseberry 项目团队使用的有 nomacs Image Lounge (Win/Mac/Linux),在其 2.4.5 的开发版本中,其已经能够完美支持 Blender 的 PNG 元数据查看啦!(点这里下载 Nomacs 2.4.5 .deb installer for a 64-bit Ubuntu based OS – 但请记住,这不是一个稳定的版本哦!)
你其实还能够用 Blender 的图片查看器来查看元数据。
# Stamp note script:
def stamp_set(scene):
render = scene.render
is_cycles = (render.engine == ‘CYCLES’)
render.use_stamp_note = True
render.stamp_note_text = (
“Samples: {samples} | “
“Aperture Radius: {aperture:.4f} | “
“Blender {ver} {branch} {hash} | “
“Animator: {anim} | “
“Compositor: {comp} | “
“Rendernode: {hostname}”
).format(
samples=scene.cycles.samples if is_cycles else render.antialiasing_samples,
aperture=scene.camera.data.cycles.aperture_size if is_cycles else “NONE”,
ver=bpy.app.version_string,
branch=bpy.app.build_branch,
hash=bpy.app.build_hash,
hostname=socket.gethostname(),
anim=Animator,
comp=Compositor,
)
bpy.app.handlers.render_pre.append(stamp_set)
|
下面的脚本将覆盖掉导入的某些参数,例如 Victor 的骨骼控制器。这里将演示如何切换 Victor的头发粒子系统开关,让其在载入时就直接关闭掉,不过其自己依然拥有以前开启的动画属性。
# Override keyed PARTICLES_TOGGLE value:
from bpy.app.handlers import persistent
@persistent
def load_handler(dummy):
bpy.data.objects[‘victor_high_proxy.001′].pose.bones[‘properties’][‘PARTICLES_TOGGLE’] = 0
bpy.app.handlers.render_pre.append(load_handler)
|
还有,你能够静默掉一些动画通道,例如关闭摄像机的晃动曲线:
bpy.data.objects[‘camera’].animation_data.action.fcurves[0].mute = True
#(or False)
|
控制其余通道只须要修改数字下标便可。