カテゴリー別アーカイブ: 趣味

Blenderで半田とガラスの素材を作って、それっぽくレンダリングしてみた結果

以下の手順で、pythonだけで作ったポリゴンをBlenderでレンダリングしてみた。

  1. pythonとmatplotlibでポリンゴンデータを自作する
  2. meshデータを作る
  3. データオブジェクトを作る
  4. データオブジェクトをBlenderに登録する
  5. 自作した頂点情報と平面情報を、meshに登録して更新する
  6. それっぽいマテリアルを作ってレンダリングする

これで、そこそこ満足な結果にはなるのだけど。

  • matplotlibで表示したのと、微妙に位置がずれている
  • 頂点数が少ないのでカウカクしている
  • レンダリングした結果が、ステンドグラスっぽく見えない

微妙な位置ずれは3D Viewの時だけで、レンダリングには影響していない様なので、 とりあえず放置。

あとは、レンダリングの調整なので、Blenderの機能でアレコレ試してみる。

ポリンゴンを操作して半田(ガラスの境目)面の隙間を埋める

ガラスに沿って半田を再現するのは難しいので、 pythonの自作ポリゴンでは、厚みの無い平面で半田を表現していた。

ガラスの寸法は、半田が入るのを見越して小さめにしているので、 部品の境界に少し隙間が空いていた。

3D Viewでは目立たないけど、レンダリングすると隙間に筋が見えてしまう。

Blenderの SOLIDIFY Modifier を使って、この隙間を塞ぐ。

sm = obj.modifiers.new('Solidify', 'SOLIDIFY')
sm.thickness = 2

ポリンゴンを操作して半田の表面を丸める → 失敗

標準機能に、色々なModifiersがあるので試してみたけど、 所望の動作をする機能は見付からなかった。

Modifiersに合わせて、元の設計を少し変更した方が良さそうだ。

ちなみに、Modifiersを使うのはとても簡単。

solder.modifiers.new('modi', type='SUBSURF')
solder.modifiers.new('modi', type='SMOOTH')
solder.modifiers.new('modi', type='CAST')

とすれば良い。 気軽に色々な効果を試せるのが素晴しい。

マテリアルの質感の調整

ガラスの色、屈折率、透明感、テクスチャなどを色々設定。お好みで。

raytrace_mirror は、全部にかけるとレンダリングに時間がかかるので、 要所要所だけにしておくと良い。

# 素材:暗いガラス
glass2_mat = bpy.data.materials.new(""darkglass"")
glass2_mat.type = 'SURFACE'
glass2_mat.diffuse_color = (0, 0, 0.5)
glass2_mat.diffuse_intensity = 0.8
glass2_mat.use_transparency = True
glass2_mat.transparency_method = 'RAYTRACE'
glass2_mat.alpha = 0.55
glass2_mat.use_raytrace = True
glass2_mat.raytrace_transparency.ior = 1.56
glass2_mat.raytrace_transparency.falloff = 0.2
glass2_mat.raytrace_transparency.filter = 0.05
glass2_mat.raytrace_transparency.depth = 8
glass2_mat.raytrace_transparency.fresnel = 0.1
glass2_mat.raytrace_mirror.use = True
glass2_mat.raytrace_mirror.reflect_factor = 0.2
glass2_tex = bpy.data.textures.new(""marbleglass"", type='STUCCI')
glass2_tex.use_color_ramp = True
glass2_mat.texture_slots.add()
glass2_mat.texture_slots[0].texture = glass2_tex
casebox.data.materials.append(bpy.data.materials['darkglass'])

IORは、(Index Of Refraction, 屈折率)の意味らしい。 ぐぐった所、透明なものは大体こんな感じだった。 他の素材については、Blenderのページに沢山掲載されている。

他のパラメータの意味は

名称 意味 ガラスの参考値
Alpha 濁り具合 0.0
IOR 屈折率 1.5
Filter 色のつき具合 1
Depth 計算回数 8 最低でも4

細かい数字の大小は、あんまり気にしなくて良いみたいだ。

床に木目と影をつける

これまでで、そこそこガラスっぽさは出てきているのに、 何か不自然だと思ったら、床に影が出ていないからだ。

床も真っ白で、如何にもCGだし。

木目パターンを BEIZ Graphics さんの無料素材を有り難く使わせて頂いて、 以下の様に、マテリル>テクスチャ>画像という感じで紐付ける。

# 素材:床
floor_mat = bpy.data.materials.new(""woodfloor"")
floor_mat.type = 'SURFACE'
floor_mat.use_raytrace = True
floor_mat.use_transparency = False
floor_tex = bpy.data.textures.new(""woodfloor"", type='IMAGE')
floor_tex.image = bpy.data.images.load(filepath='./wood-texture_00008.jpg')
floor_mat.texture_slots.add()
floor_mat.texture_slots[0].texture = floor_tex
floor.data.materials.append(bpy.data.materials['woodfloor'])

影を綺麗につけるのには、ハマってしまった。

まず、影を追加する素材側(ここでは床)のマテリアルの影オプションで、 「半透明影の受諾」を有効にする。これは必須。

問題は照明側で、環境照明や間接照明を組み合わせると計算に時間がかかるし、 バランスがとり難い。

環境照明と間接照明はOFFにして、代りに、ランプの種類を 「ポイント」ではなく「サン」に変更すると良い感じになる。 計算時間がそんなに延びないので、扱い易い。

pythonでの設定は、こんな感じ。

# Lamp
lamp = bpy.data.objects['Lamp']
lamp.data.energy = 5
lamp.data.type = 'SUN'
lamp.location = (50, 50, 100)
lamp.rotation_euler = (0, 0, 0)
lamp.data.shadow_method = 'RAY_SHADOW'

背景に模様を追加して、移り込みを再現する

pro.foto さんから格好良い部屋の素材を有り難く使わせて頂いて、 背景を室内風に変更。

# 背景追加
world = bpy.data.worlds['World']
world_tex = bpy.data.textures.new(name=""BGTexture"", type='IMAGE')
world_tex.image = bpy.data.images.load(filepath='./sit0037-054.jpg')
world = bpy.context.scene.world
slot = world.texture_slots.add()
slot.texture = world_tex
slot.use_map_horizon = True
slot.horizon_factor = 1.0

結構良い感じに仕上がったので、ここで作業終了です。

完成したのがコチラ。いやぁ、Blenderすごいな。

AccessoryCase6Normal.png

ポリゴンを自作のpythonで書いたので、形状の変更が簡単

ポリゴンを自作のpythonで書いているので、高さや パネルの個数を変更するのが簡単。

パネル7枚で、高さを増したのはコチラ。

AccessoryCase7Tall.png

ステンドグラスの設計図を作りたい。その前に

ステンドグラスの設計図を作る前に、ステンドグラスの頂点情報をPythonで作っておいた方が融通が効きそう。

綺麗に化粧直しして、ガラスっぽくレンダリングするのを Blenderでやってみたいと思う。

作った設計図の概要

  • 頂点と面情報をもった、ガラス板の集合
  • 高さと半径をパラメータにして、全体のサイズとアスペクト比を自動計算する
  • 円周方向の部品数をパラメータ化

今予め用意したのは、小物入れのポリゴンデータ

Blenderに期待している機能

  • pythonで別途自作した頂点情報と面情報の読み込み
  • 部品の嵌め合いと、半田(ステンドグラスの固定に使っている)の再現
  • 透明なガラス素材で、色の具合を確認したい
  • (今の図面は小物入れだけど)中に光源を入れて、ランプとしての出来上がりを見たい
  • 出来れば、まだらなガラスも試したい
  • 箱と蓋の嵌め合いを確認したい

まずはスケール合わせ

設計図の寸法はミリ単位で扱っているのだけれど、 Blenderの単位 BU(Blender Unit)とは標準的な数字の大きさが合わず、 そのままポリゴン表示すると画面に収まり切らない。

スケールを合わせる方法は、

  1. 単純にオブジェクトを縮小する
  2. 座標系をミリ単位にして、表示幅を設定する

1の方法は、 object.scale = (0.1, 0.1, 0.1) とすれば1/10になる。 こうしてBUに数字の大きさを合わせれば、表示のパラメータを調整する必要がない。 ただ、実際の寸法が変わってしまうと何かと不便。

2の方法をGUIで設定するには、 右側の「Scene」ウインドウの「Scene」タブの「単位」でメートル法を選んで、 拡大縮小を””1.0″”から””0.001″”にする。これでmm単位になる。

これをスクリプトで設定する方法は以下の通り。

bpy.context.scene.unit_settings.system='METRIC'
bpy.context.scene.unit_settings.scale_length = 0.001

これだけだと画面からはみ出してしまうので、 視点位置なども調整する必要がある。

3DViewのグリッドの調整

スケールをミリ単位にすると、グリッドが大き過ぎて目安にならない。 グリッドの方は、1cm単位にしよう。

for a in bpy.context.screen.areas:
    if a.type == 'VIEW_3D':
        bpy.types.SpaceView3D(a.spaces[0]).grid_lines = 30
        bpy.types.SpaceView3D(a.spaces[0]).grid_scale = 0.01

カメラと照明の位置が近すぎる

カメラと照明が、部品の内側に入ってしまったので、 位置を少し遠めに変更する。

こんな感じ。ついでに背景にも色をつけておくと見易い。

# Lamp
lamp = bpy.data.objects['Lamp']
lamp.location = (250, 250, 100)
lamp.rotation_euler = (0, 0, 0)
lamp.data.falloff_type = 'INVERSE_LINEAR'
lamp.data.shadow_method = 'NOSHADOW'

# Camera
camera = bpy.data.objects['Camera']
camera.location = (200, 0, 100)  # 100 = 10cm
camera.rotation_euler = (1.221, 0, 1.57)  # 70, 0, 90
camera.data.type = 'PERSP'
camera.data.angle = 0.7
camera.data.clip_start = 0
camera.data.clip_end = 1000

# Background
world = bpy.data.worlds['World']
world.horizon_color = (0.8, 0.8, 0.8)
world.zenith_color = (0.1, 0.1, 0.1)
world.use_sky_blend = True

全体がレンダリングされない

ミリスケールにすると、大きめの部品を作った場合にレンダリングされない部分が出てくる。

レンダリングする範囲をクリップしている設定を合わせてあげると良い。

# Camera
camera.data.clip_start = 0
camera.data.clip_end = 1000

作業中の 3DViewの視点が近すぎる (未解決)

GUIではマウスで簡単に操作出来るのだけれど、 スクリプトで変更する方法が見付からない。

スクリプトでレンダリングした結果を見る分には困らないので、 おいおい考えることにする。

とりあえず以下の様にすれば、オブジェクトが全部見える位置に移動できる。

# 3D View の視点操作
for area in bpy.context.screen.areas:
    if area.type == 'VIEW_3D':
        for region in area.regions:
            if region.type == 'WINDOW':
                override = {'area': area, 'region': region, 'edit_object': bpy.context.edit_object}
                bpy.ops.view3d.view_all(override)

あと、毎回出てくる画面、スプラッシュウィンドウを消す

毎回起動直後に出てくるBlenderの紹介?画面。 スクリプトで動かしている時には、邪魔でしかない。

あのウインドウの名前が分からなかったので、消すのに時間がかかった。(汗)

ファイル>ユーザー設定>インターフェース タブ の右下にある 「スプラッシュを表示」のチェックを外すと、今後表示されない。

これで幾分快適になった。

これまでの設定の後、さくっとレンダリングした結果はこんな感じ。

image.png

matplotlibで表示したのと、微妙に位置がずれていたり。 あんまりステンドグラスっぽく見えないのを、この後直していきたい。