blender 命令行渲染

Posted 长虹剑

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了blender 命令行渲染相关的知识,希望对你有一定的参考价值。

基础环境配置

安装及资料

apt-get install blender

Blender 2.91 参考手册

运行python脚本

Blender python 初步文档

有关渲染的样例

虚拟桌面 Xvfb

在服务器上想要运行blender需要建立虚拟桌面,挺简单的就

apt-get install Xvfb

使用的时候,首先开启虚拟桌面到后台,然后就可以运行 blender 了

export DISPLAY=:6
Xvfb -ac :6 -screen 0 640x480x24 & # 1920x1080x24
blender -b --render-output tmp/res -f 0

blender 内置 python 修改 packages

找了半天至今不知道 blender 到底是调用的哪里的 python ,不过我猜测它可能把 python 给直接编译进去了,所以后期我们应该是换不了这个python的。所以就直接 sys 中替换加载变量的路径就行。

具体就是先运行

blender -b -P ck_bpy.py

ck_bpy.py 就写一个 print(sys.path)
获得路径,然后自己的 python 也打印一下,把路径拿出来,插入到指定位置就行。

编译 blender

svn 太慢,wget 下载的方法如下

wget -P download -r -p -np https://svn.blender.org/svnroot/bf-blender/trunk/lib/linux_centos7_x86_64 -o res.log

初步尝试杂记

渲染

用默认的blend,调用脚本渲染

blender -b -P tmp/test.py -o tmp/res -f 0
import bpy
for e in bpy.data.objects:
    print(e.name)
bpy.ops.render.render()
bpy.data.images['Render Result'].save_render(filepath='tmp/res/example.png')

直接命令行指定渲染

blender -b --render-output tmp/res -f 0

自己的一些代码

(未整理)

基本渲染设置

def f2_render_bones_video():
    FPS = 15 # 60
    smpl2skeleton = Cls_smpl2skeleton( fsmpl2rig, fparents, frot_mp )
    pms = smpl2skeleton.example( fpm )
    params.pms = pms
    params.parents = smpl2skeleton.parents
    params.NJ = smpl2skeleton.NJ

    ob = bpy.data.objects["smpl_skeleton"]
    bpy.app.handlers.frame_change_pre.clear()
    bpy.app.handlers.frame_change_pre.append(frame_change_pre)
    bpy.context.view_layer.objects.active = ob #相当于鼠标左键选中
    bpy.ops.object.mode_set(mode='POSE') #切换为pose更改模式
    arr = []
    bones = []
    for i in range(24):
        bone=ob.pose.bones[f'Bone{i}']
        bone.rotation_mode = 'AXIS_ANGLE' #'XYZ'
        bones.append( bone )
        if i==0:
            arr.append( bone.location.copy() )
        arr.append( bone.rotation_axis_angle )  # tuple arr
    #print( [ e[:] for e in arr ] )
    params.T_pose = arr
    params.bones = bones
    set_render_engine()
    if isdbg:
        #set_scene( 30  )
        set_scene( 3  )
    else:
        set_scene( len(params.pms)  )
    set_render_for_video( fv, fps=FPS )

    bpy.ops.wm.save_mainfile( filepath = fblend )

def frame_change_pre(scene):
    rcnt = scene.frame_current
    NJ = params.NJ
    bones = params.bones
    bones[0].location = params.T_pose[ 0 ].copy()
    for i in range(params.NJ):
        #if i==0:
        #    print(111, params.T_pose[ i+1 ][:], bones[i].rotation_axis_angle[:])
        bones[i].rotation_axis_angle = params.T_pose[ i+1 ]

    pm = params.pms[rcnt]
    for i in range(NJ-1, -1, -1):
        a = 3+i*4
        #if i==0:
        #    print( pm[a:a+4], bones[i].rotation_axis_angle[:] )
        bones[i].rotation_axis_angle = tuple(pm[a:a+4].tolist())
    bones[0].location = pm[:3]


def set_render_engine():
    for scene in bpy.data.scenes:
        scene.render.engine = 'BLENDER_EEVEE'

    scene = bpy.context.scene
    eevee = scene.eevee

    eevee.use_soft_shadows = True

    eevee.use_ssr = True
    eevee.use_ssr_refraction = True

    eevee.use_gtao = True
    eevee.gtao_distance = 1

    eevee.use_volumetric_shadows = True
    eevee.volumetric_tile_size = '2'

def set_scene( full_frame ):
    bpy.context.scene.frame_end = full_frame
    #bpy.context.scene.camera = bpy.data.objects['camera']

def set_render_for_video(fv, fps=30, w=640, h=360 ):
    r = bpy.context.scene.render
    r.filepath = fv
    #scene.render.image_settings.file_format = 'PNG' # set output format to .png
    r.image_settings.file_format = 'FFMPEG' # set output format to .png
    r.ffmpeg.format = 'MPEG4'
    r.fps = fps
    r.resolution_x = w
    r.resolution_y = h

    bpy.ops.render.render(animation=True)

    #r.image_settings.file_format = 'PNG'
    #r.color_mode = 'RGBA'
    #bpy.types.FFmpegSettings.codec = "PNG"
    #bpy.types.FFmpegSettings.pix_fmt = "RGBA"

def set_render_for_picture(fimg, w=640, h=360 ):
    r = bpy.context.scene.render
    r.filepath = fimg
    r.image_settings.file_format = 'PNG'
    r.resolution_x = w
    r.resolution_y = h
    bpy.ops.render.render(write_still=True)

骨骼驱动的一些心得

骨骼的正确驱动包括几个因素:

  1. 骨骼设计
  2. 蒙皮权重
  3. 代码与骨骼的对应

比如基于SMPL样式的骨架有下面两种
1)完全符合 SMPL 系数的骨架

2)符合直觉的骨架

这两种骨架会导致使用smpl系数时写代码以及自动绑定的难易。

  1. 第一种骨骼:与SMPL系数几乎直接对应(可能需要坐标变换),但是如果使用blender的自动绑定权重会非常不合理,需要手动刷权重。
  2. 第二种骨骼:需要根据骨骼局部坐标轴,确定变换矩阵。(就需要写code时推导一下)

一些总结@9-2

  1. 在坐标系转换中,最终考虑的是点变换,但是我们一般直接看坐标系得到的变换其实是坐标系变换,与点变换互逆
  2. 由1 可知我们实际得到标准坐标系到骨骼局部坐标系的变换 M: A->B, 而点变换是M.T
  3. 执行坐标系变换夹杂旋转变换时时要考虑一个点,最终可以得到 M_.T x R x M_ x p , 前三个组成了最终的旋转变换,注意如果使用2,则M_=M.T
  4. blender 中显示的是骨骼的局部坐标系,如果想要变成统一的骨骼,那么骨骼都是竖直朝上的,这样写程序好些,但是自动绑定的时候蒙皮会有很大的问题。

之后发现一个事情
当blender中导入fbx 选择自动权重时,骨骼会比较正常

以上是关于blender 命令行渲染的主要内容,如果未能解决你的问题,请参考以下文章

blender 命令行渲染

Blender制作多个动画片段时踩的坑

从 Blender 2.8 导出到 LibGDX

Blender:音序器不支持边框渲染

blender学习笔记:python脚本使用与离线渲染

blender学习笔记:python脚本使用与离线渲染