blender-cameras

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Blender Cameras

Blender 相机设置

Set up cameras with the same decisions a real cinematographer makes: focal length for feel, f-stop for focus, composition for storytelling.
像专业摄影师那样设置相机:根据画面氛围选择焦距,根据对焦需求设置光圈值,根据叙事需求设计构图。

Focal length cheat sheet

焦距速查表

LengthFeelUse
14–24mmVery wide, distortedArchitecture, claustrophobic interiors, exaggerated perspective
28–35mmWide, "documentary"Establishing shots, environments
50mmNeutral (≈ human eye)Default storytelling
85mmShort telephotoPortraits, character close-ups (flattering)
100–135mmTelephotoHero product shots, isolated subjects
200mm+Long teleWildlife, surveillance look, heavy compression
Quick rule: 85mm for intimacy, 24mm for spectacle, 50mm for neutral.
焦距范围画面风格适用场景
14–24mm超广角,带有畸变建筑摄影、压抑感室内场景、夸张透视效果
28–35mm广角,「纪录片风格」开场镜头、环境展示
50mm中性视角(近似人眼)默认叙事镜头
85mm中长焦肖像照、角色特写(效果更美观)
100–135mm长焦产品主角镜头、孤立主体拍摄
200mm+超长焦野生动物拍摄、监控视角、强压缩效果
快速规则:85mm用于营造亲密感,24mm用于宏大场景,50mm用于中性叙事。

Aperture / f-stop

光圈/光圈值(f-stop)

f-stopDoFUse
f/1.2–2.0Razor thinHero portraits, dreamy
f/2.8ShallowStandard portrait
f/4ModerateTwo subjects in frame
f/5.6–8Medium-deepGroup portraits, environments
f/11+Very deepLandscape, "everything sharp"
光圈值景深(DoF)适用场景
f/1.2–2.0极浅景深主角肖像、梦幻风格画面
f/2.8浅景深标准肖像照
f/4中等景深画面包含两个主体时
f/5.6–8中深景深群体肖像、环境场景
f/11+极深深景风景摄影、「全画面清晰」需求

Recipes

配置方案

Recipe 0 — Bbox-aware hero camera (preferred for orchestrator chains)

方案0 — 基于 bounding box 的主角相机(编排链优先推荐)

Use this when you have a specific subject. Computes the subject's bounding box, places camera at a distance that fits the subject in ~80% of the frame vertically, and aims via Track-To.
python
import bpy, math
from mathutils import Vector
当拍摄特定主体时使用本方案。计算主体的 bounding box,将相机放置在能让主体垂直占比约80%画面的距离处,并通过Track-To约束自动对准主体。
python
import bpy, math
from mathutils import Vector

Choose subject — all meshes named GEO-* by default, or pass a specific list

Choose subject — all meshes named GEO-* by default, or pass a specific list

subject_meshes = [o for o in bpy.data.objects if o.type == 'MESH' and o.name.startswith('GEO-')] if not subject_meshes: raise RuntimeError("No subject meshes found (looking for GEO- prefix)")
subject_meshes = [o for o in bpy.data.objects if o.type == 'MESH' and o.name.startswith('GEO-')] if not subject_meshes: raise RuntimeError("No subject meshes found (looking for GEO- prefix)")

World-space bbox

World-space bbox

deps = bpy.context.evaluated_depsgraph_get() all_verts = [] for o in subject_meshes: eo = o.evaluated_get(deps); em = eo.to_mesh() for v in em.vertices: all_verts.append(o.matrix_world @ v.co) eo.to_mesh_clear() xs = [v.x for v in all_verts]; ys = [v.y for v in all_verts]; zs = [v.z for v in all_verts] center = Vector(((min(xs)+max(xs))/2, (min(ys)+max(ys))/2, (min(zs)+max(zs))/2)) height = max(zs) - min(zs) width = max(xs) - min(xs) biggest = max(height, width)
deps = bpy.context.evaluated_depsgraph_get() all_verts = [] for o in subject_meshes: eo = o.evaluated_get(deps); em = eo.to_mesh() for v in em.vertices: all_verts.append(o.matrix_world @ v.co) eo.to_mesh_clear() xs = [v.x for v in all_verts]; ys = [v.y for v in all_verts]; zs = [v.z for v in all_verts] center = Vector(((min(xs)+max(xs))/2, (min(ys)+max(ys))/2, (min(zs)+max(zs))/2)) height = max(zs) - min(zs) width = max(xs) - min(xs) biggest = max(height, width)

Frame fit: at distance D, vertical frame = D × (sensor_h / focal). Solve for D.

Frame fit: at distance D, vertical frame = D × (sensor_h / focal). Solve for D.

focal_mm = 60 # 60mm gives a flattering not-too-wide hero shot sensor_h_mm = 24 # full-frame frame_per_meter = sensor_h_mm / focal_mm # 0.4 m vertical frame per metre of distance target_fill = 0.80 camera_distance = biggest / (frame_per_meter * target_fill)
focal_mm = 60 # 60mm gives a flattering not-too-wide hero shot sensor_h_mm = 24 # full-frame frame_per_meter = sensor_h_mm / focal_mm # 0.4 m vertical frame per metre of distance target_fill = 0.80 camera_distance = biggest / (frame_per_meter * target_fill)

Camera positioned in front (negative Y) with slight X offset for a 3/4 angle

Camera positioned in front (negative Y) with slight X offset for a 3/4 angle

cam_pos = Vector((center.x + camera_distance * 0.3, center.y - camera_distance, center.z))
cam_pos = Vector((center.x + camera_distance * 0.3, center.y - camera_distance, center.z))

Empty for tracking

Empty for tracking

empty_name = 'Empty-camera_target' empty = bpy.data.objects.get(empty_name) or bpy.data.objects.new(empty_name, None) if empty.name not in [o.name for o in bpy.context.collection.objects]: bpy.context.collection.objects.link(empty) empty.location = center
empty_name = 'Empty-camera_target' empty = bpy.data.objects.get(empty_name) or bpy.data.objects.new(empty_name, None) if empty.name not in [o.name for o in bpy.context.collection.objects]: bpy.context.collection.objects.link(empty) empty.location = center

Camera

Camera

cam_data = bpy.data.cameras.new('CAM-hero') cam_data.lens = focal_mm cam_data.dof.use_dof = True cam_data.dof.aperture_fstop = 4.0 cam_data.dof.focus_object = subject_meshes[0] # focus on first/main subject
cam = bpy.data.objects.new('CAM-hero', cam_data) bpy.context.collection.objects.link(cam) cam.location = cam_pos
track = cam.constraints.new('TRACK_TO') track.target = empty track.track_axis = 'TRACK_NEGATIVE_Z' track.up_axis = 'UP_Y'
bpy.context.scene.camera = cam print(f"camera:bbox_aware center={tuple(round(v,2) for v in center)} dist={camera_distance:.2f}m focal={focal_mm}mm")

For elongated vertical subjects (sword, flag, candle): biggest dimension is height; the framing math fits height to 80% of vertical frame, which is what you want.

For wide horizontal subjects (car, table): biggest is width; it fits width to 80% of vertical frame too which over-zooms — for those, swap to `frame_per_meter_h = (sensor_h_mm * aspect_ratio) / focal_mm` or adjust target_fill down.
cam_data = bpy.data.cameras.new('CAM-hero') cam_data.lens = focal_mm cam_data.dof.use_dof = True cam_data.dof.aperture_fstop = 4.0 cam_data.dof.focus_object = subject_meshes[0] # focus on first/main subject
cam = bpy.data.objects.new('CAM-hero', cam_data) bpy.context.collection.objects.link(cam) cam.location = cam_pos
track = cam.constraints.new('TRACK_TO') track.target = empty track.track_axis = 'TRACK_NEGATIVE_Z' track.up_axis = 'UP_Y'
bpy.context.scene.camera = cam print(f"camera:bbox_aware center={tuple(round(v,2) for v in center)} dist={camera_distance:.2f}m focal={focal_mm}mm")

对于细长型垂直主体(如剑、旗帜、蜡烛):最大维度为高度,取景计算会将高度适配为垂直画面的80%,符合需求。

对于宽幅水平主体(如汽车、桌子):最大维度为宽度,此时会将宽度适配为垂直画面的80%,导致画面过度放大——针对这类场景,可替换为`frame_per_meter_h = (sensor_h_mm * aspect_ratio) / focal_mm`或降低target_fill值。

Recipe 1 — Hero portrait camera (85mm + shallow DoF)

方案1 — 主角肖像相机(85mm + 浅景深)

python
import bpy, math

subject = bpy.data.objects.get('GEO-subject')   # change to your subject
python
import bpy, math

subject = bpy.data.objects.get('GEO-subject')   # change to your subject

Camera

Camera

cam_data = bpy.data.cameras.new('CAM-hero') cam = bpy.data.objects.new('CAM-hero', cam_data) bpy.context.collection.objects.link(cam) bpy.context.scene.camera = cam
cam.location = (3, -4, 1.6) cam_data.lens = 85 cam_data.sensor_width = 36
cam_data = bpy.data.cameras.new('CAM-hero') cam = bpy.data.objects.new('CAM-hero', cam_data) bpy.context.collection.objects.link(cam) bpy.context.scene.camera = cam
cam.location = (3, -4, 1.6) cam_data.lens = 85 cam_data.sensor_width = 36

Depth of field

Depth of field

cam_data.dof.use_dof = True cam_data.dof.aperture_fstop = 2.8 if subject: cam_data.dof.focus_object = subject
cam_data.dof.use_dof = True cam_data.dof.aperture_fstop = 2.8 if subject: cam_data.dof.focus_object = subject

Track-to constraint (auto-aim at subject)

Track-to constraint (auto-aim at subject)

if subject: track = cam.constraints.new('TRACK_TO') track.target = subject track.track_axis = 'TRACK_NEGATIVE_Z' track.up_axis = 'UP_Y'
print('camera:CAM-hero set')
undefined
if subject: track = cam.constraints.new('TRACK_TO') track.target = subject track.track_axis = 'TRACK_NEGATIVE_Z' track.up_axis = 'UP_Y'
print('camera:CAM-hero set')
undefined

Recipe 2 — Wide environmental establishing shot (24mm)

方案2 — 广角环境开场镜头(24mm)

python
import bpy, math

cam_data = bpy.data.cameras.new('CAM-establish')
cam = bpy.data.objects.new('CAM-establish', cam_data)
bpy.context.collection.objects.link(cam)
bpy.context.scene.camera = cam

cam.location = (8, -10, 2.5)
cam.rotation_euler = (math.radians(80), 0, math.radians(35))

cam_data.lens = 24
cam_data.sensor_width = 36
cam_data.dof.use_dof = False

print('camera:CAM-establish (24mm wide)')
python
import bpy, math

cam_data = bpy.data.cameras.new('CAM-establish')
cam = bpy.data.objects.new('CAM-establish', cam_data)
bpy.context.collection.objects.link(cam)
bpy.context.scene.camera = cam

cam.location = (8, -10, 2.5)
cam.rotation_euler = (math.radians(80), 0, math.radians(35))

cam_data.lens = 24
cam_data.sensor_width = 36
cam_data.dof.use_dof = False

print('camera:CAM-establish (24mm wide)')

Recipe 3 — Product hero (100mm + macro DoF)

方案3 — 产品主角镜头(100mm + 微距景深)

python
import bpy, math

subject = bpy.data.objects.get('GEO-product')

cam_data = bpy.data.cameras.new('CAM-product')
cam = bpy.data.objects.new('CAM-product', cam_data)
bpy.context.collection.objects.link(cam)
bpy.context.scene.camera = cam

cam.location = (0.4, -1.5, 0.2)   # close-in
cam_data.lens = 100
cam_data.sensor_width = 36
cam_data.dof.use_dof = True
cam_data.dof.aperture_fstop = 2.0
if subject:
    cam_data.dof.focus_object = subject

if subject:
    track = cam.constraints.new('TRACK_TO')
    track.target = subject
    track.track_axis = 'TRACK_NEGATIVE_Z'
    track.up_axis = 'UP_Y'

print('camera:CAM-product (100mm hero)')
python
import bpy, math

subject = bpy.data.objects.get('GEO-product')

cam_data = bpy.data.cameras.new('CAM-product')
cam = bpy.data.objects.new('CAM-product', cam_data)
bpy.context.collection.objects.link(cam)
bpy.context.scene.camera = cam

cam.location = (0.4, -1.5, 0.2)   # close-in
cam_data.lens = 100
cam_data.sensor_width = 36
cam_data.dof.use_dof = True
cam_data.dof.aperture_fstop = 2.0
if subject:
    cam_data.dof.focus_object = subject

if subject:
    track = cam.constraints.new('TRACK_TO')
    track.target = subject
    track.track_axis = 'TRACK_NEGATIVE_Z'
    track.up_axis = 'UP_Y'

print('camera:CAM-product (100mm hero)')

Recipe 4 — Composition guides (rule-of-thirds overlay)

方案4 — 构图辅助线(三分法叠加层)

python
import bpy

cam_data = bpy.data.cameras['CAM-hero']
cam_data.show_composition_thirds = True
cam_data.show_composition_golden = False
cam_data.show_composition_center = False
print('composition:thirds_on')
These overlays show in viewport only; no effect on render.
python
import bpy

cam_data = bpy.data.cameras['CAM-hero']
cam_data.show_composition_thirds = True
cam_data.show_composition_golden = False
cam_data.show_composition_center = False
print('composition:thirds_on')
这些叠加层仅在视图窗口中显示,不会影响渲染结果。

Recipe 5 — Orbit camera animation (10-second 360° turntable)

方案5 — 环绕相机动画(10秒360°转盘效果)

python
import bpy, math

target = bpy.data.objects.get('GEO-subject')
python
import bpy, math

target = bpy.data.objects.get('GEO-subject')

Empty as pivot

Empty as pivot

pivot = bpy.data.objects.new('Empty-orbit_pivot', None) bpy.context.collection.objects.link(pivot) if target: pivot.location = target.location
pivot = bpy.data.objects.new('Empty-orbit_pivot', None) bpy.context.collection.objects.link(pivot) if target: pivot.location = target.location

Camera child of pivot

Camera child of pivot

cam_data = bpy.data.cameras.new('CAM-orbit') cam = bpy.data.objects.new('CAM-orbit', cam_data) bpy.context.collection.objects.link(cam) cam.parent = pivot cam.location = (0, -5, 0.5) cam.rotation_euler = (math.radians(85), 0, 0) cam_data.lens = 50
bpy.context.scene.camera = cam
cam_data = bpy.data.cameras.new('CAM-orbit') cam = bpy.data.objects.new('CAM-orbit', cam_data) bpy.context.collection.objects.link(cam) cam.parent = pivot cam.location = (0, -5, 0.5) cam.rotation_euler = (math.radians(85), 0, 0) cam_data.lens = 50
bpy.context.scene.camera = cam

Animate pivot's Z rotation: 0 → 360° over frames 1..240 (10s @ 24fps)

Animate pivot's Z rotation: 0 → 360° over frames 1..240 (10s @ 24fps)

pivot.rotation_euler = (0, 0, 0) pivot.keyframe_insert('rotation_euler', frame=1) pivot.rotation_euler = (0, 0, math.radians(360)) pivot.keyframe_insert('rotation_euler', frame=240)
pivot.rotation_euler = (0, 0, 0) pivot.keyframe_insert('rotation_euler', frame=1) pivot.rotation_euler = (0, 0, math.radians(360)) pivot.keyframe_insert('rotation_euler', frame=240)

Set linear interpolation for constant orbit speed

Set linear interpolation for constant orbit speed

if pivot.animation_data and pivot.animation_data.action: for fc in pivot.animation_data.action.fcurves: for kp in fc.keyframe_points: kp.interpolation = 'LINEAR'
print('camera:CAM-orbit (10s turntable)')
undefined
if pivot.animation_data and pivot.animation_data.action: for fc in pivot.animation_data.action.fcurves: for kp in fc.keyframe_points: kp.interpolation = 'LINEAR'
print('camera:CAM-orbit (10s turntable)')
undefined

Recipe 6 — Push-in / dolly (camera moves forward, no zoom)

方案6 — 推进/推拉镜头(相机向前移动,无变焦)

python
import bpy

cam = bpy.data.objects['CAM-hero']
python
import bpy

cam = bpy.data.objects['CAM-hero']

Start position

Start position

cam.location = (3, -8, 1.6) cam.keyframe_insert('location', frame=1)
cam.location = (3, -8, 1.6) cam.keyframe_insert('location', frame=1)

End position (closer to subject)

End position (closer to subject)

cam.location = (3, -4, 1.6) cam.keyframe_insert('location', frame=120) print('camera:dolly_5s')

A push-in (physical move forward) is visually distinct from a zoom (focal length change). Use push-ins for cinematic feel, zooms for surveillance/news look.
cam.location = (3, -4, 1.6) cam.keyframe_insert('location', frame=120) print('camera:dolly_5s')

推进镜头(物理向前移动)与变焦镜头(焦距变化)视觉效果截然不同。推进镜头用于营造电影感,变焦镜头适用于监控/新闻风格画面。

Composition rules — enforce via positioning

构图规则——通过机位设置实现

  1. Rule of thirds: place the subject at one of the 4 intersection points, not center.
  2. Headroom: leave ~10% empty above the head.
  3. Nose room: if subject faces left, leave space on the left for them to "look into".
  4. Foreground/midground/background: three depth layers feel more cinematic.
  1. 三分法:将主体放置在4个交叉点之一,而非画面中心。
  2. 头部空间:在主体头部上方留出约10%的空白区域。
  3. 视线空间:若主体面朝左侧,需在左侧留出空间供其「看向」。
  4. 前景/中景/背景:三层景深会让画面更具电影感。

Sensor sizes

传感器尺寸

SensorWidth (mm)Notes
Full frame DSLR / 35mm cinema36Default
APS-C22.51.5–1.6× crop
Super 3524.89Most cinema
Micro Four Thirds17.3Mirrorless
iPhone 15 Pro9.8Smartphone reference
Set with
cam_data.sensor_width = 36
.
传感器类型宽度(mm)说明
全画幅DSLR / 35mm电影机36默认设置
APS-C22.51.5–1.6倍裁切
Super 3524.89主流电影机规格
Micro Four Thirds17.3无反相机规格
iPhone 15 Pro9.8智能手机参考
可通过
cam_data.sensor_width = 36
设置。

Common pitfalls

常见问题

SymptomFix
Distorted face on portraitUse 50mm+ for human subjects
Subject blurred, background sharpSet
dof.focus_object
to the subject
Camera dead-center on subjectApply rule of thirds; offset subject
Orbit camera tilts wildlyUse Track-To constraint, not manual rotation
Camera below ground in animationAdd Floor constraint or check Z keyframes
DoF very slow in CyclesAcceptable for finals; viewport may use simpler approximation
问题表现解决方法
肖像画面中面部畸变拍摄人物主体时使用50mm及以上焦距
主体模糊、背景清晰
dof.focus_object
设置为主体
相机正对主体中心应用三分法,偏移主体位置
环绕相机画面剧烈倾斜使用Track-To约束,而非手动旋转
动画中相机穿模到地面以下添加地面约束或检查Z轴关键帧
Cycles渲染中景深效果速度极慢最终渲染可接受;视图窗口可使用简化近似效果

When to load
references/overview.md

何时加载
references/overview.md

Load when:
  • Cinematic effects beyond defaults: anamorphic, lens flares, vignette
  • Multi-camera scenes (camera markers for editing)
  • Camera shake / handheld noise
  • Stereo / VR camera setup
The reference covers: full focal length theory, aperture/f-stop tables, composition guides, sensor variants for matching real cameras (iPhone, cinema, DSLR), animated camera patterns, cinematic effects.
在以下场景加载:
  • 超出默认设置的电影级效果:变形镜头、镜头光晕、暗角
  • 多相机场景(用于剪辑的相机标记)
  • 相机抖动/手持拍摄噪点
  • 立体/VR相机设置
该参考文档涵盖:完整焦距理论、光圈/光圈值表格、构图辅助线、匹配真实相机的传感器变体(iPhone、电影机、DSLR)、动画相机模式、电影级效果。