![見出し画像](https://assets.st-note.com/production/uploads/images/157639826/rectangle_large_type_2_822496d33641f921c3b5274f10503eb1.png?width=1200)
Blenderで球体の中にHDR画像を貼り付けて、VRMとのアニメーションを作成
以下のような背景のあるアニメーションを作成する手順を紹介する。
(この手順で出力される背景は、3D的なオブジェクトではないので、複雑なことはできません。)
みはるが投稿
— kongo jun (@jun_kongo) October 5, 2024
AnimateDiff前 pic.twitter.com/uEs7IXIpN9
HDR画像を作成
以下の手順を参考に、HDR画像を作成する。
内側にHDR画像を貼り付けた球体を出力
以下のスクリプトをBlenderのスクリプトタブで実行する。
(実行手順も上記のQiita記事を参考にしてください。)
import bpy
import math
def create_hdri_sphere(hdri_path):
# 既存のオブジェクトをすべて削除
bpy.ops.object.select_all(action='SELECT')
bpy.ops.object.delete()
# 世界の背景設定
world = bpy.context.scene.world
world.use_nodes = True
node_tree = world.node_tree
node_tree.nodes.clear()
# テクスチャノードを追加
tex_node = node_tree.nodes.new(type='ShaderNodeTexEnvironment')
tex_node.image = bpy.data.images.load(hdri_path)
# 背景ノードを追加
background_node = node_tree.nodes.new(type='ShaderNodeBackground')
# ワールドアウトプットノードを追加
output_node = node_tree.nodes.new(type='ShaderNodeOutputWorld')
# ノードを接続
node_tree.links.new(tex_node.outputs['Color'], background_node.inputs['Color'])
node_tree.links.new(background_node.outputs['Background'], output_node.inputs['Surface'])
# 球体を作成
bpy.ops.mesh.primitive_uv_sphere_add(segments=64, ring_count=32, radius=10)
sphere = bpy.context.active_object
# マテリアルを作成
mat = bpy.data.materials.new(name="HDRI_Material")
mat.use_nodes = True
sphere.data.materials.append(mat)
# ノードを設定
nodes = mat.node_tree.nodes
nodes.clear()
# テクスチャノードを追加
tex_node = nodes.new(type='ShaderNodeTexEnvironment')
tex_node.image = bpy.data.images.load(hdri_path)
# エミッションノードを追加
emission_node = nodes.new(type='ShaderNodeEmission')
# マテリアルアウトプットノードを追加
output_node = nodes.new(type='ShaderNodeOutputMaterial')
# ノードを接続
links = mat.node_tree.links
links.new(tex_node.outputs['Color'], emission_node.inputs['Color'])
links.new(emission_node.outputs['Emission'], output_node.inputs['Surface'])
# UVマッピングを調整
bpy.ops.object.mode_set(mode='EDIT')
bpy.ops.mesh.select_all(action='SELECT')
bpy.ops.uv.sphere_project()
bpy.ops.object.mode_set(mode='OBJECT')
# HDRIファイルのパスを指定して関数を呼び出す
hdri_path = r"C:\Users\XXXXX\AAAAAA.hdr"
create_hdri_sphere(hdri_path)
出力される球体の内側。
![](https://assets.st-note.com/img/1728701199-TSgf9UeCjYrB7npmX15lwD3Z.png?width=1200)
出力される球体の外側。(わかりにくいで、下の画像の球体の内側は上の画像のような状態)
![](https://assets.st-note.com/img/1728701210-G2tfpVDYgIls01aeu953AWEF.png?width=1200)
BlenderにVRMをインポート
※こちらは以下の記事を参考にしてください。
![](https://assets.st-note.com/img/1728701304-BtCdx1Vyj3qGk90zNUhAwcK5.png?width=1200)
VRMの場所を修正
上記の手順通りにVRMをインポートすると、微妙な位置にモデルが出力されるため、以下のスクリプトをBlenderで実行し、モデルの位置とサイズを調整する。
import bpy
# アクティブなオブジェクト(選択されているVRMモデル)を取得
obj = bpy.context.active_object
if obj is not None:
# スケールを5に設定
obj.scale = (5, 5, 5)
# Z軸の位置を-10に設定
obj.location.z = -10
print(f"オブジェクト '{obj.name}' のスケールと位置を更新しました。")
else:
print("選択されているオブジェクトがありません。VRMモデルを選択してからスクリプトを実行してください。")
![](https://assets.st-note.com/img/1728701345-AtgvdQzJbofiNjHxV96lRLeY.png?width=1200)
(必要に応じて)モーションをインポート
以下の手順などで作成したVRMAをBlenderにインポートする。
アニメーションを作成
以下のスクリプトを実行し、アニメーションを作成する。(PCのスペック次第で、そこそこ時間がかかります。)
■モデルを斜め上から
import bpy
import math
import os
from datetime import datetime
# ユーザーが調整可能なパラメータ
distance_from_model = 9.0 # モデルからの距離
camera_height = -2.0 # カメラの高さ
camera_angle = 80.0 # カメラの角度(度単位)
output_path = r"C:\Users\XXXXX\output\"
# 解像度の指定
resolution_x = 1080 # 横解像度
resolution_y = 1920 # 縦解像度
# フレームレートと回転角度の指定
frame_rate = 30 # フレームレート(fps)
rotation_degrees = 360 # カメラの回転角度(度単位)
# 既存のカメラを削除
for obj in bpy.data.objects:
if obj.type == 'CAMERA':
bpy.data.objects.remove(obj, do_unlink=True)
# 新しいカメラを追加
bpy.ops.object.camera_add()
camera = bpy.context.object
camera.name = "RotatingCamera"
# カメラの角度をラジアンに変換
camera_angle_rad = math.radians(camera_angle)
# カメラの初期位置を設定
camera.location = (distance_from_model, 0, camera_height)
camera.rotation_euler = (camera_angle_rad, 0, math.pi / 2)
# 回転の中心となる空オブジェクトを原点に追加
bpy.ops.object.empty_add(type='PLAIN_AXES', location=(0, 0, 0))
pivot = bpy.context.object
pivot.name = "CameraPivot"
# カメラをピボットにペアレント設定
camera.parent = pivot
# シーンの設定
scene = bpy.context.scene
scene.frame_start = 1
scene.frame_end = 300 # アニメーションのフレーム数(例として10秒間のアニメーション)
# フレームレートを設定
scene.render.fps = frame_rate
# カメラを回転させるためのキーを設定
pivot.rotation_euler = (0, 0, 0)
pivot.keyframe_insert(data_path="rotation_euler", frame=scene.frame_start)
# 回転角度をラジアンに変換
rotation_radians = math.radians(rotation_degrees)
pivot.rotation_euler = (0, 0, rotation_radians)
pivot.keyframe_insert(data_path="rotation_euler", frame=scene.frame_end)
# 補間を線形に設定
for fcurve in pivot.animation_data.action.fcurves:
for keyframe in fcurve.keyframe_points:
keyframe.interpolation = 'LINEAR'
# タイムスタンプを生成
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
# レンダリング出力設定
scene.render.image_settings.file_format = 'FFMPEG'
scene.render.ffmpeg.format = 'MPEG4'
scene.render.filepath = os.path.join(output_path, f"animation_{timestamp}.mp4")
# 解像度を設定
scene.render.resolution_x = resolution_x
scene.render.resolution_y = resolution_y
scene.render.resolution_percentage = 100 # 解像度の割合(100%で指定した解像度)
# 出力ディレクトリが存在しない場合は作成
if not os.path.exists(output_path):
os.makedirs(output_path)
# カメラをアクティブカメラに設定
scene.camera = camera
# アニメーションをレンダリング
bpy.ops.render.render(animation=True)
■モデルを斜め下から
import bpy
import math
import os
from datetime import datetime
# ユーザーが調整可能なパラメータ
distance_from_model = 6.0 # モデルからの距離
camera_height = -7.0 # カメラの高さ
camera_angle = 110.0 # カメラの角度(度単位)
output_path = r"C:\Users\XXXXX\output\"
# 解像度の指定
resolution_x = 1080 # 横解像度
resolution_y = 1920 # 縦解像度
# フレームレートと回転角度の指定
frame_rate = 30 # フレームレート(fps)
rotation_degrees = 360 # カメラの回転角度(度単位)
# 既存のカメラを削除
for obj in bpy.data.objects:
if obj.type == 'CAMERA':
bpy.data.objects.remove(obj, do_unlink=True)
# 新しいカメラを追加
bpy.ops.object.camera_add()
camera = bpy.context.object
camera.name = "RotatingCamera"
# カメラの角度をラジアンに変換
camera_angle_rad = math.radians(camera_angle)
# カメラの初期位置を設定
camera.location = (distance_from_model, 0, camera_height)
camera.rotation_euler = (camera_angle_rad, 0, math.pi / 2)
# 回転の中心となる空オブジェクトを原点に追加
bpy.ops.object.empty_add(type='PLAIN_AXES', location=(0, 0, 0))
pivot = bpy.context.object
pivot.name = "CameraPivot"
# カメラをピボットにペアレント設定
camera.parent = pivot
# シーンの設定
scene = bpy.context.scene
scene.frame_start = 1
scene.frame_end = 300 # アニメーションのフレーム数(例として10秒間のアニメーション)
# フレームレートを設定
scene.render.fps = frame_rate
# カメラを回転させるためのキーを設定
pivot.rotation_euler = (0, 0, 0)
pivot.keyframe_insert(data_path="rotation_euler", frame=scene.frame_start)
# 回転角度をラジアンに変換
rotation_radians = math.radians(rotation_degrees)
pivot.rotation_euler = (0, 0, rotation_radians)
pivot.keyframe_insert(data_path="rotation_euler", frame=scene.frame_end)
# 補間を線形に設定
for fcurve in pivot.animation_data.action.fcurves:
for keyframe in fcurve.keyframe_points:
keyframe.interpolation = 'LINEAR'
# タイムスタンプを生成
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
# レンダリング出力設定
scene.render.image_settings.file_format = 'FFMPEG'
scene.render.ffmpeg.format = 'MPEG4'
scene.render.filepath = os.path.join(output_path, f"animation_{timestamp}.mp4")
# 解像度を設定
scene.render.resolution_x = resolution_x
scene.render.resolution_y = resolution_y
scene.render.resolution_percentage = 100 # 解像度の割合(100%で指定した解像度)
# 出力ディレクトリが存在しない場合は作成
if not os.path.exists(output_path):
os.makedirs(output_path)
# カメラをアクティブカメラに設定
scene.camera = camera
# アニメーションをレンダリング
bpy.ops.render.render(animation=True)
アウトプット
以下のようなアニメーションが作成される。
■モデルを斜め上から(速度だけいじってます。)
みはるが投稿
— kongo jun (@jun_kongo) October 4, 2024
背景のリアルさとVRoidの3D感に違和感マックス。
まー、AnimateDiffするので関係ないですが。 pic.twitter.com/9fenqmVhi0
■モデルを斜め下から
みはるが投稿
— kongo jun (@jun_kongo) October 5, 2024
AnimateDiff前 pic.twitter.com/uEs7IXIpN9
+α
AnimateDiffを使うと、3D感が緩和できます。
みはるが投稿
— kongo jun (@jun_kongo) October 5, 2024
AnimateDiffでリアル背景とVRoidを中和し切れず。
背景がリアルすぎるかなぁ。 pic.twitter.com/rbDVWb7l1S
みはるが投稿
— kongo jun (@jun_kongo) October 5, 2024
今回はわりと違和感ないかなぁ。
そもそもAnimateDiffする前から合成だから、構成としての違和感はあるけど、絵柄的な違和感はだいぶ減ったかなぁ。 pic.twitter.com/Ft4mz1N7CU