diff options
author | Brecht Van Lommel <brechtvanlommel@gmail.com> | 2018-03-10 03:36:09 +0300 |
---|---|---|
committer | Brecht Van Lommel <brechtvanlommel@gmail.com> | 2018-03-10 08:27:19 +0300 |
commit | 78c2063685cb6e0d0bcb895cf4eb70686455d596 (patch) | |
tree | 70f7010f9a960f087b3e5b842874a919a4e0860d /intern/cycles/render | |
parent | 267d8923265a284c5d9a462e1d86305d613fcad8 (diff) |
Cycles: support arbitrary number of motion blur steps for cameras.
Diffstat (limited to 'intern/cycles/render')
-rw-r--r-- | intern/cycles/render/camera.cpp | 77 | ||||
-rw-r--r-- | intern/cycles/render/camera.h | 10 | ||||
-rw-r--r-- | intern/cycles/render/object.cpp | 9 | ||||
-rw-r--r-- | intern/cycles/render/scene.cpp | 1 | ||||
-rw-r--r-- | intern/cycles/render/scene.h | 3 | ||||
-rw-r--r-- | intern/cycles/render/session.cpp | 2 |
6 files changed, 77 insertions, 25 deletions
diff --git a/intern/cycles/render/camera.cpp b/intern/cycles/render/camera.cpp index a1c6a279956..38936ffc094 100644 --- a/intern/cycles/render/camera.cpp +++ b/intern/cycles/render/camera.cpp @@ -82,6 +82,7 @@ NODE_DEFINE(Camera) SOCKET_FLOAT(bladesrotation, "Blades Rotation", 0.0f); SOCKET_TRANSFORM(matrix, "Matrix", transform_identity()); + SOCKET_TRANSFORM_ARRAY(motion, "Motion", array<Transform>()); SOCKET_FLOAT(aperture_ratio, "Aperture Ratio", 1.0f); @@ -151,9 +152,6 @@ Camera::Camera() height = 512; resolution = 1; - motion.pre = transform_identity(); - motion.post = transform_identity(); - use_motion = false; use_perspective_motion = false; shutter_curve.resize(RAMP_TABLE_SIZE); @@ -317,15 +315,22 @@ void Camera::update(Scene *scene) kcam->ndctoworld = ndctoworld; /* camera motion */ - kcam->have_motion = 0; + kcam->num_motion_steps = 0; kcam->have_perspective_motion = 0; + kernel_camera_motion.clear(); + + /* Test if any of the transforms are actually different. */ + bool have_motion = false; + for(size_t i = 0; i < motion.size(); i++) { + have_motion = have_motion || motion[i] != matrix; + } if(need_motion == Scene::MOTION_PASS) { /* TODO(sergey): Support perspective (zoom, fov) motion. */ if(type == CAMERA_PANORAMA) { - if(use_motion) { - kcam->motion_pass_pre = transform_inverse(motion.pre); - kcam->motion_pass_post = transform_inverse(motion.post); + if(have_motion) { + kcam->motion_pass_pre = transform_inverse(motion[0]); + kcam->motion_pass_post = transform_inverse(motion[motion.size()-1]); } else { kcam->motion_pass_pre = kcam->worldtocamera; @@ -333,9 +338,9 @@ void Camera::update(Scene *scene) } } else { - if(use_motion) { - kcam->perspective_pre = cameratoraster * transform_inverse(motion.pre); - kcam->perspective_post = cameratoraster * transform_inverse(motion.post); + if(have_motion) { + kcam->perspective_pre = cameratoraster * transform_inverse(motion[0]); + kcam->perspective_post = cameratoraster * transform_inverse(motion[motion.size()-1]); } else { kcam->perspective_pre = worldtoraster; @@ -344,9 +349,10 @@ void Camera::update(Scene *scene) } } else if(need_motion == Scene::MOTION_BLUR) { - if(use_motion) { - transform_motion_decompose(&kcam->motion, &motion, &matrix); - kcam->have_motion = 1; + if(have_motion) { + kernel_camera_motion.resize(motion.size()); + transform_motion_decompose(kernel_camera_motion.data(), motion.data(), motion.size()); + kcam->num_motion_steps = motion.size(); } /* TODO(sergey): Support other types of camera. */ @@ -469,6 +475,16 @@ void Camera::device_update(Device * /* device */, } dscene->data.cam = kernel_camera; + + size_t num_motion_steps = kernel_camera_motion.size(); + if(num_motion_steps) { + DecomposedTransform *camera_motion = dscene->camera_motion.alloc(num_motion_steps); + memcpy(camera_motion, kernel_camera_motion.data(), sizeof(*camera_motion) * num_motion_steps); + dscene->camera_motion.copy_to_device(); + } + else { + dscene->camera_motion.free(); + } } void Camera::device_update_volume(Device * /*device*/, @@ -495,10 +511,11 @@ void Camera::device_update_volume(Device * /*device*/, } void Camera::device_free(Device * /*device*/, - DeviceScene * /*dscene*/, + DeviceScene *dscene, Scene *scene) { scene->lookup_tables->remove_table(&shutter_table_offset); + dscene->camera_motion.free(); } bool Camera::modified(const Camera& cam) @@ -509,7 +526,6 @@ bool Camera::modified(const Camera& cam) bool Camera::motion_modified(const Camera& cam) { return !((motion == cam.motion) && - (use_motion == cam.use_motion) && (use_perspective_motion == cam.use_perspective_motion)); } @@ -706,17 +722,17 @@ float Camera::world_to_raster_size(float3 P) * may be a better way to do this, but calculating differentials from the * point directly ahead seems to produce good enough results. */ #if 0 - float2 dir = direction_to_panorama(&kernel_camera, normalize(D)); + float2 dir = direction_to_panorama(&kernel_camera, kernel_camera_motion.data(), normalize(D)); float3 raster = transform_perspective(&cameratoraster, make_float3(dir.x, dir.y, 0.0f)); ray.t = 1.0f; - camera_sample_panorama(&kernel_camera, raster.x, raster.y, 0.0f, 0.0f, &ray); + camera_sample_panorama(&kernel_camera, kernel_camera_motion.data(), raster.x, raster.y, 0.0f, 0.0f, &ray); if(ray.t == 0.0f) { /* No differentials, just use from directly ahead. */ - camera_sample_panorama(&kernel_camera, 0.5f*width, 0.5f*height, 0.0f, 0.0f, &ray); + camera_sample_panorama(&kernel_camera, kernel_camera_motion.data(), 0.5f*width, 0.5f*height, 0.0f, 0.0f, &ray); } #else - camera_sample_panorama(&kernel_camera, 0.5f*width, 0.5f*height, 0.0f, 0.0f, &ray); + camera_sample_panorama(&kernel_camera, kernel_camera_motion.data(), 0.5f*width, 0.5f*height, 0.0f, 0.0f, &ray); #endif differential_transfer(&ray.dP, ray.dP, ray.D, ray.dD, ray.D, dist); @@ -728,4 +744,27 @@ float Camera::world_to_raster_size(float3 P) return res; } +bool Camera::use_motion() const +{ + return motion.size() > 1; +} + +float Camera::motion_time(int step) const +{ + return (use_motion()) ? 2.0f * step / (motion.size() - 1) - 1.0f : 0.0f; +} + +int Camera::motion_step(float time) const +{ + if(use_motion()) { + for(int step = 0; step < motion.size(); step++) { + if(time == motion_time(step)) { + return step; + } + } + } + + return -1; +} + CCL_NAMESPACE_END diff --git a/intern/cycles/render/camera.h b/intern/cycles/render/camera.h index 8f49a372f24..37d05c01bd9 100644 --- a/intern/cycles/render/camera.h +++ b/intern/cycles/render/camera.h @@ -141,8 +141,8 @@ public: Transform matrix; /* motion */ - MotionTransform motion; - bool use_motion, use_perspective_motion; + array<Transform> motion; + bool use_perspective_motion; float fov_pre, fov_post; /* computed camera parameters */ @@ -176,6 +176,7 @@ public: /* Kernel camera data, copied here for dicing. */ KernelCamera kernel_camera; + array<DecomposedTransform> kernel_camera_motion; /* functions */ Camera(); @@ -199,6 +200,11 @@ public: /* Calculates the width of a pixel at point in world space. */ float world_to_raster_size(float3 P); + /* Motion blur. */ + float motion_time(int step) const; + int motion_step(float time) const; + bool use_motion() const; + private: /* Private utility functions. */ float3 transform_raster_to_world(float raster_x, float raster_y); diff --git a/intern/cycles/render/object.cpp b/intern/cycles/render/object.cpp index 6201775b992..bde340ae928 100644 --- a/intern/cycles/render/object.cpp +++ b/intern/cycles/render/object.cpp @@ -139,9 +139,10 @@ void Object::compute_bounds(bool motion_blur) if(mtfm.post == transform_empty()) { mtfm.post = tfm; } + mtfm.mid = tfm; DecomposedMotionTransform decomp; - transform_motion_decompose(&decomp, &mtfm, &tfm); + transform_motion_decompose(&decomp.pre, &mtfm.pre, 3); bounds = BoundBox::empty; @@ -151,7 +152,7 @@ void Object::compute_bounds(bool motion_blur) for(float t = 0.0f; t < 1.0f; t += (1.0f/128.0f)) { Transform ttfm; - transform_motion_interpolate(&ttfm, &decomp, t); + transform_motion_array_interpolate(&ttfm, &decomp.pre, 3, t); bounds.grow(mbounds.transformed(&ttfm)); } } @@ -422,8 +423,10 @@ void ObjectManager::device_update_object_transform(UpdateObjectTransformState *s if(ob->use_motion) { /* decompose transformations for interpolation. */ DecomposedMotionTransform decomp; + MotionTransform mtfm = ob->motion; + mtfm.mid = tfm; - transform_motion_decompose(&decomp, &ob->motion, &ob->tfm); + transform_motion_decompose(&decomp.pre, &mtfm.pre, 3); kobject.tfm = decomp; flag |= SD_OBJECT_MOTION; state->have_motion = true; diff --git a/intern/cycles/render/scene.cpp b/intern/cycles/render/scene.cpp index e9b9b417e30..6fc6e453aff 100644 --- a/intern/cycles/render/scene.cpp +++ b/intern/cycles/render/scene.cpp @@ -62,6 +62,7 @@ DeviceScene::DeviceScene(Device *device) objects(device, "__objects", MEM_TEXTURE), object_motion_pass(device, "__object_motion_pass", MEM_TEXTURE), object_flag(device, "__object_flag", MEM_TEXTURE), + camera_motion(device, "__camera_motion", MEM_TEXTURE), attributes_map(device, "__attributes_map", MEM_TEXTURE), attributes_float(device, "__attributes_float", MEM_TEXTURE), attributes_float3(device, "__attributes_float3", MEM_TEXTURE), diff --git a/intern/cycles/render/scene.h b/intern/cycles/render/scene.h index aebd84f92d8..74e1df2f1d2 100644 --- a/intern/cycles/render/scene.h +++ b/intern/cycles/render/scene.h @@ -90,6 +90,9 @@ public: device_vector<Transform> object_motion_pass; device_vector<uint> object_flag; + /* cameras */ + device_vector<DecomposedTransform> camera_motion; + /* attributes */ device_vector<uint4> attributes_map; device_vector<float> attributes_float; diff --git a/intern/cycles/render/session.cpp b/intern/cycles/render/session.cpp index e8d9558c38d..5732faf2a36 100644 --- a/intern/cycles/render/session.cpp +++ b/intern/cycles/render/session.cpp @@ -656,7 +656,7 @@ DeviceRequestedFeatures Session::get_requested_device_features() */ requested_features.use_hair = false; requested_features.use_object_motion = false; - requested_features.use_camera_motion = scene->camera->use_motion; + requested_features.use_camera_motion = scene->camera->use_motion(); foreach(Object *object, scene->objects) { Mesh *mesh = object->mesh; if(mesh->num_curves()) { |