AI が 1 文から書いた 5 秒のアニメ: 夜明けの紙の舟(120 コマ、EEVEE、MP4)。本番の GPU で描いた本物の結果と、そのまま動く bpy スクリプト、設定、GPU 秒。スクリプトの URL を scene_url に渡せば同じものが出ます。
| 頼んだ文 | 5 秒の Blender アニメを作って: 夜明けの穏やかな水面を、折り紙の舟がゆっくり揺れながら流れていく。(AI が https://render.janction.jp/samples/ex23_paper_boat.py を書き、1〜120 コマを EEVEE の 720p で MP4 に) |
|---|---|
| MCP の呼び出し | render_final(scene_url="https://render.janction.jp/samples/ex23_paper_boat.py", frame_start=1, frame_end=120, width=1280, height=720, samples=64, engine="eevee", output="mp4", fps=24) |
| GPU 秒 / 往復 | 138.2 s / 39 s |
| 料金の目安(0.1 円/GPU 秒) | 13.8 JPY (無料の残りの中なら 0 円) |
| 描いた日 | 2026-10-20 |
| Blender | 5.0 |
ChatGPT · Claude · Grok · Perplexity
JANCTION Render(MCP サーバー https://render.janction.jp/mcp)で、この作例を描いて: render_preview(scene_url="https://render.janction.jp/samples/ex23_paper_boat.py")。そのあと、私の題材に合わせて色・形・カメラを変える案を出して。仕上げの前に確認して。
リンクを押すと、下の文が入った状態でそのアプリが開きます(入らないときは写して貼ってください)。そのアプリに JANCTION Render をまだつないでいなければ、先にコネクタとして https://render.janction.jp/mcp を足してください。
| frame_start | 1 |
|---|---|
| frame_end | 120 |
| width | 1280 |
| height | 720 |
| samples | 64 |
| denoise | True |
| engine | eevee |
| output | mp4 |
| fps | 24 |
ex23_paper_boat.py。シーン・カメラ・コマ範囲だけを組み、解像度・サンプル・ノイズ除去・GPU はサービスが決めます。
"""JANCTION Render example 23: a 5-second animation an AI wrote from one sentence (a paper boat at dawn).
The request was: "Make a 5-second Blender animation: a folded paper boat drifting across calm water at dawn,
bobbing gently." Claude wrote this script (no files, no add-ons) and JANCTION rendered it.
Reproduce: render_final(scene_url="https://render.janction.jp/samples/ex23_paper_boat.py",
frame_start=1, frame_end=120, width=1280, height=720, engine="eevee", output="mp4", fps=24)
Everything is built from primitives: the water is a grid with two Wave modifiers, the boat is a few faces.
"""
import math
import bmesh
import bpy
for ob in list(bpy.data.objects):
bpy.data.objects.remove(ob, do_unlink=True)
scene = bpy.context.scene
scene.frame_start, scene.frame_end = 1, 120
scene.render.fps = 24
def principled(name, color, roughness, metallic=0.0, transmission=0.0):
m = bpy.data.materials.new(name)
m.use_nodes = True
b = next(n for n in m.node_tree.nodes if n.type == "BSDF_PRINCIPLED")
b.inputs["Base Color"].default_value = (*color, 1.0)
b.inputs["Roughness"].default_value = roughness
b.inputs["Metallic"].default_value = metallic
for key in ("Transmission Weight", "Transmission"):
if key in b.inputs:
b.inputs[key].default_value = transmission
break
return m
# water: a fine grid with a slow Wave modifier (animated by the frame number)
bpy.ops.mesh.primitive_grid_add(x_subdivisions=160, y_subdivisions=160, size=40, location=(0, 0, 0))
water = bpy.context.active_object
water.name = "Water"
wave = water.modifiers.new("Wave", "WAVE")
wave.height = 0.05
wave.width = 0.7
wave.narrowness = 1.2
wave.speed = 0.05
wave.start_position_x = -30.0 # a far-away centre: the rings arrive as long, nearly straight swells
wave.use_normal = False
swell = water.modifiers.new("Swell", "WAVE")
swell.height = 0.02
swell.width = 0.5
swell.speed = 0.03
swell.start_position_x, swell.start_position_y = 18.0, 25.0
bpy.ops.object.shade_smooth()
water.data.materials.append(principled("Water", (0.012, 0.03, 0.05), 0.12)) # dark and glossy: it mirrors the sky
# paper boat: a hull (an upside-down trapezoid prism) and a triangular sail, built from vertices
bm = bmesh.new()
top_l, bot_l, top_w, bot_w, h = 0.70, 0.42, 0.18, 0.06, 0.22
v = [bm.verts.new(p) for p in [
(-top_l, -top_w, h), (top_l, -top_w, h), (top_l, top_w, h), (-top_l, top_w, h), # rim
(-bot_l, -bot_w, 0.0), (bot_l, -bot_w, 0.0), (bot_l, bot_w, 0.0), (-bot_l, bot_w, 0.0), # keel
]]
for f in ([0, 1, 5, 4], [1, 2, 6, 5], [2, 3, 7, 6], [3, 0, 4, 7], [4, 5, 6, 7]):
bm.faces.new([v[i] for i in f])
s = [bm.verts.new(p) for p in [(-0.34, 0.0, h), (0.34, 0.0, h), (0.0, 0.0, h + 0.55)]]
bm.faces.new(s)
me = bpy.data.meshes.new("PaperBoat")
bm.to_mesh(me)
bm.free()
boat = bpy.data.objects.new("PaperBoat", me)
scene.collection.objects.link(boat)
solid = boat.modifiers.new("Paper", "SOLIDIFY")
solid.thickness = 0.008
boat.data.materials.append(principled("Paper", (0.95, 0.93, 0.88), 0.6))
boat.scale = (0.9, 0.9, 0.9)
# drift from left to right and bob on the swell (keyframes every 6 frames)
for f in range(1, 121, 6):
t = (f - 1) / 119.0
boat.location = (-3.2 + 6.4 * t, 0.2 * math.sin(t * math.pi), 0.02 + 0.035 * math.sin(f / 9.0))
boat.rotation_euler = (0.06 * math.sin(f / 11.0), 0.05 * math.sin(f / 7.0 + 1.0), math.radians(8) * math.sin(t * math.pi))
boat.keyframe_insert("location", frame=f)
boat.keyframe_insert("rotation_euler", frame=f)
# dawn: a low warm sun from the camera's left and a sky that goes from orange at the horizon to deep blue overhead
sun_data = bpy.data.lights.new("Sun", "SUN")
sun_data.energy = 4.0
sun_data.color = (1.0, 0.66, 0.42)
sun_data.angle = math.radians(2)
sun = bpy.data.objects.new("Sun", sun_data)
scene.collection.objects.link(sun)
sun.rotation_euler = (math.radians(72), 0.0, math.radians(-40))
world = scene.world or bpy.data.worlds.new("World")
scene.world = world
world.use_nodes = True
nt = world.node_tree
bg = next(n for n in nt.nodes if n.type == "BACKGROUND")
coord = nt.nodes.new("ShaderNodeTexCoord")
xyz = nt.nodes.new("ShaderNodeSeparateXYZ")
ramp = nt.nodes.new("ShaderNodeValToRGB")
nt.links.new(coord.outputs["Generated"], xyz.inputs[0])
nt.links.new(xyz.outputs["Z"], ramp.inputs["Fac"])
nt.links.new(ramp.outputs["Color"], bg.inputs["Color"])
stops = ramp.color_ramp.elements
stops[0].position, stops[0].color = 0.0, (1.0, 0.55, 0.30, 1.0) # horizon (Generated Z of the world is the view direction, 0 at the horizon)
stops[1].position, stops[1].color = 0.30, (0.08, 0.12, 0.30, 1.0) # overhead
mid = stops.new(0.07)
mid.color = (0.92, 0.45, 0.42, 1.0) # pink band above the horizon
bg.inputs["Strength"].default_value = 0.9
# camera: low over the water, panning slowly after the boat (it tracks a point that moves at half the boat's speed)
aim = bpy.data.objects.new("Aim", None)
scene.collection.objects.link(aim)
for f in (1, 120):
aim.location = (-1.6 + 3.2 * (f - 1) / 119.0, 0.0, 0.25)
aim.keyframe_insert("location", frame=f)
cam = bpy.data.objects.new("Camera", bpy.data.cameras.new("Camera"))
scene.collection.objects.link(cam)
scene.camera = cam
cam.data.lens = 40
cam.location = (0.0, -6.0, 0.75)
track = cam.constraints.new("TRACK_TO")
track.target = aim
track.track_axis = "TRACK_NEGATIVE_Z"
track.up_axis = "UP_Y"
JANCTION Render v0.4.152 · JasmyLab Inc. · 更新 2026-10-14 · 検証 Blender 3.6 / 4.2 / 4.5 / 5.0 / 5.2, JANCTION Render 0.4.152 · English