imageは利用前にsave()しろ!pythonコマンドからのベイクの仕方

imageの仕様的な

ワンボタンでベイクとセットアップができる便利機能を作ってたんだけど、その際にimageの変な(?)仕様でつまづいた。

はじめこんな調子(ざっくり)のコードをかいたわけだけど、

img = bpy.data.images.new(filename,size,size,True)
bpy.ops.object.bake_image()
img.filepath = savepath
img.save()

これがまともに動かない!真っ黒な画像が出力されてしまう。
で、すったもんだほんとにいろいろ試して調べた結果、以下のようにすべきだとわかった

img = bpy.data.images.new(filename,size,size,True)
img.filepath = savepath
img.save()
bpy.ops.object.bake_image()
img.save()

bake前に一回保存!!!

すると、まともに出力できる。どうもnew()したあとは初期化が済んでないんだかなんだか、まともにつかえない。一回save()するとまともに動くようになる。
今回は外部ファイルに保存するのが前提だったのでinternalでやる方法は調べてない。多分pack()すればいいんじゃないか?わかんないけど。

豆知識

imageにはimage.is_dirtyというフラグがあり、いろいろ操作して保存されていない状態だとTrueになる。まとめて保存とか書くときはこれを使うと便利。

pythonコマンドからのベイクの仕方

で、それだけで終わってもなんなのでpythonコマンドからのベイクの仕方について。
これもつまづきポイントがある。
APIリファレンスを見てみると、ベイクには
の2つがある。
bake()にはなんか引数がいっぱいついており、bake_image()には引数が全くない。
なるほどスクリプトからはbake()を使えばいいんだな、と思う。
これが間違っている…。

bake()をするには、UI上で編集モードに入り、UV画像エディタで画像を選択する、という操作が必要で、それがなければ「アクティブ画像がありません」とおこられる。
普通にやってもスクリプトからはどうにもならない。
スクリプトからベイクするにはbake_image()を使わなければならない。

bake_image()のための準備

bake_image()ではUI上でアクティブ画像を設定する必要がない。
しかし、オブジェクトのUVデータ上でベイク先画像を設定しなければならない。
のでこんな感じの準備をする必要がある。

imgtobebaked = bpy.data.images.new(filename,size,size,True)
imgtobebaked.filepath = hogehoge
imgtobebaked.save()
for uvface in bakeobj.data.uv_textures.active.data:
    uvface.image = imgtobebaked 

bake_image()の設定

bake_image()には引数がないんだけどどこでレンダ設定すんの??
ってとこだけど、実はなんとこれ、UIでいうレンダパネル内のベイク設定が使用される。なるほどだから引数がいらないのか!
ということで、ベイクの種類とか設定をいじりたい場合は
bpy.context.scene.render.bake_type = 'FULL'
bpy.context.scene.render.use_bake_selected_to_active = True
みたいな指定をしてやればいい。

ベイクのざっくりコード

ということで

imgtobebaked = bpy.data.images.new(filename,size,size,True)
imgtobebaked.filepath = hogehoge
imgtobebaked.save()
for uvface in bakeobj.data.uv_textures.active.data:
    uvface.image = imgtobebaked 

bpy.context.scene.render.bake_type = 'FULL'
bpy.context.scene.render.use_bake_selected_to_active = True

bake_image()

imgtobebaked.save()

のようなコードをかけば、スクリプトからベイクできるのである。

複数ベイクする場合の注意

スクリプトからやるからには、baseColorとかNormalとかAOとかを一度に処理しようとするはずであるけど、この時一個ずつベイクして、ベイクした画像をマテリアルに設定して、ということをしてしまうとテクスチャの循環参照でエラーが起きる。
一旦全部ベイクしきってから、結果をマテリアルに設定していくほうがよい。
既にマテリアルに設定してある画像にベイクする場合は、テクスチャを無効にするとかマテリアルを一回外すとかしたほうがよい。



コメント

このブログの人気の投稿

漫画用アドオン群公開しました

Rigify!(Blender 2.79)