Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/intern
diff options
context:
space:
mode:
authorSergey Sharybin <sergey.vfx@gmail.com>2015-07-21 16:36:35 +0300
committerSergey Sharybin <sergey.vfx@gmail.com>2015-07-21 18:40:03 +0300
commitdc3563ff4801907ec8cd21a1589f0cb56d021a8f (patch)
tree88743d23f009deb1d3a3cc379ba1d67f5116a91e /intern
parent1df42798d46d031c7666a75b47faa0d20fc965ef (diff)
Cycles: Implement camera zoom motion blur
Works totally similar to camera motion blur and majority of the changes are related on just passing extra arguments to sync() functions. Couple of things still to look into: - Motion pass will not include motion caused by the zoom. - Only perspective cameras are supported currently. - Motion is being interpolated on projected coordinates, which might give different results from constructing projection matrix from interpolated field of view. This could be good enough for us, but we need to consider improving this at some point. Reviewers: juicyfruit, dingto Reviewed By: dingto Differential Revision: https://developer.blender.org/D1383
Diffstat (limited to 'intern')
-rw-r--r--intern/cycles/blender/blender_camera.cpp102
-rw-r--r--intern/cycles/blender/blender_object.cpp17
-rw-r--r--intern/cycles/blender/blender_session.cpp28
-rw-r--r--intern/cycles/blender/blender_sync.cpp13
-rw-r--r--intern/cycles/blender/blender_sync.h18
-rw-r--r--intern/cycles/kernel/kernel_camera.h25
-rw-r--r--intern/cycles/kernel/kernel_types.h8
-rw-r--r--intern/cycles/render/camera.cpp24
-rw-r--r--intern/cycles/render/camera.h4
-rw-r--r--intern/cycles/util/util_transform.h5
10 files changed, 202 insertions, 42 deletions
diff --git a/intern/cycles/blender/blender_camera.cpp b/intern/cycles/blender/blender_camera.cpp
index 90b42ea4ec2..18e9aa8bc17 100644
--- a/intern/cycles/blender/blender_camera.cpp
+++ b/intern/cycles/blender/blender_camera.cpp
@@ -244,8 +244,11 @@ static Transform blender_camera_matrix(const Transform& tfm,
return transform_clear_scale(result);
}
-static void blender_camera_viewplane(BlenderCamera *bcam, int width, int height,
- BoundBox2D *viewplane, float *aspectratio, float *sensor_size)
+static void blender_camera_viewplane(BlenderCamera *bcam,
+ int width, int height,
+ BoundBox2D *viewplane,
+ float *aspectratio,
+ float *sensor_size)
{
/* dimensions */
float xratio = (float)width*bcam->pixelaspect.x;
@@ -258,24 +261,34 @@ static void blender_camera_viewplane(BlenderCamera *bcam, int width, int height,
/* sensor fitting */
if(bcam->sensor_fit == BlenderCamera::AUTO) {
horizontal_fit = (xratio > yratio);
- *sensor_size = bcam->sensor_width;
+ if(sensor_size != NULL) {
+ *sensor_size = bcam->sensor_width;
+ }
}
else if(bcam->sensor_fit == BlenderCamera::HORIZONTAL) {
horizontal_fit = true;
- *sensor_size = bcam->sensor_width;
+ if(sensor_size != NULL) {
+ *sensor_size = bcam->sensor_width;
+ }
}
else {
horizontal_fit = false;
- *sensor_size = bcam->sensor_height;
+ if(sensor_size != NULL) {
+ *sensor_size = bcam->sensor_height;
+ }
}
if(horizontal_fit) {
- *aspectratio = xratio/yratio;
+ if(aspectratio != NULL) {
+ *aspectratio = xratio/yratio;
+ }
xaspect = *aspectratio;
yaspect = 1.0f;
}
else {
- *aspectratio = yratio/xratio;
+ if(aspectratio != NULL) {
+ *aspectratio = yratio/xratio;
+ }
xaspect = 1.0f;
yaspect = *aspectratio;
}
@@ -284,31 +297,37 @@ static void blender_camera_viewplane(BlenderCamera *bcam, int width, int height,
if(bcam->type == CAMERA_ORTHOGRAPHIC) {
xaspect = xaspect*bcam->ortho_scale/(*aspectratio*2.0f);
yaspect = yaspect*bcam->ortho_scale/(*aspectratio*2.0f);
- *aspectratio = bcam->ortho_scale/2.0f;
+ if(aspectratio != NULL) {
+ *aspectratio = bcam->ortho_scale/2.0f;
+ }
}
if(bcam->type == CAMERA_PANORAMA) {
/* set viewplane */
- *viewplane = bcam->pano_viewplane;
+ if(viewplane != NULL) {
+ *viewplane = bcam->pano_viewplane;
+ }
}
else {
/* set viewplane */
- viewplane->left = -xaspect;
- viewplane->right = xaspect;
- viewplane->bottom = -yaspect;
- viewplane->top = yaspect;
-
- /* zoom for 3d camera view */
- *viewplane = (*viewplane) * bcam->zoom;
-
- /* modify viewplane with camera shift and 3d camera view offset */
- float dx = 2.0f*(*aspectratio*bcam->shift.x + bcam->offset.x*xaspect*2.0f);
- float dy = 2.0f*(*aspectratio*bcam->shift.y + bcam->offset.y*yaspect*2.0f);
-
- viewplane->left += dx;
- viewplane->right += dx;
- viewplane->bottom += dy;
- viewplane->top += dy;
+ if(viewplane != NULL) {
+ viewplane->left = -xaspect;
+ viewplane->right = xaspect;
+ viewplane->bottom = -yaspect;
+ viewplane->top = yaspect;
+
+ /* zoom for 3d camera view */
+ *viewplane = (*viewplane) * bcam->zoom;
+
+ /* modify viewplane with camera shift and 3d camera view offset */
+ float dx = 2.0f*(*aspectratio*bcam->shift.x + bcam->offset.x*xaspect*2.0f);
+ float dy = 2.0f*(*aspectratio*bcam->shift.y + bcam->offset.y*yaspect*2.0f);
+
+ viewplane->left += dx;
+ viewplane->right += dx;
+ viewplane->bottom += dy;
+ viewplane->top += dy;
+ }
}
}
@@ -386,7 +405,10 @@ static void blender_camera_sync(Camera *cam, BlenderCamera *bcam, int width, int
cam->motion.pre = cam->matrix;
cam->motion.post = cam->matrix;
cam->use_motion = false;
+ cam->use_perspective_motion = false;
cam->shuttertime = bcam->shuttertime;
+ cam->fov_pre = cam->fov;
+ cam->fov_post = cam->fov;
/* border */
cam->border = bcam->border;
@@ -435,7 +457,10 @@ void BlenderSync::sync_camera(BL::RenderSettings b_render, BL::Object b_override
blender_camera_sync(cam, &bcam, width, height);
}
-void BlenderSync::sync_camera_motion(BL::Object b_ob, float motion_time)
+void BlenderSync::sync_camera_motion(BL::RenderSettings b_render,
+ BL::Object b_ob,
+ int width, int height,
+ float motion_time)
{
Camera *cam = scene->camera;
BL::Array<float, 16> b_ob_matrix;
@@ -454,6 +479,31 @@ void BlenderSync::sync_camera_motion(BL::Object b_ob, float motion_time)
cam->use_motion = true;
}
}
+
+ if(cam->type == CAMERA_PERSPECTIVE) {
+ BlenderCamera bcam;
+ float aspectratio, sensor_size;
+ blender_camera_init(&bcam, b_render);
+ blender_camera_from_object(&bcam, b_engine, b_ob);
+ blender_camera_viewplane(&bcam,
+ width, height,
+ NULL,
+ &aspectratio,
+ &sensor_size);
+ /* TODO(sergey): De-duplicate calculation with camera sync. */
+ float fov = 2.0f * atanf((0.5f * sensor_size) / bcam.lens / aspectratio);
+ if(fov != cam->fov) {
+ VLOG(1) << "Camera " << b_ob.name() << " FOV change detected.";
+ if(motion_time == -1.0f) {
+ cam->fov_pre = fov;
+ cam->use_perspective_motion = true;
+ }
+ else if(motion_time == 1.0f) {
+ cam->fov_post = fov;
+ cam->use_perspective_motion = true;
+ }
+ }
+ }
}
/* Sync 3D View Camera */
diff --git a/intern/cycles/blender/blender_object.cpp b/intern/cycles/blender/blender_object.cpp
index 35ba450be41..432c4aaa078 100644
--- a/intern/cycles/blender/blender_object.cpp
+++ b/intern/cycles/blender/blender_object.cpp
@@ -659,7 +659,11 @@ void BlenderSync::sync_objects(BL::SpaceView3D b_v3d, float motion_time)
mesh_motion_synced.clear();
}
-void BlenderSync::sync_motion(BL::SpaceView3D b_v3d, BL::Object b_override, void **python_thread_state)
+void BlenderSync::sync_motion(BL::RenderSettings b_render,
+ BL::SpaceView3D b_v3d,
+ BL::Object b_override,
+ int width, int height,
+ void **python_thread_state)
{
if(scene->need_motion() == Scene::MOTION_NONE)
return;
@@ -679,6 +683,9 @@ void BlenderSync::sync_motion(BL::SpaceView3D b_v3d, BL::Object b_override, void
/* note iteration over motion_times set happens in sorted order */
foreach(float relative_time, motion_times) {
+ VLOG(1) << "Synchronizing motion for the relative time "
+ << relative_time << ".";
+
/* fixed shutter time to get previous and next frame for motion pass */
float shuttertime;
@@ -698,8 +705,12 @@ void BlenderSync::sync_motion(BL::SpaceView3D b_v3d, BL::Object b_override, void
python_thread_state_save(python_thread_state);
/* sync camera, only supports two times at the moment */
- if(relative_time == -1.0f || relative_time == 1.0f)
- sync_camera_motion(b_cam, relative_time);
+ if(relative_time == -1.0f || relative_time == 1.0f) {
+ sync_camera_motion(b_render,
+ b_cam,
+ width, height,
+ relative_time);
+ }
/* sync object */
sync_objects(b_v3d, relative_time);
diff --git a/intern/cycles/blender/blender_session.cpp b/intern/cycles/blender/blender_session.cpp
index e1d5e1310d5..8903801d38d 100644
--- a/intern/cycles/blender/blender_session.cpp
+++ b/intern/cycles/blender/blender_session.cpp
@@ -122,7 +122,12 @@ void BlenderSession::create_session()
if(session_pause == false) {
/* full data sync */
sync->sync_view(b_v3d, b_rv3d, width, height);
- sync->sync_data(b_v3d, b_engine.camera_override(), &python_thread_state);
+ sync->sync_data(b_render,
+ b_v3d,
+ b_engine.camera_override(),
+ width, height,
+ &python_thread_state,
+ b_rlay_name.c_str());
}
}
else {
@@ -477,7 +482,12 @@ void BlenderSession::render()
/* update scene */
sync->sync_camera(b_render, b_engine.camera_override(), width, height);
- sync->sync_data(b_v3d, b_engine.camera_override(), &python_thread_state, b_rlay_name.c_str());
+ sync->sync_data(b_render,
+ b_v3d,
+ b_engine.camera_override(),
+ width, height,
+ &python_thread_state,
+ b_rlay_name.c_str());
/* update number of samples per layer */
int samples = sync->get_layer_samples();
@@ -570,7 +580,12 @@ void BlenderSession::bake(BL::Object b_object, const string& pass_type, const in
/* update scene */
sync->sync_camera(b_render, b_engine.camera_override(), width, height);
- sync->sync_data(b_v3d, b_engine.camera_override(), &python_thread_state);
+ sync->sync_data(b_render,
+ b_v3d,
+ b_engine.camera_override(),
+ width, height,
+ &python_thread_state,
+ b_rlay_name.c_str());
/* get buffer parameters */
SessionParams session_params = BlenderSync::get_session_params(b_engine, b_userpref, b_scene, background);
@@ -712,7 +727,12 @@ void BlenderSession::synchronize()
}
/* data and camera synchronize */
- sync->sync_data(b_v3d, b_engine.camera_override(), &python_thread_state);
+ sync->sync_data(b_render,
+ b_v3d,
+ b_engine.camera_override(),
+ width, height,
+ &python_thread_state,
+ b_rlay_name.c_str());
if(b_rv3d)
sync->sync_view(b_v3d, b_rv3d, width, height);
diff --git a/intern/cycles/blender/blender_sync.cpp b/intern/cycles/blender/blender_sync.cpp
index c5fb7925306..8888d219aac 100644
--- a/intern/cycles/blender/blender_sync.cpp
+++ b/intern/cycles/blender/blender_sync.cpp
@@ -145,7 +145,12 @@ bool BlenderSync::sync_recalc()
return recalc;
}
-void BlenderSync::sync_data(BL::SpaceView3D b_v3d, BL::Object b_override, void **python_thread_state, const char *layer)
+void BlenderSync::sync_data(BL::RenderSettings b_render,
+ BL::SpaceView3D b_v3d,
+ BL::Object b_override,
+ int width, int height,
+ void **python_thread_state,
+ const char *layer)
{
sync_render_layers(b_v3d, layer);
sync_integrator();
@@ -157,7 +162,11 @@ void BlenderSync::sync_data(BL::SpaceView3D b_v3d, BL::Object b_override, void *
mesh_synced.clear(); /* use for objects and motion sync */
sync_objects(b_v3d);
- sync_motion(b_v3d, b_override, python_thread_state);
+ sync_motion(b_render,
+ b_v3d,
+ b_override,
+ width, height,
+ python_thread_state);
mesh_synced.clear();
}
diff --git a/intern/cycles/blender/blender_sync.h b/intern/cycles/blender/blender_sync.h
index b8bd14c0f71..efc6ae94542 100644
--- a/intern/cycles/blender/blender_sync.h
+++ b/intern/cycles/blender/blender_sync.h
@@ -53,7 +53,12 @@ public:
/* sync */
bool sync_recalc();
- void sync_data(BL::SpaceView3D b_v3d, BL::Object b_override, void **python_thread_state, const char *layer = 0);
+ void sync_data(BL::RenderSettings b_render,
+ BL::SpaceView3D b_v3d,
+ BL::Object b_override,
+ int width, int height,
+ void **python_thread_state,
+ const char *layer = 0);
void sync_render_layers(BL::SpaceView3D b_v3d, const char *layer);
void sync_integrator();
void sync_camera(BL::RenderSettings b_render, BL::Object b_override, int width, int height);
@@ -75,7 +80,11 @@ private:
void sync_lamps(bool update_all);
void sync_materials(bool update_all);
void sync_objects(BL::SpaceView3D b_v3d, float motion_time = 0.0f);
- void sync_motion(BL::SpaceView3D b_v3d, BL::Object b_override, void **python_thread_state);
+ void sync_motion(BL::RenderSettings b_render,
+ BL::SpaceView3D b_v3d,
+ BL::Object b_override,
+ int width, int height,
+ void **python_thread_state);
void sync_film();
void sync_view();
void sync_world(bool update_all);
@@ -98,7 +107,10 @@ private:
void sync_light(BL::Object b_parent, int persistent_id[OBJECT_PERSISTENT_ID_SIZE], BL::Object b_ob, Transform& tfm, bool *use_portal);
void sync_background_light(bool use_portal);
void sync_mesh_motion(BL::Object b_ob, Object *object, float motion_time);
- void sync_camera_motion(BL::Object b_ob, float motion_time);
+ void sync_camera_motion(BL::RenderSettings b_render,
+ BL::Object b_ob,
+ int width, int height,
+ float motion_time);
/* particles */
bool sync_dupli_particle(BL::Object b_ob, BL::DupliObject b_dup, Object *object);
diff --git a/intern/cycles/kernel/kernel_camera.h b/intern/cycles/kernel/kernel_camera.h
index 3ce5134181a..67651f96544 100644
--- a/intern/cycles/kernel/kernel_camera.h
+++ b/intern/cycles/kernel/kernel_camera.h
@@ -43,7 +43,30 @@ ccl_device void camera_sample_perspective(KernelGlobals *kg, float raster_x, flo
{
/* create ray form raster position */
Transform rastertocamera = kernel_data.cam.rastertocamera;
- float3 Pcamera = transform_perspective(&rastertocamera, make_float3(raster_x, raster_y, 0.0f));
+ float3 raster = make_float3(raster_x, raster_y, 0.0f);
+ float3 Pcamera = transform_perspective(&rastertocamera, raster);
+
+#ifdef __CAMERA_MOTION__
+ if(kernel_data.cam.have_perspective_motion) {
+ /* TODO(sergey): Currently we interpolate projected coordinate which
+ * gives nice looking result and which is simple, but is in fact a bit
+ * different comparing to constructing projective matrix from an
+ * interpolated field of view.
+ */
+ if(ray->time < 0.5f) {
+ Transform rastertocamera_pre = kernel_data.cam.perspective_motion.pre;
+ float3 Pcamera_pre =
+ transform_perspective(&rastertocamera_pre, raster);
+ Pcamera = interp(Pcamera_pre, Pcamera, ray->time * 2.0f);
+ }
+ else {
+ Transform rastertocamera_post = kernel_data.cam.perspective_motion.post;
+ float3 Pcamera_post =
+ transform_perspective(&rastertocamera_post, raster);
+ Pcamera = interp(Pcamera, Pcamera_post, (ray->time - 0.5f) * 2.0f);
+ }
+ }
+#endif
ray->P = make_float3(0.0f, 0.0f, 0.0f);
ray->D = Pcamera;
diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h
index 46e5d6b2a31..ba8cba1dc83 100644
--- a/intern/cycles/kernel/kernel_types.h
+++ b/intern/cycles/kernel/kernel_types.h
@@ -778,7 +778,7 @@ typedef struct KernelCamera {
/* motion blur */
float shuttertime;
- int have_motion;
+ int have_motion, have_perspective_motion;
/* clipping */
float nearclip;
@@ -796,7 +796,6 @@ typedef struct KernelCamera {
float inv_aperture_ratio;
int is_inside_volume;
- int pad2;
/* more matrices */
Transform screentoworld;
@@ -810,6 +809,11 @@ typedef struct KernelCamera {
Transform worldtocamera;
MotionTransform motion;
+
+ /* Denotes changes in the projective matrix, namely in rastertocamera.
+ * Used for camera zoom motion blur,
+ */
+ PerspectiveMotionTransform perspective_motion;
} KernelCamera;
typedef struct KernelFilm {
diff --git a/intern/cycles/render/camera.cpp b/intern/cycles/render/camera.cpp
index 89505221862..df2a1d348d6 100644
--- a/intern/cycles/render/camera.cpp
+++ b/intern/cycles/render/camera.cpp
@@ -40,6 +40,7 @@ Camera::Camera()
motion.pre = transform_identity();
motion.post = transform_identity();
use_motion = false;
+ use_perspective_motion = false;
aperture_ratio = 1.0f;
@@ -170,6 +171,23 @@ void Camera::update()
dx = transform_direction(&cameratoworld, dx);
dy = transform_direction(&cameratoworld, dy);
+ /* TODO(sergey): Support other types of camera. */
+ if(type == CAMERA_PERSPECTIVE) {
+ /* TODO(sergey): Move to an utility function and de-duplicate with
+ * calculation above.
+ */
+ Transform screentocamera_pre =
+ transform_inverse(transform_perspective(fov_pre,
+ nearclip,
+ farclip));
+ Transform screentocamera_post =
+ transform_inverse(transform_perspective(fov_post,
+ nearclip,
+ farclip));
+ perspective_motion.pre = screentocamera_pre * rastertoscreen;
+ perspective_motion.post = screentocamera_post * rastertoscreen;
+ }
+
need_update = false;
need_device_update = true;
need_flags_update = true;
@@ -205,8 +223,10 @@ void Camera::device_update(Device *device, DeviceScene *dscene, Scene *scene)
/* camera motion */
kcam->have_motion = 0;
+ kcam->have_perspective_motion = 0;
if(need_motion == Scene::MOTION_PASS) {
+ /* TODO(sergey): Support perspective (zoom, fov) motion. */
if(type == CAMERA_PANORAMA) {
if(use_motion) {
kcam->motion.pre = transform_inverse(motion.pre);
@@ -234,6 +254,10 @@ void Camera::device_update(Device *device, DeviceScene *dscene, Scene *scene)
transform_motion_decompose((DecompMotionTransform*)&kcam->motion, &motion, &matrix);
kcam->have_motion = 1;
}
+ if(use_perspective_motion) {
+ kcam->perspective_motion = perspective_motion;
+ kcam->have_perspective_motion = 1;
+ }
}
#endif
diff --git a/intern/cycles/render/camera.h b/intern/cycles/render/camera.h
index 3efbe904e2f..1bedb051112 100644
--- a/intern/cycles/render/camera.h
+++ b/intern/cycles/render/camera.h
@@ -83,7 +83,9 @@ public:
/* motion */
MotionTransform motion;
- bool use_motion;
+ bool use_motion, use_perspective_motion;
+ float fov_pre, fov_post;
+ PerspectiveMotionTransform perspective_motion;
/* computed camera parameters */
Transform screentoworld;
diff --git a/intern/cycles/util/util_transform.h b/intern/cycles/util/util_transform.h
index 0b87db0a379..ba8d04b5c16 100644
--- a/intern/cycles/util/util_transform.h
+++ b/intern/cycles/util/util_transform.h
@@ -55,6 +55,11 @@ typedef struct DecompMotionTransform {
float4 post_x, post_y;
} DecompMotionTransform;
+typedef struct PerspectiveMotionTransform {
+ Transform pre;
+ Transform post;
+} PerspectiveMotionTransform;
+
/* Functions */
ccl_device_inline float3 transform_perspective(const Transform *t, const float3 a)