Cycles: Add support for motion blur position

This adds an option to control at what time relative to the current frame
the shutter is fully opened. Supported options are:

- Shutter is starting to open at the current frame
- Shutter is fully opened at the current frame
- Shutter is fully closed  at the current frame

Custom shutter time offset is possible, same as custom curve for shutter
openness but those are considered nice things to have rather than something
crucial.

Reviewers: juicyfruit, dingto

Subscribers: venomgfx, hjalti

Differential Revision: https://developer.blender.org/D1380
This commit is contained in:
Sergey Sharybin 2015-06-29 17:40:13 +02:00
parent ccbf48330f
commit 5d3e07862c
7 changed files with 80 additions and 6 deletions

View File

@ -519,6 +519,18 @@ class CyclesRenderSettings(bpy.types.PropertyGroup):
min=0.0, max=5.0
)
cls.motion_blur_position = EnumProperty(
name="Motion Blur Position",
default='CENTER',
description="Specifies an offset for the shutters time interval "
"which allows to change the motion blur trails",
items=(
('START', "Start on Frame", "The shutter opens at the current frame"),
('CENTER', "Center on Frame", "The shutter is open during the current frame"),
('END', "End on Frame", "The shutter closes at the current frame"),
),
)
@classmethod
def unregister(cls):
del bpy.types.Scene.cycles

View File

@ -259,11 +259,14 @@ class CyclesRender_PT_motion_blur(CyclesButtonsPanel, Panel):
def draw(self, context):
layout = self.layout
rd = context.scene.render
scene = context.scene
cscene = scene.cycles
rd = scene.render
layout.active = rd.use_motion_blur
row = layout.row()
row.prop(rd, "motion_blur_shutter")
col = layout.column()
col.prop(cscene, "motion_blur_position", text="Position")
col.prop(rd, "motion_blur_shutter")
class CyclesRender_PT_film(CyclesButtonsPanel, Panel):

View File

@ -36,6 +36,7 @@ struct BlenderCamera {
float lens;
float shuttertime;
Camera::MotionPosition motion_position;
float aperturesize;
uint apertureblades;
@ -83,6 +84,7 @@ static void blender_camera_init(BlenderCamera *bcam, BL::RenderSettings b_render
bcam->sensor_height = 18.0f;
bcam->sensor_fit = BlenderCamera::AUTO;
bcam->shuttertime = 1.0f;
bcam->motion_position = Camera::MOTION_POSITION_CENTER;
bcam->border.right = 1.0f;
bcam->border.top = 1.0f;
bcam->pano_viewplane.right = 1.0f;
@ -409,6 +411,7 @@ static void blender_camera_sync(Camera *cam, BlenderCamera *bcam, int width, int
cam->shuttertime = bcam->shuttertime;
cam->fov_pre = cam->fov;
cam->fov_post = cam->fov;
cam->motion_position = bcam->motion_position;
/* border */
cam->border = bcam->border;
@ -431,6 +434,22 @@ void BlenderSync::sync_camera(BL::RenderSettings b_render, BL::Object b_override
bcam.pixelaspect.y = b_render.pixel_aspect_y();
bcam.shuttertime = b_render.motion_blur_shutter();
PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
switch(RNA_enum_get(&cscene, "motion_blur_position")) {
case 0:
bcam.motion_position = Camera::MOTION_POSITION_START;
break;
case 1:
bcam.motion_position = Camera::MOTION_POSITION_CENTER;
break;
case 2:
bcam.motion_position = Camera::MOTION_POSITION_END;
break;
default:
bcam.motion_position = Camera::MOTION_POSITION_CENTER;
break;
}
/* border */
if(b_render.use_border()) {
bcam.border.left = b_render.border_min_x();

View File

@ -685,6 +685,28 @@ void BlenderSync::sync_motion(BL::RenderSettings b_render,
Camera prevcam = *(scene->camera);
int frame_center = b_scene.frame_current();
float frame_center_delta = 0.0f;
if(scene->need_motion() != Scene::MOTION_PASS &&
scene->camera->motion_position != Camera::MOTION_POSITION_CENTER)
{
float shuttertime = scene->camera->shuttertime;
if(scene->camera->motion_position == Camera::MOTION_POSITION_END) {
frame_center_delta = -shuttertime * 0.5f;
}
else {
assert(scene->camera->motion_position == Camera::MOTION_POSITION_START);
frame_center_delta = shuttertime * 0.5f;
}
float time = frame_center + frame_center_delta;
int frame = (int)floorf(time);
float subframe = time - frame;
python_thread_state_restore(python_thread_state);
b_engine.frame_set(frame, subframe);
python_thread_state_save(python_thread_state);
sync_camera_motion(b_render, b_cam, width, height, 0.0f);
sync_objects(b_v3d, 0.0f);
}
/* always sample these times for camera motion */
motion_times.insert(-1.0f);
@ -704,7 +726,7 @@ void BlenderSync::sync_motion(BL::RenderSettings b_render,
shuttertime = scene->camera->shuttertime;
/* compute frame and subframe time */
float time = frame_center + relative_time * shuttertime * 0.5f;
float time = frame_center + frame_center_delta + relative_time * shuttertime * 0.5f;
int frame = (int)floorf(time);
float subframe = time - frame;

View File

@ -161,7 +161,12 @@ void BlenderSync::sync_data(BL::RenderSettings b_render,
mesh_synced.clear(); /* use for objects and motion sync */
sync_objects(b_v3d);
if(scene->need_motion() == Scene::MOTION_PASS ||
scene->need_motion() == Scene::MOTION_NONE ||
scene->camera->motion_position == Camera::MOTION_POSITION_CENTER)
{
sync_objects(b_v3d);
}
sync_motion(b_render,
b_v3d,
b_override,

View File

@ -29,6 +29,7 @@ CCL_NAMESPACE_BEGIN
Camera::Camera()
{
shuttertime = 1.0f;
motion_position = MOTION_POSITION_CENTER;
aperturesize = 0.0f;
focaldistance = 10.0f;

View File

@ -32,12 +32,24 @@ class Scene;
/* Camera
*
* The camera parameters are quite standard, tested to be both compatible with
* Renderman, and Blender after remapping. */
* Renderman, and Blender after remapping.
*/
class Camera {
public:
/* Specifies an offset for the shutter's time interval. */
enum MotionPosition {
/* Shutter opens at the current frame. */
MOTION_POSITION_START,
/* Shutter is fully open at the current frame. */
MOTION_POSITION_CENTER,
/* Shutter closes at the current frame. */
MOTION_POSITION_END,
};
/* motion blur */
float shuttertime;
MotionPosition motion_position;
/* depth of field */
float focaldistance;